diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 2f746eb645076..bd408d260e9c7 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -290,8 +290,7 @@ static inline int hwsim_net_set_netgroup(struct net *net) { struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id); - hwsim_net->netgroup = ida_simple_get(&hwsim_netgroup_ida, - 0, 0, GFP_KERNEL); + hwsim_net->netgroup = ida_alloc(&hwsim_netgroup_ida, GFP_KERNEL); return hwsim_net->netgroup >= 0 ? 0 : -ENOMEM; } @@ -4733,7 +4732,7 @@ static void __net_exit hwsim_exit_net(struct net *net) NULL); } - ida_simple_remove(&hwsim_netgroup_ida, hwsim_net_get_netgroup(net)); + ida_free(&hwsim_netgroup_ida, hwsim_net_get_netgroup(net)); } static struct pernet_operations hwsim_net_ops = { diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c index 8d8378bafd9b0..1ac4684fab251 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c @@ -20,9 +20,11 @@ static const struct ieee80211_txrx_stypes wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = { [NL80211_IFTYPE_STATION] = { - .tx = 0xffff, + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4), .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) }, [NL80211_IFTYPE_AP] = { .tx = 0xffff, @@ -305,6 +307,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, int ret; u32 i; u8 security = WILC_FW_SEC_NO; + enum mfptype mfp_type = WILC_FW_MFP_NONE; enum authtype auth_type = WILC_FW_AUTH_ANY; u32 cipher_group; struct cfg80211_bss *bss; @@ -313,32 +316,9 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, vif->connecting = true; - memset(priv->wep_key, 0, sizeof(priv->wep_key)); - memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len)); - cipher_group = sme->crypto.cipher_group; if (cipher_group != 0) { - if (cipher_group == WLAN_CIPHER_SUITE_WEP40) { - security = WILC_FW_SEC_WEP; - - priv->wep_key_len[sme->key_idx] = sme->key_len; - memcpy(priv->wep_key[sme->key_idx], sme->key, - sme->key_len); - - wilc_set_wep_default_keyid(vif, sme->key_idx); - wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len, - sme->key_idx); - } else if (cipher_group == WLAN_CIPHER_SUITE_WEP104) { - security = WILC_FW_SEC_WEP_EXTENDED; - - priv->wep_key_len[sme->key_idx] = sme->key_len; - memcpy(priv->wep_key[sme->key_idx], sme->key, - sme->key_len); - - wilc_set_wep_default_keyid(vif, sme->key_idx); - wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len, - sme->key_idx); - } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) { + if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) { if (cipher_group == WLAN_CIPHER_SUITE_TKIP) security = WILC_FW_SEC_WPA2_TKIP; else @@ -373,8 +353,14 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, auth_type = WILC_FW_AUTH_OPEN_SYSTEM; break; - case NL80211_AUTHTYPE_SHARED_KEY: - auth_type = WILC_FW_AUTH_SHARED_KEY; + case NL80211_AUTHTYPE_SAE: + auth_type = WILC_FW_AUTH_SAE; + if (sme->ssid_len) { + memcpy(vif->auth.ssid.ssid, sme->ssid, sme->ssid_len); + vif->auth.ssid.ssid_len = sme->ssid_len; + } + vif->auth.key_mgmt_suite = cpu_to_be32(sme->crypto.akm_suites[0]); + ether_addr_copy(vif->auth.bssid, sme->bssid); break; default: @@ -384,6 +370,10 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, if (sme->crypto.n_akm_suites) { if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X) auth_type = WILC_FW_AUTH_IEEE8021; + else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_PSK_SHA256) + auth_type = WILC_FW_AUTH_OPEN_SYSTEM_SHA256; + else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X_SHA256) + auth_type = WILC_FW_AUTH_IEE8021X_SHA256; } if (wfi_drv->usr_scan_req.scan_result) { @@ -427,6 +417,13 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, wfi_drv->conn_info.arg = priv; wfi_drv->conn_info.param = join_params; + if (sme->mfp == NL80211_MFP_OPTIONAL) + mfp_type = WILC_FW_MFP_OPTIONAL; + else if (sme->mfp == NL80211_MFP_REQUIRED) + mfp_type = WILC_FW_MFP_REQUIRED; + + wfi_drv->conn_info.mfp_type = mfp_type; + ret = wilc_set_join_req(vif, bss->bssid, sme->ie, sme->ie_len); if (ret) { netdev_err(dev, "wilc_set_join_req(): Error\n"); @@ -487,14 +484,6 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, return ret; } -static inline void wilc_wfi_cfg_copy_wep_info(struct wilc_priv *priv, - u8 key_index, - struct key_params *params) -{ - priv->wep_key_len[key_index] = params->key_len; - memcpy(priv->wep_key[key_index], params->key, params->key_len); -} - static int wilc_wfi_cfg_allocate_wpa_entry(struct wilc_priv *priv, u8 idx) { if (!priv->wilc_gtk[idx]) { @@ -514,6 +503,18 @@ static int wilc_wfi_cfg_allocate_wpa_entry(struct wilc_priv *priv, u8 idx) return 0; } +static int wilc_wfi_cfg_allocate_wpa_igtk_entry(struct wilc_priv *priv, u8 idx) +{ + idx -= 4; + if (!priv->wilc_igtk[idx]) { + priv->wilc_igtk[idx] = kzalloc(sizeof(*priv->wilc_igtk[idx]), + GFP_KERNEL); + if (!priv->wilc_igtk[idx]) + return -ENOMEM; + } + return 0; +} + static int wilc_wfi_cfg_copy_wpa_info(struct wilc_wfi_key *key_info, struct key_params *params) { @@ -550,35 +551,9 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, u8 op_mode; struct wilc_vif *vif = netdev_priv(netdev); struct wilc_priv *priv = &vif->priv; + struct wilc_wfi_key *key; switch (params->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - if (priv->wdev.iftype == NL80211_IFTYPE_AP) { - wilc_wfi_cfg_copy_wep_info(priv, key_index, params); - - if (params->cipher == WLAN_CIPHER_SUITE_WEP40) - mode = WILC_FW_SEC_WEP; - else - mode = WILC_FW_SEC_WEP_EXTENDED; - - ret = wilc_add_wep_key_bss_ap(vif, params->key, - params->key_len, - key_index, mode, - WILC_FW_AUTH_OPEN_SYSTEM); - break; - } - if (memcmp(params->key, priv->wep_key[key_index], - params->key_len)) { - wilc_wfi_cfg_copy_wep_info(priv, key_index, params); - - ret = wilc_add_wep_key_bss_sta(vif, params->key, - params->key_len, - key_index); - } - - break; - case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: if (priv->wdev.iftype == NL80211_IFTYPE_AP || @@ -640,6 +615,26 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, key_index); break; + case WLAN_CIPHER_SUITE_AES_CMAC: + ret = wilc_wfi_cfg_allocate_wpa_igtk_entry(priv, key_index); + if (ret) + return -ENOMEM; + + key = priv->wilc_igtk[key_index - 4]; + ret = wilc_wfi_cfg_copy_wpa_info(key, params); + if (ret) + return -ENOMEM; + + if (priv->wdev.iftype == NL80211_IFTYPE_AP || + priv->wdev.iftype == NL80211_IFTYPE_P2P_GO) + op_mode = WILC_AP_MODE; + else + op_mode = WILC_STATION_MODE; + + ret = wilc_add_igtk(vif, params->key, keylen, params->seq, + params->seq_len, mac_addr, op_mode, + key_index); + break; default: netdev_err(netdev, "%s: Unsupported cipher\n", __func__); @@ -657,30 +652,34 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev, struct wilc_vif *vif = netdev_priv(netdev); struct wilc_priv *priv = &vif->priv; - if (priv->wilc_gtk[key_index]) { - kfree(priv->wilc_gtk[key_index]->key); - priv->wilc_gtk[key_index]->key = NULL; - kfree(priv->wilc_gtk[key_index]->seq); - priv->wilc_gtk[key_index]->seq = NULL; - - kfree(priv->wilc_gtk[key_index]); - priv->wilc_gtk[key_index] = NULL; - } - - if (priv->wilc_ptk[key_index]) { - kfree(priv->wilc_ptk[key_index]->key); - priv->wilc_ptk[key_index]->key = NULL; - kfree(priv->wilc_ptk[key_index]->seq); - priv->wilc_ptk[key_index]->seq = NULL; - kfree(priv->wilc_ptk[key_index]); - priv->wilc_ptk[key_index] = NULL; - } - - if (key_index <= 3 && priv->wep_key_len[key_index]) { - memset(priv->wep_key[key_index], 0, - priv->wep_key_len[key_index]); - priv->wep_key_len[key_index] = 0; - wilc_remove_wep_key(vif, key_index); + if (!pairwise && (key_index == 4 || key_index == 5)) { + key_index -= 4; + if (priv->wilc_igtk[key_index]) { + kfree(priv->wilc_igtk[key_index]->key); + priv->wilc_igtk[key_index]->key = NULL; + kfree(priv->wilc_igtk[key_index]->seq); + priv->wilc_igtk[key_index]->seq = NULL; + kfree(priv->wilc_igtk[key_index]); + priv->wilc_igtk[key_index] = NULL; + } + } else { + if (priv->wilc_gtk[key_index]) { + kfree(priv->wilc_gtk[key_index]->key); + priv->wilc_gtk[key_index]->key = NULL; + kfree(priv->wilc_gtk[key_index]->seq); + priv->wilc_gtk[key_index]->seq = NULL; + + kfree(priv->wilc_gtk[key_index]); + priv->wilc_gtk[key_index] = NULL; + } + if (priv->wilc_ptk[key_index]) { + kfree(priv->wilc_ptk[key_index]->key); + priv->wilc_ptk[key_index]->key = NULL; + kfree(priv->wilc_ptk[key_index]->seq); + priv->wilc_ptk[key_index]->seq = NULL; + kfree(priv->wilc_ptk[key_index]); + priv->wilc_ptk[key_index] = NULL; + } } return 0; @@ -695,11 +694,20 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, struct key_params key_params; if (!pairwise) { - key_params.key = priv->wilc_gtk[key_index]->key; - key_params.cipher = priv->wilc_gtk[key_index]->cipher; - key_params.key_len = priv->wilc_gtk[key_index]->key_len; - key_params.seq = priv->wilc_gtk[key_index]->seq; - key_params.seq_len = priv->wilc_gtk[key_index]->seq_len; + if (key_index == 4 || key_index == 5) { + key_index -= 4; + key_params.key = priv->wilc_igtk[key_index]->key; + key_params.cipher = priv->wilc_igtk[key_index]->cipher; + key_params.key_len = priv->wilc_igtk[key_index]->key_len; + key_params.seq = priv->wilc_igtk[key_index]->seq; + key_params.seq_len = priv->wilc_igtk[key_index]->seq_len; + } else { + key_params.key = priv->wilc_gtk[key_index]->key; + key_params.cipher = priv->wilc_gtk[key_index]->cipher; + key_params.key_len = priv->wilc_gtk[key_index]->key_len; + key_params.seq = priv->wilc_gtk[key_index]->seq; + key_params.seq_len = priv->wilc_gtk[key_index]->seq_len; + } } else { key_params.key = priv->wilc_ptk[key_index]->key; key_params.cipher = priv->wilc_ptk[key_index]->cipher; @@ -713,14 +721,19 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, return 0; } +/* wiphy_new_nm() will WARNON if not present */ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool unicast, bool multicast) { - struct wilc_vif *vif = netdev_priv(netdev); + return 0; +} - wilc_set_wep_default_keyid(vif, key_index); +static int set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev, + u8 key_index) +{ + struct wilc_vif *vif = netdev_priv(netdev); - return 0; + return wilc_set_default_mgmt_key_index(vif, key_index); } static int get_station(struct wiphy *wiphy, struct net_device *dev, @@ -977,6 +990,18 @@ static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u32 len, u8 sta_ch) } } +bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size) +{ + struct wilc *wl = vif->wilc; + struct wilc_priv *priv = &vif->priv; + int freq, ret; + + freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ); + ret = cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0); + + return ret; +} + void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size) { struct wilc *wl = vif->wilc; @@ -1162,8 +1187,14 @@ static int mgmt_tx(struct wiphy *wiphy, goto out_txq_add_pkt; } - if (!ieee80211_is_public_action((struct ieee80211_hdr *)buf, len)) + if (!ieee80211_is_public_action((struct ieee80211_hdr *)buf, len)) { + if (chan) + wilc_set_mac_chnl_num(vif, chan->hw_value); + else + wilc_set_mac_chnl_num(vif, vif->wilc->op_ch); + goto out_set_timeout; + } d = (struct wilc_p2p_pub_act_frame *)(&mgmt->u.action); if (d->oui_type != WLAN_OUI_TYPE_WFA_P2P || @@ -1230,6 +1261,7 @@ void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy, struct wilc_vif *vif = netdev_priv(wdev->netdev); u32 presp_bit = BIT(IEEE80211_STYPE_PROBE_REQ >> 4); u32 action_bit = BIT(IEEE80211_STYPE_ACTION >> 4); + u32 pauth_bit = BIT(IEEE80211_STYPE_AUTH >> 4); if (wl->initialized) { bool prev = vif->mgmt_reg_stypes & presp_bit; @@ -1243,10 +1275,26 @@ void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy, if (now != prev) wilc_frame_register(vif, IEEE80211_STYPE_ACTION, now); + + prev = vif->mgmt_reg_stypes & pauth_bit; + now = upd->interface_stypes & pauth_bit; + if (now != prev) + wilc_frame_register(vif, IEEE80211_STYPE_AUTH, now); } vif->mgmt_reg_stypes = - upd->interface_stypes & (presp_bit | action_bit); + upd->interface_stypes & (presp_bit | action_bit | pauth_bit); +} + +static int external_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_external_auth_params *auth) +{ + struct wilc_vif *vif = netdev_priv(dev); + + if (auth->status == WLAN_STATUS_SUCCESS) + wilc_set_external_auth_param(vif, auth); + + return 0; } static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev, @@ -1647,6 +1695,7 @@ static const struct cfg80211_ops wilc_cfg80211_ops = { .del_key = del_key, .get_key = get_key, .set_default_key = set_default_key, + .set_default_mgmt_key = set_default_mgmt_key, .add_virtual_intf = add_virtual_intf, .del_virtual_intf = del_virtual_intf, .change_virtual_intf = change_virtual_intf, @@ -1662,6 +1711,7 @@ static const struct cfg80211_ops wilc_cfg80211_ops = { .change_bss = change_bss, .set_wiphy_params = set_wiphy_params, + .external_auth = external_auth, .set_pmksa = set_pmksa, .del_pmksa = del_pmksa, .flush_pmksa = flush_pmksa, @@ -1804,7 +1854,7 @@ struct wilc *wilc_create_wiphy(struct device *dev) BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT); wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - + wiphy->features |= NL80211_FEATURE_SAE; set_wiphy_dev(wiphy, dev); wl->wiphy = wiphy; ret = wiphy_register(wiphy); diff --git a/drivers/net/wireless/microchip/wilc1000/fw.h b/drivers/net/wireless/microchip/wilc1000/fw.h index 1114530d03e4f..5c5cac4aab029 100644 --- a/drivers/net/wireless/microchip/wilc1000/fw.h +++ b/drivers/net/wireless/microchip/wilc1000/fw.h @@ -41,21 +41,23 @@ struct wilc_drv_handler { u8 mode; } __packed; -struct wilc_wep_key { - u8 index; +struct wilc_sta_wpa_ptk { + u8 mac_addr[ETH_ALEN]; u8 key_len; u8 key[]; } __packed; -struct wilc_sta_wpa_ptk { +struct wilc_ap_wpa_ptk { u8 mac_addr[ETH_ALEN]; + u8 index; u8 key_len; u8 key[]; } __packed; -struct wilc_ap_wpa_ptk { - u8 mac_addr[ETH_ALEN]; +struct wilc_wpa_igtk { u8 index; + u8 pn_len; + u8 pn[6]; u8 key_len; u8 key[]; } __packed; @@ -116,4 +118,13 @@ struct wilc_join_bss_param { struct wilc_noa_opp_enable opp_en; }; } __packed; + +struct wilc_external_auth_param { + u8 action; + u8 bssid[ETH_ALEN]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + __le32 key_mgmt_suites; + __le16 status; +} __packed; #endif diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c index 71b44cfe0dfca..4038a254465f0 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.c +++ b/drivers/net/wireless/microchip/wilc1000/hif.c @@ -271,12 +271,19 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, static int wilc_send_connect_wid(struct wilc_vif *vif) { int result = 0; - struct wid wid_list[4]; + struct wid wid_list[5]; u32 wid_cnt = 0; struct host_if_drv *hif_drv = vif->hif_drv; struct wilc_conn_info *conn_attr = &hif_drv->conn_info; struct wilc_join_bss_param *bss_param = conn_attr->param; + + wid_list[wid_cnt].id = WID_SET_MFP; + wid_list[wid_cnt].type = WID_CHAR; + wid_list[wid_cnt].size = sizeof(char); + wid_list[wid_cnt].val = (s8 *)&conn_attr->mfp_type; + wid_cnt++; + wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE; wid_list[wid_cnt].type = WID_BIN_DATA; wid_list[wid_cnt].val = conn_attr->req_ies; @@ -306,7 +313,10 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) netdev_err(vif->ndev, "failed to send config packet\n"); goto error; } else { - hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; + if (conn_attr->auth_type == WILC_FW_AUTH_SAE) + hif_drv->hif_state = HOST_IF_EXTERNAL_AUTH; + else + hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; } return 0; @@ -665,7 +675,12 @@ static void handle_rcvd_gnrl_async_info(struct work_struct *work) goto free_msg; } - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { + + if (hif_drv->hif_state == HOST_IF_EXTERNAL_AUTH) { + cfg80211_external_auth_request(vif->ndev, &vif->auth, + GFP_KERNEL); + hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; + } else if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { host_int_parse_assoc_resp_info(vif, mac_info->status); } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) { if (hif_drv->hif_state == HOST_IF_CONNECTED) { @@ -710,7 +725,8 @@ int wilc_disconnect(struct wilc_vif *vif) } if (conn_info->conn_result) { - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) + if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || + hif_drv->hif_state == HOST_IF_EXTERNAL_AUTH) del_timer(&hif_drv->connect_timer); conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0, @@ -986,6 +1002,31 @@ void wilc_set_wowlan_trigger(struct wilc_vif *vif, bool enabled) pr_err("Failed to send wowlan trigger config packet\n"); } +int wilc_set_external_auth_param(struct wilc_vif *vif, + struct cfg80211_external_auth_params *auth) +{ + int ret; + struct wid wid; + struct wilc_external_auth_param *param; + + wid.id = WID_EXTERNAL_AUTH_PARAM; + wid.type = WID_BIN_DATA; + wid.size = sizeof(*param); + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) + return -EINVAL; + + wid.val = (u8 *)param; + param->action = auth->action; + ether_addr_copy(param->bssid, auth->bssid); + memcpy(param->ssid, auth->ssid.ssid, auth->ssid.ssid_len); + param->ssid_len = auth->ssid.ssid_len; + ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); + + kfree(param); + return ret; +} + static void handle_scan_timer(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); @@ -1038,108 +1079,6 @@ static void timer_connect_cb(struct timer_list *t) kfree(msg); } -int wilc_remove_wep_key(struct wilc_vif *vif, u8 index) -{ - struct wid wid; - int result; - - wid.id = WID_REMOVE_WEP_KEY; - wid.type = WID_STR; - wid.size = sizeof(char); - wid.val = &index; - - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); - if (result) - netdev_err(vif->ndev, - "Failed to send remove wep key config packet\n"); - return result; -} - -int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index) -{ - struct wid wid; - int result; - - wid.id = WID_KEY_ID; - wid.type = WID_CHAR; - wid.size = sizeof(char); - wid.val = &index; - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); - if (result) - netdev_err(vif->ndev, - "Failed to send wep default key config packet\n"); - - return result; -} - -int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, - u8 index) -{ - struct wid wid; - int result; - struct wilc_wep_key *wep_key; - - wid.id = WID_ADD_WEP_KEY; - wid.type = WID_STR; - wid.size = sizeof(*wep_key) + len; - wep_key = kzalloc(wid.size, GFP_KERNEL); - if (!wep_key) - return -ENOMEM; - - wid.val = (u8 *)wep_key; - - wep_key->index = index; - wep_key->key_len = len; - memcpy(wep_key->key, key, len); - - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); - if (result) - netdev_err(vif->ndev, - "Failed to add wep key config packet\n"); - - kfree(wep_key); - return result; -} - -int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, - u8 index, u8 mode, enum authtype auth_type) -{ - struct wid wid_list[3]; - int result; - struct wilc_wep_key *wep_key; - - wid_list[0].id = WID_11I_MODE; - wid_list[0].type = WID_CHAR; - wid_list[0].size = sizeof(char); - wid_list[0].val = &mode; - - wid_list[1].id = WID_AUTH_TYPE; - wid_list[1].type = WID_CHAR; - wid_list[1].size = sizeof(char); - wid_list[1].val = (s8 *)&auth_type; - - wid_list[2].id = WID_WEP_KEY_VALUE; - wid_list[2].type = WID_STR; - wid_list[2].size = sizeof(*wep_key) + len; - wep_key = kzalloc(wid_list[2].size, GFP_KERNEL); - if (!wep_key) - return -ENOMEM; - - wid_list[2].val = (u8 *)wep_key; - - wep_key->index = index; - wep_key->key_len = len; - memcpy(wep_key->key, key, len); - result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, - ARRAY_SIZE(wid_list)); - if (result) - netdev_err(vif->ndev, - "Failed to add wep ap key config packet\n"); - - kfree(wep_key); - return result; -} - int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode, u8 index) @@ -1211,6 +1150,36 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, return result; } +int wilc_add_igtk(struct wilc_vif *vif, const u8 *igtk, u8 igtk_key_len, + const u8 *pn, u8 pn_len, const u8 *mac_addr, u8 mode, u8 index) +{ + int result = 0; + u8 t_key_len = igtk_key_len; + struct wid wid; + struct wilc_wpa_igtk *key_buf; + + key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL); + if (!key_buf) + return -ENOMEM; + + key_buf->index = index; + + memcpy(&key_buf->pn[0], pn, pn_len); + key_buf->pn_len = pn_len; + + memcpy(&key_buf->key[0], igtk, igtk_key_len); + key_buf->key_len = t_key_len; + + wid.id = WID_ADD_IGTK; + wid.type = WID_STR; + wid.size = sizeof(*key_buf) + t_key_len; + wid.val = (s8 *)key_buf; + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); + kfree(key_buf); + + return result; +} + int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 index, u32 key_rsc_len, const u8 *key_rsc, const u8 *rx_mic, const u8 *tx_mic, u8 mode, @@ -1749,6 +1718,10 @@ void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX; break; + case IEEE80211_STYPE_AUTH: + reg_frame.reg_id = WILC_FW_AUTH_REQ_IDX; + break; + default: break; } @@ -1996,3 +1969,20 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power) return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1); } + +int wilc_set_default_mgmt_key_index(struct wilc_vif *vif, u8 index) +{ + struct wid wid; + int result; + + wid.id = WID_DEFAULT_MGMT_KEY_ID; + wid.type = WID_CHAR; + wid.size = sizeof(char); + wid.val = &index; + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); + if (result) + netdev_err(vif->ndev, + "Failed to send default mgmt key index\n"); + + return result; +} diff --git a/drivers/net/wireless/microchip/wilc1000/hif.h b/drivers/net/wireless/microchip/wilc1000/hif.h index 77616fc77575c..d8dd94dcfe149 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.h +++ b/drivers/net/wireless/microchip/wilc1000/hif.h @@ -47,6 +47,7 @@ enum host_if_state { HOST_IF_WAITING_CONN_RESP = 3, HOST_IF_CONNECTED = 4, HOST_IF_P2P_LISTEN = 5, + HOST_IF_EXTERNAL_AUTH = 6, HOST_IF_FORCE_32BIT = 0xFFFFFFFF }; @@ -107,6 +108,7 @@ struct wilc_conn_info { u8 bssid[ETH_ALEN]; u8 security; enum authtype auth_type; + enum mfptype mfp_type; u8 ch; u8 *req_ies; size_t req_ies_len; @@ -151,15 +153,12 @@ struct host_if_drv { }; struct wilc_vif; -int wilc_remove_wep_key(struct wilc_vif *vif, u8 index); -int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index); -int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, - u8 index); -int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, - u8 index, u8 mode, enum authtype auth_type); int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode, u8 index); +int wilc_add_igtk(struct wilc_vif *vif, const u8 *igtk, u8 igtk_key_len, + const u8 *pn, u8 pn_len, const u8 *mac_addr, u8 mode, + u8 index); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val); int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, @@ -208,9 +207,12 @@ int wilc_get_vif_idx(struct wilc_vif *vif); int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power); int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); void wilc_set_wowlan_trigger(struct wilc_vif *vif, bool enabled); +int wilc_set_external_auth_param(struct wilc_vif *vif, + struct cfg80211_external_auth_params *param); void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length); void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length); void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length); void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, struct cfg80211_crypto_settings *crypto); +int wilc_set_default_mgmt_key_index(struct wilc_vif *vif, u8 index); #endif diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c index 3c292e3464c25..fcc4e61592ee1 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.c +++ b/drivers/net/wireless/microchip/wilc1000/netdev.c @@ -835,15 +835,24 @@ void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, } } -void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size) +void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size, bool is_auth) { int srcu_idx; struct wilc_vif *vif; srcu_idx = srcu_read_lock(&wilc->srcu); list_for_each_entry_rcu(vif, &wilc->vif_list, list) { + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buff; u16 type = le16_to_cpup((__le16 *)buff); u32 type_bit = BIT(type >> 4); + u32 auth_bit = BIT(IEEE80211_STYPE_AUTH >> 4); + + if ((vif->mgmt_reg_stypes & auth_bit && + ieee80211_is_auth(mgmt->frame_control)) && + vif->iftype == WILC_STATION_MODE && is_auth) { + wilc_wfi_mgmt_frame_rx(vif, buff, size); + break; + } if (vif->priv.p2p_listen_state && vif->mgmt_reg_stypes & type_bit) diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.h b/drivers/net/wireless/microchip/wilc1000/netdev.h index a067274c20144..822e65d00f538 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.h +++ b/drivers/net/wireless/microchip/wilc1000/netdev.h @@ -45,12 +45,6 @@ struct wilc_wfi_key { u32 cipher; }; -struct wilc_wfi_wep_key { - u8 *key; - u8 key_len; - u8 key_idx; -}; - struct sta_info { u8 sta_associated_bss[WILC_MAX_NUM_STA][ETH_ALEN]; }; @@ -63,8 +57,6 @@ struct wilc_wfi_p2p_listen_params { }; static const u32 wilc_cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, WLAN_CIPHER_SUITE_AES_CMAC @@ -132,13 +124,12 @@ struct wilc_priv { struct net_device *dev; struct host_if_drv *hif_drv; struct wilc_pmkid_attr pmkid_list; - u8 wep_key[4][WLAN_KEY_LEN_WEP104]; - u8 wep_key_len[4]; /* The real interface that the monitor is on */ struct net_device *real_ndev; struct wilc_wfi_key *wilc_gtk[WILC_MAX_NUM_STA]; struct wilc_wfi_key *wilc_ptk[WILC_MAX_NUM_STA]; + struct wilc_wfi_key *wilc_igtk[2]; u8 wilc_groupkey; /* mutexes */ @@ -195,6 +186,7 @@ struct wilc_vif { struct wilc_priv priv; struct list_head list; struct cfg80211_bss *bss; + struct cfg80211_external_auth_params auth; }; struct wilc_tx_queue_status { @@ -288,7 +280,7 @@ struct wilc_wfi_mon_priv { void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); void wilc_mac_indicate(struct wilc *wilc); void wilc_netdev_cleanup(struct wilc *wilc); -void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); +void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size, bool is_auth); void wilc_wlan_set_bssid(struct net_device *wilc_netdev, const u8 *bssid, u8 mode); struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name, diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index 18420e954402f..2ae8dd3411aca 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -191,11 +191,11 @@ static void wilc_wlan_power(struct wilc *wilc, bool on) /* assert ENABLE: */ gpiod_set_value(gpios->enable, 1); mdelay(5); - /* deassert RESET: */ - gpiod_set_value(gpios->reset, 0); - } else { /* assert RESET: */ gpiod_set_value(gpios->reset, 1); + } else { + /* deassert RESET: */ + gpiod_set_value(gpios->reset, 0); /* deassert ENABLE: */ gpiod_set_value(gpios->enable, 0); } diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index 48441f0389ca1..f3f504d12873e 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -968,7 +968,8 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size) if (pkt_offset & IS_MANAGMEMENT) { buff_ptr += HOST_HDR_OFFSET; - wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len); + wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len, + pkt_offset & IS_MGMT_AUTH_PKT); } else { if (!is_cfg_packet) { wilc_frmw_to_host(wilc, buff_ptr, pkt_len, diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h index eb7978166d73e..b45e72789a0e0 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan.h @@ -305,6 +305,7 @@ #define IS_MANAGMEMENT 0x100 #define IS_MANAGMEMENT_CALLBACK 0x080 #define IS_MGMT_STATUS_SUCCES 0x040 +#define IS_MGMT_AUTH_PKT 0x010 #define WILC_WID_TYPE GENMASK(15, 12) #define WILC_VMM_ENTRY_FULL_RETRY 1 @@ -423,6 +424,7 @@ int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc); netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size); +bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size); void host_wakeup_notify(struct wilc *wilc); void host_sleep_notify(struct wilc *wilc); void chip_allow_sleep(struct wilc *wilc); diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_if.h b/drivers/net/wireless/microchip/wilc1000/wlan_if.h index 6eb7eb4ac2944..df2f5a63bdf6f 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan_if.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan_if.h @@ -85,7 +85,16 @@ enum authtype { WILC_FW_AUTH_OPEN_SYSTEM = 1, WILC_FW_AUTH_SHARED_KEY = 2, WILC_FW_AUTH_ANY = 3, - WILC_FW_AUTH_IEEE8021 = 5 + WILC_FW_AUTH_IEEE8021 = 5, + WILC_FW_AUTH_SAE = 7, + WILC_FW_AUTH_IEE8021X_SHA256 = 9, + WILC_FW_AUTH_OPEN_SYSTEM_SHA256 = 13 +}; + +enum mfptype { + WILC_FW_MFP_NONE = 0x0, + WILC_FW_MFP_OPTIONAL = 0x1, + WILC_FW_MFP_REQUIRED = 0x2 }; enum site_survey { @@ -176,7 +185,8 @@ enum { enum { WILC_FW_ACTION_FRM_IDX = 0, - WILC_FW_PROBE_REQ_IDX = 1 + WILC_FW_PROBE_REQ_IDX = 1, + WILC_FW_AUTH_REQ_IDX = 2 }; enum wid_type { @@ -657,6 +667,9 @@ enum { WID_LOG_TERMINAL_SWITCH = 0x00CD, WID_TX_POWER = 0x00CE, WID_WOWLAN_TRIGGER = 0X00CF, + WID_SET_MFP = 0x00D0, + + WID_DEFAULT_MGMT_KEY_ID = 0x00D2, /* EMAC Short WID list */ /* RTS Threshold */ /* @@ -746,6 +759,7 @@ enum { WID_REMOVE_KEY = 0x301E, WID_ASSOC_REQ_INFO = 0x301F, WID_ASSOC_RES_INFO = 0x3020, + WID_ADD_IGTK = 0x3022, WID_MANUFACTURER = 0x3026, /* Added for CAPI tool */ WID_MODEL_NAME = 0x3027, /* Added for CAPI tool */ WID_MODEL_NUM = 0x3028, /* Added for CAPI tool */ @@ -789,7 +803,7 @@ enum { WID_ADD_BEACON = 0x408a, WID_SETUP_MULTICAST_FILTER = 0x408b, - + WID_EXTERNAL_AUTH_PARAM = 0x408d, /* Miscellaneous WIDs */ WID_ALL = 0x7FFE, WID_MAX = 0xFFFF diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 87e98ab068ed7..1f57a0055bbd8 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1643,38 +1643,34 @@ static void authenticate_timeout(struct timer_list *t) /*===========================================================================*/ static int parse_addr(char *in_str, UCHAR *out) { + int i, k; int len; - int i, j, k; - int status; if (in_str == NULL) return 0; - if ((len = strlen(in_str)) < 2) + len = strnlen(in_str, ADDRLEN * 2 + 1) - 1; + if (len < 1) return 0; memset(out, 0, ADDRLEN); - status = 1; - j = len - 1; - if (j > 12) - j = 12; i = 5; - while (j > 0) { - if ((k = hex_to_bin(in_str[j--])) != -1) + while (len > 0) { + if ((k = hex_to_bin(in_str[len--])) != -1) out[i] = k; else return 0; - if (j == 0) + if (len == 0) break; - if ((k = hex_to_bin(in_str[j--])) != -1) + if ((k = hex_to_bin(in_str[len--])) != -1) out[i] += k << 4; else return 0; if (!i--) break; } - return status; + return 1; } /*===========================================================================*/ diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c index 901cdfe3723cf..0b1bc04cb6adb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/debug.c +++ b/drivers/net/wireless/realtek/rtlwifi/debug.c @@ -329,8 +329,8 @@ static ssize_t rtl_debugfs_set_write_h2c(struct file *filp, tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count); - if (!buffer || copy_from_user(tmp, buffer, tmp_len)) - return count; + if (copy_from_user(tmp, buffer, tmp_len)) + return -EFAULT; tmp[tmp_len] = '\0'; @@ -340,8 +340,8 @@ static ssize_t rtl_debugfs_set_write_h2c(struct file *filp, &h2c_data[4], &h2c_data[5], &h2c_data[6], &h2c_data[7]); - if (h2c_len <= 0) - return count; + if (h2c_len == 0) + return -EINVAL; for (i = 0; i < h2c_len; i++) h2c_data_packed[i] = (u8)h2c_data[i]; diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c index 1a52ff585fbc7..7cde6bcf253b4 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.c +++ b/drivers/net/wireless/realtek/rtw88/debug.c @@ -269,11 +269,7 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v) for (i = 0 ; i < buf_size ; i += 8) { if (i % page_size == 0) seq_printf(m, "PAGE %d\n", (i + offset) / page_size); - seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", - *(buf + i), *(buf + i + 1), - *(buf + i + 2), *(buf + i + 3), - *(buf + i + 4), *(buf + i + 5), - *(buf + i + 6), *(buf + i + 7)); + seq_printf(m, "%8ph\n", buf + i); } vfree(buf); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index efabd5b1bf5b6..a44b1810165d0 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1383,9 +1383,12 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, bool hw_scan) { - struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + struct rtw_vif *rtwvif = vif ? (struct rtw_vif *)vif->drv_priv : NULL; u32 config = 0; + if (!rtwvif) + return; + clear_bit(RTW_FLAG_SCANNING, rtwdev->flags); clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 93cce44df5318..993bd6b1d723e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -2701,7 +2701,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = { {0x953, BIT(1), RTW_REG_DOMAIN_MAC8}, }; -struct rtw_chip_info rtw8723d_hw_spec = { +const struct rtw_chip_info rtw8723d_hw_spec = { .ops = &rtw8723d_ops, .id = RTW_CHIP_TYPE_8723D, .fw_name = "rtw88/rtw8723d_fw.bin", diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index 41d35174a5425..4641f6e047b41 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -72,6 +72,8 @@ struct rtw8723d_efuse { struct rtw8723de_efuse e; }; +extern const struct rtw_chip_info rtw8723d_hw_spec; + /* phy status page0 */ #define GET_PHY_STAT_P0_PWDB(phy_stat) \ le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8)) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.c b/drivers/net/wireless/realtek/rtw88/rtw8723de.c index 2dd689441e8dc..abbaafa328513 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723de.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723de.c @@ -5,7 +5,7 @@ #include #include #include "pci.h" -#include "rtw8723de.h" +#include "rtw8723d.h" static const struct pci_device_id rtw_8723de_id_table[] = { { diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.h b/drivers/net/wireless/realtek/rtw88/rtw8723de.h deleted file mode 100644 index 2b4894846a07f..0000000000000 --- a/drivers/net/wireless/realtek/rtw88/rtw8723de.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2018-2019 Realtek Corporation - */ - -#ifndef __RTW_8723DE_H_ -#define __RTW_8723DE_H_ - -extern struct rtw_chip_info rtw8723d_hw_spec; - -#endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index ffee39ea5df69..42841f5d502c2 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -1877,7 +1877,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = { {0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, }; -struct rtw_chip_info rtw8821c_hw_spec = { +const struct rtw_chip_info rtw8821c_hw_spec = { .ops = &rtw8821c_ops, .id = RTW_CHIP_TYPE_8821C, .fw_name = "rtw88/rtw8821c_fw.bin", diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h index d9fbddd7b0f35..2698801fc35d5 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h @@ -84,6 +84,8 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) rtw_write32_mask(rtwdev, addr + 0x200, mask, data); } +extern const struct rtw_chip_info rtw8821c_hw_spec; + #define rtw_write32s_mask(rtwdev, addr, mask, data) \ do { \ BUILD_BUG_ON((addr) < 0xC00 || (addr) >= 0xD00); \ diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c index 56d22f9de9042..f3d971feda047 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c @@ -5,7 +5,7 @@ #include #include #include "pci.h" -#include "rtw8821ce.h" +#include "rtw8821c.h" static const struct pci_device_id rtw_8821ce_id_table[] = { { diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821ce.h b/drivers/net/wireless/realtek/rtw88/rtw8821ce.h deleted file mode 100644 index 54142acca5344..0000000000000 --- a/drivers/net/wireless/realtek/rtw88/rtw8821ce.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2018-2019 Realtek Corporation - */ - -#ifndef __RTW_8821CE_H_ -#define __RTW_8821CE_H_ - -extern struct rtw_chip_info rtw8821c_hw_spec; - -#endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index dccd722b8e624..321848870561e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -2497,7 +2497,7 @@ static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = { [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0}, }; -struct rtw_chip_info rtw8822b_hw_spec = { +const struct rtw_chip_info rtw8822b_hw_spec = { .ops = &rtw8822b_ops, .id = RTW_CHIP_TYPE_8822B, .fw_name = "rtw88/rtw8822b_fw.bin", diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.h b/drivers/net/wireless/realtek/rtw88/rtw8822b.h index 3fff8b881854b..01d3644e0c946 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h @@ -187,4 +187,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) #define REG_ANTWT 0x1904 #define REG_IQKFAILMSK 0x1bf0 +extern const struct rtw_chip_info rtw8822b_hw_spec; + #endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822be.c b/drivers/net/wireless/realtek/rtw88/rtw8822be.c index 62ee7e62cac02..4994950776cd9 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822be.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822be.c @@ -5,7 +5,7 @@ #include #include #include "pci.h" -#include "rtw8822be.h" +#include "rtw8822b.h" static const struct pci_device_id rtw_8822be_id_table[] = { { diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822be.h b/drivers/net/wireless/realtek/rtw88/rtw8822be.h deleted file mode 100644 index 6668460d664da..0000000000000 --- a/drivers/net/wireless/realtek/rtw88/rtw8822be.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2018-2019 Realtek Corporation - */ - -#ifndef __RTW_8822BE_H_ -#define __RTW_8822BE_H_ - -extern struct rtw_chip_info rtw8822b_hw_spec; - -#endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index c043b5c520b9a..09f9e4adcf349 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -5310,7 +5310,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822c[] = { {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, }; -struct rtw_chip_info rtw8822c_hw_spec = { +const struct rtw_chip_info rtw8822c_hw_spec = { .ops = &rtw8822c_ops, .id = RTW_CHIP_TYPE_8822C, .fw_name = "rtw88/rtw8822c_fw.bin", diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h index 8201955e1f217..479d5d769c520 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h @@ -118,6 +118,8 @@ enum rtw8822c_dpk_one_shot_action { void rtw8822c_parse_tbl_dpk(struct rtw_dev *rtwdev, const struct rtw_table *tbl); +extern const struct rtw_chip_info rtw8822c_hw_spec; + #define RTW_DECL_TABLE_DPK(name) \ const struct rtw_table name ## _tbl = { \ .data = name, \ diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c index 3845b1333dc39..e26c6bc829363 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c @@ -5,7 +5,7 @@ #include #include #include "pci.h" -#include "rtw8822ce.h" +#include "rtw8822c.h" static const struct pci_device_id rtw_8822ce_id_table[] = { { diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.h b/drivers/net/wireless/realtek/rtw88/rtw8822ce.h deleted file mode 100644 index fee32d7a45047..0000000000000 --- a/drivers/net/wireless/realtek/rtw88/rtw8822ce.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright(c) 2018-2019 Realtek Corporation - */ - -#ifndef __RTW_8822CE_H_ -#define __RTW_8822CE_H_ - -extern struct rtw_chip_info rtw8822c_hw_spec; - -#endif diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c index 8a26adeb23fb2..db3c55f0ccd0d 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.c +++ b/drivers/net/wireless/realtek/rtw89/cam.c @@ -602,11 +602,18 @@ int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; u8 bss_color = vif->bss_conf.he_bss_color.color; + u8 bss_mask; + + if (vif->bss_conf.nontransmitted) + bss_mask = RTW89_BSSID_MATCH_5_BYTES; + else + bss_mask = RTW89_BSSID_MATCH_ALL; FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx); FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset); FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len); FWCMD_SET_ADDR_BSSID_VALID(cmd, bssid_cam->valid); + FWCMD_SET_ADDR_BSSID_MASK(cmd, bss_mask); FWCMD_SET_ADDR_BSSID_BB_SEL(cmd, bssid_cam->phy_idx); FWCMD_SET_ADDR_BSSID_BSS_COLOR(cmd, bss_color); diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h index a3931d3e40d26..74a6c4748d64f 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.h +++ b/drivers/net/wireless/realtek/rtw89/cam.h @@ -9,6 +9,9 @@ #define RTW89_SEC_CAM_LEN 20 +#define RTW89_BSSID_MATCH_ALL GENMASK(5, 0) +#define RTW89_BSSID_MATCH_5_BYTES GENMASK(4, 0) + static inline void FWCMD_SET_ADDR_IDX(void *cmd, u32 value) { le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(7, 0)); @@ -309,6 +312,11 @@ static inline void FWCMD_SET_ADDR_BSSID_BB_SEL(void *cmd, u32 value) le32p_replace_bits((__le32 *)(cmd) + 13, value, BIT(1)); } +static inline void FWCMD_SET_ADDR_BSSID_MASK(void *cmd, u32 value) +{ + le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(7, 2)); +} + static inline void FWCMD_SET_ADDR_BSSID_BSS_COLOR(void *cmd, u32 value) { le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(13, 8)); diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index a6a90572e74bf..d2f2a3d65ef6f 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -1343,6 +1343,47 @@ struct rtw89_vif_rx_stats_iter_data { const u8 *bssid; }; +static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct sk_buff *skb) +{ + struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data; + u8 *pos, *end, type; + u16 aid; + + if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) || + rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || + rtwvif->net_type == RTW89_NET_TYPE_NO_LINK) + return; + + type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK); + if (type != IEEE80211_TRIGGER_TYPE_BASIC) + return; + + end = (u8 *)tf + skb->len; + pos = tf->variable; + + while (end - pos >= RTW89_TF_BASIC_USER_INFO_SZ) { + aid = RTW89_GET_TF_USER_INFO_AID12(pos); + rtw89_debug(rtwdev, RTW89_DBG_TXRX, + "[TF] aid: %d, ul_mcs: %d, rua: %d\n", + aid, RTW89_GET_TF_USER_INFO_UL_MCS(pos), + RTW89_GET_TF_USER_INFO_RUA(pos)); + + if (aid == RTW89_TF_PAD) + break; + + if (aid == vif->bss_conf.aid) { + rtwvif->stats.rx_tf_acc++; + rtwdev->stats.rx_tf_acc++; + break; + } + + pos += RTW89_TF_BASIC_USER_INFO_SZ; + } +} + static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { @@ -1355,6 +1396,11 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; const u8 *bssid = iter_data->bssid; + if (ieee80211_is_trigger(hdr->frame_control)) { + rtw89_stats_trigger_frame(rtwdev, vif, skb); + return; + } + if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) return; @@ -1608,7 +1654,7 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, if (rtwdev->scanning && RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { - u8 chan = hal->current_channel; + u8 chan = hal->current_primary_channel; u8 band = hal->current_band_type; enum nl80211_band nl_band; @@ -2023,6 +2069,8 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, stats->rx_unicast = 0; stats->tx_cnt = 0; stats->rx_cnt = 0; + stats->rx_tf_periodic = stats->rx_tf_acc; + stats->rx_tf_acc = 0; if (tx_tfc_lv != stats->tx_tfc_lv || rx_tfc_lv != stats->rx_tfc_lv) return true; @@ -2875,7 +2923,10 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, bool hw_scan) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL; + + if (!rtwvif) + return; ether_addr_copy(rtwvif->mac_addr, vif->addr); rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); @@ -3008,6 +3059,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index e8a77225a90ff..239d47d0ec6d6 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -55,6 +55,16 @@ enum htc_om_channel_width { #define RTW89_HTC_MASK_HTC_OM_DL_MU_MIMO_RR BIT(16) #define RTW89_HTC_MASK_HTC_OM_UL_MU_DATA_DIS BIT(17) +#define RTW89_TF_PAD GENMASK(11, 0) +#define RTW89_TF_BASIC_USER_INFO_SZ 6 + +#define RTW89_GET_TF_USER_INFO_AID12(data) \ + le32_get_bits(*((const __le32 *)(data)), GENMASK(11, 0)) +#define RTW89_GET_TF_USER_INFO_RUA(data) \ + le32_get_bits(*((const __le32 *)(data)), GENMASK(19, 12)) +#define RTW89_GET_TF_USER_INFO_UL_MCS(data) \ + le32_get_bits(*((const __le32 *)(data)), GENMASK(24, 21)) + enum rtw89_subband { RTW89_CH_2G = 0, RTW89_CH_5G_BAND_1 = 1, @@ -943,6 +953,10 @@ struct rtw89_traffic_stats { u32 rx_throughput; u32 tx_throughput_raw; u32 rx_throughput_raw; + + u32 rx_tf_acc; + u32 rx_tf_periodic; + enum rtw89_tfc_lv tx_tfc_lv; enum rtw89_tfc_lv rx_tfc_lv; struct ewma_tp tx_ewma_tp; @@ -2550,9 +2564,24 @@ enum rtw89_sar_sources { RTW89_SAR_SOURCE_NR, }; +enum rtw89_sar_subband { + RTW89_SAR_2GHZ_SUBBAND, + RTW89_SAR_5GHZ_SUBBAND_1_2, /* U-NII-1 and U-NII-2 */ + RTW89_SAR_5GHZ_SUBBAND_2_E, /* U-NII-2-Extended */ + RTW89_SAR_5GHZ_SUBBAND_3, /* U-NII-3 */ + RTW89_SAR_6GHZ_SUBBAND_5_L, /* U-NII-5 lower part */ + RTW89_SAR_6GHZ_SUBBAND_5_H, /* U-NII-5 higher part */ + RTW89_SAR_6GHZ_SUBBAND_6, /* U-NII-6 */ + RTW89_SAR_6GHZ_SUBBAND_7_L, /* U-NII-7 lower part */ + RTW89_SAR_6GHZ_SUBBAND_7_H, /* U-NII-7 higher part */ + RTW89_SAR_6GHZ_SUBBAND_8, /* U-NII-8 */ + + RTW89_SAR_SUBBAND_NR, +}; + struct rtw89_sar_cfg_common { - bool set[RTW89_SUBBAND_NR]; - s32 cfg[RTW89_SUBBAND_NR]; + bool set[RTW89_SAR_SUBBAND_NR]; + s32 cfg[RTW89_SAR_SUBBAND_NR]; }; struct rtw89_sar_info { @@ -2646,6 +2675,10 @@ struct rtw89_lck_info { u8 thermal[RF_PATH_MAX]; }; +struct rtw89_rx_dck_info { + u8 thermal[RF_PATH_MAX]; +}; + struct rtw89_iqk_info { bool lok_cor_fail[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR]; bool lok_fin_fail[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR]; @@ -2776,13 +2809,20 @@ enum rtw89_multi_cfo_mode { enum rtw89_phy_cfo_status { RTW89_PHY_DCFO_STATE_NORMAL = 0, RTW89_PHY_DCFO_STATE_ENHANCE = 1, + RTW89_PHY_DCFO_STATE_HOLD = 2, RTW89_PHY_DCFO_STATE_MAX }; +enum rtw89_phy_cfo_ul_ofdma_acc_mode { + RTW89_CFO_UL_OFDMA_ACC_DISABLE = 0, + RTW89_CFO_UL_OFDMA_ACC_ENABLE = 1 +}; + struct rtw89_cfo_tracking_info { u16 cfo_timer_ms; bool cfo_trig_by_timer_en; enum rtw89_phy_cfo_status phy_cfo_status; + enum rtw89_phy_cfo_ul_ofdma_acc_mode cfo_ul_ofdma_acc_mode; u8 phy_cfo_trk_cnt; bool is_adjust; enum rtw89_multi_cfo_mode rtw89_multi_cfo_mode; @@ -3125,6 +3165,7 @@ struct rtw89_dev { struct rtw89_dpk_info dpk; struct rtw89_mcc_info mcc; struct rtw89_lck_info lck; + struct rtw89_rx_dck_info rx_dck; bool is_tssi_mode[RF_PATH_MAX]; bool is_bt_iqk_timeout; diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 7820bc3ab3b47..f00f81916f2f5 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -2376,7 +2376,8 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d), RX: %u [%u] Mbps (lv: %d)\n", stats->tx_throughput, stats->tx_throughput_raw, stats->tx_tfc_lv, stats->rx_throughput, stats->rx_throughput_raw, stats->rx_tfc_lv); - seq_printf(m, "Beacon: %u\n", pkt_stat->beacon_nr); + seq_printf(m, "Beacon: %u, TF: %u\n", pkt_stat->beacon_nr, + stats->rx_tf_periodic); seq_printf(m, "Avg packet length: TX=%u, RX=%u\n", stats->tx_avg_len, stats->rx_avg_len); diff --git a/drivers/net/wireless/realtek/rtw89/debug.h b/drivers/net/wireless/realtek/rtw89/debug.h index de72155ad1fea..561b04faf703d 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.h +++ b/drivers/net/wireless/realtek/rtw89/debug.h @@ -24,6 +24,7 @@ enum rtw89_debug_mask { RTW89_DBG_BTC = BIT(13), RTW89_DBG_BF = BIT(14), RTW89_DBG_HW_SCAN = BIT(15), + RTW89_DBG_SAR = BIT(16), }; enum rtw89_debug_mac_reg_sel { diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 4718aced1428a..2d9c3157d878c 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -2257,7 +2257,7 @@ static int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev, list_add_tail(&ch_info->list, &chan_list); off_chan_time += ch_info->period; } - rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list); + ret = rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list); out: list_for_each_entry_safe(ch_info, tmp, &chan_list, list) { @@ -2339,6 +2339,9 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, rtwvif->scan_req = NULL; rtwvif->scan_ies = NULL; rtwdev->scan_info.scanning_vif = NULL; + + if (rtwvif->net_type != RTW89_NET_TYPE_NO_LINK) + rtw89_store_op_chan(rtwdev, false); } void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) @@ -2365,20 +2368,27 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, if (ret) goto out; } - rtw89_fw_h2c_scan_offload(rtwdev, &opt, rtwvif); + ret = rtw89_fw_h2c_scan_offload(rtwdev, &opt, rtwvif); out: return ret; } -void rtw89_store_op_chan(struct rtw89_dev *rtwdev) +void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_hal *hal = &rtwdev->hal; - scan_info->op_pri_ch = hal->current_primary_channel; - scan_info->op_chan = hal->current_channel; - scan_info->op_bw = hal->current_band_width; - scan_info->op_band = hal->current_band_type; + if (backup) { + scan_info->op_pri_ch = hal->current_primary_channel; + scan_info->op_chan = hal->current_channel; + scan_info->op_bw = hal->current_band_width; + scan_info->op_band = hal->current_band_type; + } else { + hal->current_primary_channel = scan_info->op_pri_ch; + hal->current_channel = scan_info->op_chan; + hal->current_band_width = scan_info->op_bw; + hal->current_band_type = scan_info->op_band; + } } #define H2C_FW_CPU_EXCEPTION_LEN 4 diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 95a55c4213db3..e75ad22aa85df 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -2633,17 +2633,14 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev, struct rtw89_mac_c2h_info *c2h_info); int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable); void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev); -void rtw89_store_op_chan(struct rtw89_dev *rtwdev); +void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup); void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_scan_request *req); void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, bool aborted); int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, bool enable); -void rtw89_hw_scan_status_report(struct rtw89_dev *rtwdev, struct sk_buff *skb); -void rtw89_hw_scan_chan_switch(struct rtw89_dev *rtwdev, struct sk_buff *skb); void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); -void rtw89_store_op_chan(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev); #endif diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 3cf892912c1d9..93124b815825f 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -3681,17 +3681,20 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h, rtw89_hw_scan_complete(rtwdev, vif, false); break; case RTW89_SCAN_ENTER_CH_NOTIFY: - if (rtw89_is_op_chan(rtwdev, band, chan)) + hal->prev_band_type = hal->current_band_type; + hal->current_band_type = band; + hal->prev_primary_channel = hal->current_primary_channel; + hal->current_primary_channel = chan; + hal->current_channel = chan; + hal->current_band_width = RTW89_CHANNEL_WIDTH_20; + if (rtw89_is_op_chan(rtwdev, band, chan)) { + rtw89_store_op_chan(rtwdev, false); ieee80211_wake_queues(rtwdev->hw); + } break; default: return; } - - hal->prev_band_type = hal->current_band_type; - hal->prev_primary_channel = hal->current_channel; - hal->current_channel = chan; - hal->current_band_type = band; } static void diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 9f511c8d8a376..f66619354734d 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -666,6 +666,7 @@ enum mac_ax_err_info { MAC_AX_ERR_L2_ERR_APB_BBRF_TO_RX4281 = 0x2360, MAC_AX_ERR_L2_ERR_APB_BBRF_TO_OTHERS = 0x2370, MAC_AX_ERR_L2_RESET_DONE = 0x2400, + MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT = 0x2599, MAC_AX_ERR_CPU_EXCEPTION = 0x3000, MAC_AX_ERR_ASSERTION = 0x4000, MAC_AX_GET_ERR_MAX, diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index f24e4a208376b..6d0c62c545a78 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -350,7 +350,7 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw, rtw89_phy_set_bss_color(rtwdev, vif); rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif); rtw89_mac_port_update(rtwdev, rtwvif); - rtw89_store_op_chan(rtwdev); + rtw89_store_op_chan(rtwdev, true); } else { /* Abort ongoing scan if cancel_scan isn't issued * when disconnected by peer diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 0ef7821b2e0fc..25872dfb4da1c 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -738,6 +738,9 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev) if (unlikely(isrs.halt_c2h_isrs & B_AX_HALT_C2H_INT_EN)) rtw89_ser_notify(rtwdev, rtw89_mac_get_err_status(rtwdev)); + if (unlikely(isrs.halt_c2h_isrs & B_AX_WDT_TIMEOUT_INT_EN)) + rtw89_ser_notify(rtwdev, MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT); + if (unlikely(rtwpci->under_recovery)) goto enable_intr; @@ -3126,7 +3129,7 @@ static void rtw89_pci_recovery_intr_mask_v1(struct rtw89_dev *rtwdev) struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; rtwpci->ind_intrs = B_AX_HS0ISR_IND_INT_EN; - rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN; + rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN; rtwpci->intrs[0] = 0; rtwpci->intrs[1] = 0; } @@ -3138,7 +3141,7 @@ static void rtw89_pci_default_intr_mask_v1(struct rtw89_dev *rtwdev) rtwpci->ind_intrs = B_AX_HCI_AXIDMA_INT_EN | B_AX_HS1ISR_IND_INT_EN | B_AX_HS0ISR_IND_INT_EN; - rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN; + rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN; rtwpci->intrs[0] = B_AX_TXDMA_STUCK_INT_EN | B_AX_RXDMA_INT_EN | B_AX_RXP1DMA_INT_EN | @@ -3155,7 +3158,7 @@ static void rtw89_pci_low_power_intr_mask_v1(struct rtw89_dev *rtwdev) rtwpci->ind_intrs = B_AX_HS1ISR_IND_INT_EN | B_AX_HS0ISR_IND_INT_EN; - rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN; + rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | B_AX_WDT_TIMEOUT_INT_EN; rtwpci->intrs[0] = 0; rtwpci->intrs[1] = B_AX_GPIO18_INT_EN; } diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index bb585ed191908..a118647213e35 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -94,6 +94,7 @@ /* Interrupts */ #define R_AX_HIMR0 0x01A0 +#define B_AX_WDT_TIMEOUT_INT_EN BIT(22) #define B_AX_HALT_C2H_INT_EN BIT(21) #define R_AX_HISR0 0x01A4 diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 762cdba9d3cfd..217aacb6e8c1b 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -2151,6 +2151,7 @@ static void rtw89_phy_cfo_init(struct rtw89_dev *rtwdev) cfo->cfo_trig_by_timer_en = false; cfo->phy_cfo_trk_cnt = 0; cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL; + cfo->cfo_ul_ofdma_acc_mode = RTW89_CFO_UL_OFDMA_ACC_ENABLE; } static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev, @@ -2419,6 +2420,13 @@ void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev) { struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking; struct rtw89_traffic_stats *stats = &rtwdev->stats; + bool is_ul_ofdma = false, ofdma_acc_en = false; + + if (stats->rx_tf_periodic > CFO_TF_CNT_TH) + is_ul_ofdma = true; + if (cfo->cfo_ul_ofdma_acc_mode == RTW89_CFO_UL_OFDMA_ACC_ENABLE && + is_ul_ofdma) + ofdma_acc_en = true; switch (cfo->phy_cfo_status) { case RTW89_PHY_DCFO_STATE_NORMAL: @@ -2430,16 +2438,26 @@ void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev) } break; case RTW89_PHY_DCFO_STATE_ENHANCE: - if (cfo->phy_cfo_trk_cnt >= CFO_PERIOD_CNT) { + if (stats->tx_throughput <= CFO_TP_LOWER) + cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL; + else if (ofdma_acc_en && + cfo->phy_cfo_trk_cnt >= CFO_PERIOD_CNT) + cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_HOLD; + else + cfo->phy_cfo_trk_cnt++; + + if (cfo->phy_cfo_status == RTW89_PHY_DCFO_STATE_NORMAL) { cfo->phy_cfo_trk_cnt = 0; cfo->cfo_trig_by_timer_en = false; } - if (cfo->cfo_trig_by_timer_en == 1) - cfo->phy_cfo_trk_cnt++; + break; + case RTW89_PHY_DCFO_STATE_HOLD: if (stats->tx_throughput <= CFO_TP_LOWER) { cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL; cfo->phy_cfo_trk_cnt = 0; cfo->cfo_trig_by_timer_en = false; + } else { + cfo->phy_cfo_trk_cnt++; } break; default: diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 291660154d58d..e20636f54b553 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -62,6 +62,7 @@ #define CFO_COMP_PERIOD 250 #define CFO_COMP_WEIGHT 8 #define MAX_CFO_TOLERANCE 30 +#define CFO_TF_CNT_TH 300 #define CCX_MAX_PERIOD 2097 #define CCX_MAX_PERIOD_UNIT 32 diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 64840c8d9efe8..b697aef2faf2d 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -1861,6 +1861,7 @@ static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev) { rtw8852c_dpk_track(rtwdev); rtw8852c_lck_track(rtwdev); + rtw8852c_rx_dck_track(rtwdev); } static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c index dfb9caba9bc41..4186d825d19b7 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c @@ -3864,6 +3864,7 @@ void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_afe) { + struct rtw89_rx_dck_info *rx_dck = &rtwdev->rx_dck; u8 path, kpath; u32 rf_reg5; @@ -3883,6 +3884,7 @@ void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_a rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX); _set_rx_dck(rtwdev, phy, path, is_afe); + rx_dck->thermal[path] = ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]); rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5); if (rtwdev->is_tssi_mode[path]) @@ -3891,6 +3893,31 @@ void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_a } } +#define RTW8852C_RX_DCK_TH 8 + +void rtw8852c_rx_dck_track(struct rtw89_dev *rtwdev) +{ + struct rtw89_rx_dck_info *rx_dck = &rtwdev->rx_dck; + u8 cur_thermal; + int delta; + int path; + + for (path = 0; path < RF_PATH_NUM_8852C; path++) { + cur_thermal = + ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]); + delta = abs((int)cur_thermal - rx_dck->thermal[path]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[RX_DCK] path=%d current thermal=0x%x delta=0x%x\n", + path, cur_thermal, delta); + + if (delta >= RTW8852C_RX_DCK_TH) { + rtw8852c_rx_dck(rtwdev, RTW89_PHY_0, false); + return; + } + } +} + void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { u32 tx_en; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h index c32756f0c01a9..5118a49da8d3e 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h @@ -12,6 +12,7 @@ void rtw8852c_rck(struct rtw89_dev *rtwdev); void rtw8852c_dack(struct rtw89_dev *rtwdev); void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); void rtw8852c_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool is_afe); +void rtw8852c_rx_dck_track(struct rtw89_dev *rtwdev); void rtw8852c_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); void rtw8852c_dpk_track(struct rtw89_dev *rtwdev); void rtw8852c_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c index 097c87899ceaa..eb2d3ec28775f 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.c +++ b/drivers/net/wireless/realtek/rtw89/sar.c @@ -5,15 +5,122 @@ #include "debug.h" #include "sar.h" +static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev, + u32 center_freq) +{ + switch (center_freq) { + default: + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "center freq: %u to SAR subband is unhandled\n", + center_freq); + fallthrough; + case 2412 ... 2484: + return RTW89_SAR_2GHZ_SUBBAND; + case 5180 ... 5320: + return RTW89_SAR_5GHZ_SUBBAND_1_2; + case 5500 ... 5720: + return RTW89_SAR_5GHZ_SUBBAND_2_E; + case 5745 ... 5825: + return RTW89_SAR_5GHZ_SUBBAND_3; + case 5955 ... 6155: + return RTW89_SAR_6GHZ_SUBBAND_5_L; + case 6175 ... 6415: + return RTW89_SAR_6GHZ_SUBBAND_5_H; + case 6435 ... 6515: + return RTW89_SAR_6GHZ_SUBBAND_6; + case 6535 ... 6695: + return RTW89_SAR_6GHZ_SUBBAND_7_L; + case 6715 ... 6855: + return RTW89_SAR_6GHZ_SUBBAND_7_H; + + /* freq 6875 (ch 185, 20MHz) spans RTW89_SAR_6GHZ_SUBBAND_7_H + * and RTW89_SAR_6GHZ_SUBBAND_8, so directly describe it with + * struct rtw89_sar_span in the following. + */ + + case 6895 ... 7115: + return RTW89_SAR_6GHZ_SUBBAND_8; + } +} + +struct rtw89_sar_span { + enum rtw89_sar_subband subband_low; + enum rtw89_sar_subband subband_high; +}; + +#define RTW89_SAR_SPAN_VALID(span) ((span)->subband_high) + +#define RTW89_SAR_6GHZ_SPAN_HEAD 6145 +#define RTW89_SAR_6GHZ_SPAN_IDX(center_freq) \ + ((((int)(center_freq) - RTW89_SAR_6GHZ_SPAN_HEAD) / 5) / 2) + +#define RTW89_DECL_SAR_6GHZ_SPAN(center_freq, subband_l, subband_h) \ + [RTW89_SAR_6GHZ_SPAN_IDX(center_freq)] = { \ + .subband_low = RTW89_SAR_6GHZ_ ## subband_l, \ + .subband_high = RTW89_SAR_6GHZ_ ## subband_h, \ + } + +/* Since 6GHz SAR subbands are not edge aligned, some cases span two SAR + * subbands. In the following, we describe each of them with rtw89_sar_span. + */ +static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = { + RTW89_DECL_SAR_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H), + RTW89_DECL_SAR_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H), + RTW89_DECL_SAR_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H), + RTW89_DECL_SAR_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L), + RTW89_DECL_SAR_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L), + RTW89_DECL_SAR_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L), + RTW89_DECL_SAR_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H), + RTW89_DECL_SAR_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H), + RTW89_DECL_SAR_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8), + RTW89_DECL_SAR_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8), + RTW89_DECL_SAR_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8), + RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8), +}; + static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg) { struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common; - enum rtw89_subband subband = rtwdev->hal.current_subband; + struct rtw89_hal *hal = &rtwdev->hal; + enum rtw89_band band = hal->current_band_type; + u32 center_freq = hal->current_freq; + const struct rtw89_sar_span *span = NULL; + enum rtw89_sar_subband subband_l, subband_h; + int idx; + + if (band == RTW89_BAND_6G) { + idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq); + /* To decrease size of rtw89_sar_overlapping_6ghz[], + * RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs + * to make first span as index 0 of the table. So, if center + * frequency is less than the first one, it will get netative. + */ + if (idx >= 0 && idx < ARRAY_SIZE(rtw89_sar_overlapping_6ghz)) + span = &rtw89_sar_overlapping_6ghz[idx]; + } + + if (span && RTW89_SAR_SPAN_VALID(span)) { + subband_l = span->subband_low; + subband_h = span->subband_high; + } else { + subband_l = rtw89_sar_get_subband(rtwdev, center_freq); + subband_h = subband_l; + } + + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "for {band %u, center_freq %u}, SAR subband: {%u, %u}\n", + band, center_freq, subband_l, subband_h); - if (!rtwsar->set[subband]) + if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h]) return -ENODATA; - *cfg = rtwsar->cfg[subband]; + if (!rtwsar->set[subband_l]) + *cfg = rtwsar->cfg[subband_h]; + else if (!rtwsar->set[subband_h]) + *cfg = rtwsar->cfg[subband_l]; + else + *cfg = min(rtwsar->cfg[subband_l], rtwsar->cfg[subband_h]); + return 0; } @@ -128,21 +235,20 @@ static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev, return ret; } -static const u8 rtw89_common_sar_subband_map[] = { - RTW89_CH_2G, - RTW89_CH_5G_BAND_1, - RTW89_CH_5G_BAND_3, - RTW89_CH_5G_BAND_4, -}; - static const struct cfg80211_sar_freq_ranges rtw89_common_sar_freq_ranges[] = { { .start_freq = 2412, .end_freq = 2484, }, { .start_freq = 5180, .end_freq = 5320, }, { .start_freq = 5500, .end_freq = 5720, }, { .start_freq = 5745, .end_freq = 5825, }, + { .start_freq = 5955, .end_freq = 6155, }, + { .start_freq = 6175, .end_freq = 6415, }, + { .start_freq = 6435, .end_freq = 6515, }, + { .start_freq = 6535, .end_freq = 6695, }, + { .start_freq = 6715, .end_freq = 6875, }, + { .start_freq = 6875, .end_freq = 7115, }, }; -static_assert(ARRAY_SIZE(rtw89_common_sar_subband_map) == +static_assert(RTW89_SAR_SUBBAND_NR == ARRAY_SIZE(rtw89_common_sar_freq_ranges)); const struct cfg80211_sar_capa rtw89_sar_capa = { @@ -159,7 +265,6 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, u8 fct; u32 freq_start; u32 freq_end; - u32 band; s32 power; u32 i, idx; @@ -175,15 +280,14 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, freq_start = rtw89_common_sar_freq_ranges[idx].start_freq; freq_end = rtw89_common_sar_freq_ranges[idx].end_freq; - band = rtw89_common_sar_subband_map[idx]; power = sar->sub_specs[i].power; - rtw89_info(rtwdev, "On freq %u to %u, ", freq_start, freq_end); - rtw89_info(rtwdev, "set SAR power limit %d (unit: 1/%lu dBm)\n", - power, BIT(fct)); + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "On freq %u to %u, set SAR limit %d (unit: 1/%lu dBm)\n", + freq_start, freq_end, power, BIT(fct)); - sar_common.set[band] = true; - sar_common.cfg[band] = power; + sar_common.set[idx] = true; + sar_common.cfg[idx] = power; } return rtw89_apply_sar_common(rtwdev, &sar_common); diff --git a/drivers/net/wireless/silabs/wfx/fwio.c b/drivers/net/wireless/silabs/wfx/fwio.c index 3d1b8a135dc07..52c7f560b062c 100644 --- a/drivers/net/wireless/silabs/wfx/fwio.c +++ b/drivers/net/wireless/silabs/wfx/fwio.c @@ -286,8 +286,7 @@ static int load_firmware_secure(struct wfx_dev *wdev) error: kfree(buf); - if (fw) - release_firmware(fw); + release_firmware(fw); if (ret) print_boot_status(wdev); return ret; diff --git a/drivers/net/wireless/st/cw1200/bh.c b/drivers/net/wireless/st/cw1200/bh.c index 10e019cddcc65..3b4ded2ac801c 100644 --- a/drivers/net/wireless/st/cw1200/bh.c +++ b/drivers/net/wireless/st/cw1200/bh.c @@ -327,18 +327,12 @@ static int cw1200_bh_rx_helper(struct cw1200_common *priv, if (WARN_ON(wsm_handle_rx(priv, wsm_id, wsm, &skb_rx))) goto err; - if (skb_rx) { - dev_kfree_skb(skb_rx); - skb_rx = NULL; - } + dev_kfree_skb(skb_rx); return 0; err: - if (skb_rx) { - dev_kfree_skb(skb_rx); - skb_rx = NULL; - } + dev_kfree_skb(skb_rx); return -1; } diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index 514f2c1124b61..ba14d83353a4b 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -654,7 +654,7 @@ static int __init virt_wifi_init_module(void) { int err; - /* Guaranteed to be locallly-administered and not multicast. */ + /* Guaranteed to be locally-administered and not multicast. */ eth_random_addr(fake_router_bssid); err = register_netdevice_notifier(&virt_wifi_notifier); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 75d40acb60c1c..5c65ae6b81543 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -76,6 +76,7 @@ #define IEEE80211_STYPE_ACTION 0x00D0 /* control */ +#define IEEE80211_STYPE_TRIGGER 0x0020 #define IEEE80211_STYPE_CTL_EXT 0x0060 #define IEEE80211_STYPE_BACK_REQ 0x0080 #define IEEE80211_STYPE_BACK 0x0090 @@ -295,6 +296,17 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2) #define IEEE80211_HT_CTL_LEN 4 +/* trigger type within common_info of trigger frame */ +#define IEEE80211_TRIGGER_TYPE_MASK 0xf +#define IEEE80211_TRIGGER_TYPE_BASIC 0x0 +#define IEEE80211_TRIGGER_TYPE_BFRP 0x1 +#define IEEE80211_TRIGGER_TYPE_MU_BAR 0x2 +#define IEEE80211_TRIGGER_TYPE_MU_RTS 0x3 +#define IEEE80211_TRIGGER_TYPE_BSRP 0x4 +#define IEEE80211_TRIGGER_TYPE_GCR_MU_BAR 0x5 +#define IEEE80211_TRIGGER_TYPE_BQRP 0x6 +#define IEEE80211_TRIGGER_TYPE_NFRP 0x7 + struct ieee80211_hdr { __le16 frame_control; __le16 duration_id; @@ -324,6 +336,15 @@ struct ieee80211_qos_hdr { __le16 qos_ctrl; } __packed __aligned(2); +struct ieee80211_trigger { + __le16 frame_control; + __le16 duration; + u8 ra[ETH_ALEN]; + u8 ta[ETH_ALEN]; + __le64 common_info; + u8 variable[]; +} __packed __aligned(2); + /** * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set * @fc: frame control bytes in little-endian byteorder @@ -729,6 +750,16 @@ static inline bool ieee80211_is_qos_nullfunc(__le16 fc) cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); } +/** + * ieee80211_is_trigger - check if frame is trigger frame + * @fc: frame control field in little-endian byteorder + */ +static inline bool ieee80211_is_trigger(__le16 fc) +{ + return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_TRIGGER); +} + /** * ieee80211_is_any_nullfunc - check if frame is regular or QoS nullfunc frame * @fc: frame control bytes in little-endian byteorder diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ebadb21039686..5c9e97eca7390 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1958,36 +1958,6 @@ struct ieee80211_key_seq { }; }; -/** - * struct ieee80211_cipher_scheme - cipher scheme - * - * This structure contains a cipher scheme information defining - * the secure packet crypto handling. - * - * @cipher: a cipher suite selector - * @iftype: a cipher iftype bit mask indicating an allowed cipher usage - * @hdr_len: a length of a security header used the cipher - * @pn_len: a length of a packet number in the security header - * @pn_off: an offset of pn from the beginning of the security header - * @key_idx_off: an offset of key index byte in the security header - * @key_idx_mask: a bit mask of key_idx bits - * @key_idx_shift: a bit shift needed to get key_idx - * key_idx value calculation: - * (sec_header_base[key_idx_off] & key_idx_mask) >> key_idx_shift - * @mic_len: a mic length in bytes - */ -struct ieee80211_cipher_scheme { - u32 cipher; - u16 iftype; - u8 hdr_len; - u8 pn_len; - u8 pn_off; - u8 key_idx_off; - u8 key_idx_mask; - u8 key_idx_shift; - u8 mic_len; -}; - /** * enum set_key_cmd - key command * @@ -2664,9 +2634,6 @@ enum ieee80211_hw_flags { * deliver to a WMM STA during any Service Period triggered by the WMM STA. * Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values. * - * @n_cipher_schemes: a size of an array of cipher schemes definitions. - * @cipher_schemes: a pointer to an array of cipher scheme definitions - * supported by HW. * @max_nan_de_entries: maximum number of NAN DE functions supported by the * device. * @@ -2716,8 +2683,6 @@ struct ieee80211_hw { netdev_features_t netdev_features; u8 uapsd_queues; u8 uapsd_max_sp_len; - u8 n_cipher_schemes; - const struct ieee80211_cipher_scheme *cipher_schemes; u8 max_nan_de_entries; u8 tx_sk_pacing_shift; u8 weight_multiplier; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index d9490e3062a70..98f905f16411f 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -5874,7 +5874,7 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up * the connected inactive stations in AP mode. * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested - * to work properly to suppport receiving regulatory hints from + * to work properly to support receiving regulatory hints from * cellular base stations. * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only * here to reserve the value for API/ABI compatibility) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f7896f257e1b4..881efbfb96f6d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -5,7 +5,7 @@ * Copyright 2006-2010 Johannes Berg * Copyright 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #include @@ -438,7 +438,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct sta_info *sta = NULL; - const struct ieee80211_cipher_scheme *cs = NULL; struct ieee80211_key *key; int err; @@ -456,23 +455,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, if (WARN_ON_ONCE(fips_enabled)) return -EINVAL; break; - case WLAN_CIPHER_SUITE_CCMP: - case WLAN_CIPHER_SUITE_CCMP_256: - case WLAN_CIPHER_SUITE_AES_CMAC: - case WLAN_CIPHER_SUITE_BIP_CMAC_256: - case WLAN_CIPHER_SUITE_BIP_GMAC_128: - case WLAN_CIPHER_SUITE_BIP_GMAC_256: - case WLAN_CIPHER_SUITE_GCMP: - case WLAN_CIPHER_SUITE_GCMP_256: - break; default: - cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type); break; } key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, - params->key, params->seq_len, params->seq, - cs); + params->key, params->seq_len, params->seq); if (IS_ERR(key)) return PTR_ERR(key); @@ -537,9 +525,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, break; } - if (sta) - sta->cipher_scheme = cs; - err = ieee80211_key_link(key, sdata, sta); out_unlock: @@ -548,33 +533,53 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, return err; } +static struct ieee80211_key * +ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, + u8 key_idx, bool pairwise, const u8 *mac_addr) +{ + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + + if (mac_addr) { + sta = sta_info_get_bss(sdata, mac_addr); + if (!sta) + return NULL; + + if (pairwise && key_idx < NUM_DEFAULT_KEYS) + return rcu_dereference_check_key_mtx(local, + sta->ptk[key_idx]); + + if (!pairwise && + key_idx < NUM_DEFAULT_KEYS + + NUM_DEFAULT_MGMT_KEYS + + NUM_DEFAULT_BEACON_KEYS) + return rcu_dereference_check_key_mtx(local, + sta->deflink.gtk[key_idx]); + + return NULL; + } + + if (key_idx < NUM_DEFAULT_KEYS + + NUM_DEFAULT_MGMT_KEYS + + NUM_DEFAULT_BEACON_KEYS) + return rcu_dereference_check_key_mtx(local, + sdata->keys[key_idx]); + + return NULL; +} + static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, bool pairwise, const u8 *mac_addr) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - struct ieee80211_key *key = NULL; + struct ieee80211_key *key; int ret; mutex_lock(&local->sta_mtx); mutex_lock(&local->key_mtx); - if (mac_addr) { - ret = -ENOENT; - - sta = sta_info_get_bss(sdata, mac_addr); - if (!sta) - goto out_unlock; - - if (pairwise) - key = key_mtx_dereference(local, sta->ptk[key_idx]); - else - key = key_mtx_dereference(local, - sta->deflink.gtk[key_idx]); - } else - key = key_mtx_dereference(local, sdata->keys[key_idx]); - + key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr); if (!key) { ret = -ENOENT; goto out_unlock; @@ -597,10 +602,9 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, struct key_params *params)) { struct ieee80211_sub_if_data *sdata; - struct sta_info *sta = NULL; u8 seq[6] = {0}; struct key_params params; - struct ieee80211_key *key = NULL; + struct ieee80211_key *key; u64 pn64; u32 iv32; u16 iv16; @@ -611,20 +615,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, rcu_read_lock(); - if (mac_addr) { - sta = sta_info_get_bss(sdata, mac_addr); - if (!sta) - goto out; - - if (pairwise && key_idx < NUM_DEFAULT_KEYS) - key = rcu_dereference(sta->ptk[key_idx]); - else if (!pairwise && - key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS + - NUM_DEFAULT_BEACON_KEYS) - key = rcu_dereference(sta->deflink.gtk[key_idx]); - } else - key = rcu_dereference(sdata->keys[key_idx]); - + key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr); if (!key) goto out; @@ -1207,9 +1198,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, params->crypto.control_port_over_nl80211; sdata->control_port_no_preauth = params->crypto.control_port_no_preauth; - sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local, - ¶ms->crypto, - sdata->vif.type); list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { vlan->control_port_protocol = @@ -1220,10 +1208,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, params->crypto.control_port_over_nl80211; vlan->control_port_no_preauth = params->crypto.control_port_no_preauth; - vlan->encrypt_headroom = - ieee80211_cs_headroom(sdata->local, - ¶ms->crypto, - vlan->vif.type); } sdata->vif.bss_conf.dtim_period = params->dtim_period; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 86ef0a46a68ce..1cf331572de1b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -5,7 +5,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007-2010 Johannes Berg * Copyright 2013-2015 Intel Mobile Communications GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #ifndef IEEE80211_I_H @@ -944,7 +944,6 @@ struct ieee80211_sub_if_data { bool control_port_no_encrypt; bool control_port_no_preauth; bool control_port_over_nl80211; - int encrypt_headroom; atomic_t num_tx_queued; struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; @@ -2483,14 +2482,6 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work); int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, struct cfg80211_csa_settings *csa_settings); -bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs); -bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n); -const struct ieee80211_cipher_scheme * -ieee80211_cs_get(struct ieee80211_local *local, u32 cipher, - enum nl80211_iftype iftype); -int ieee80211_cs_headroom(struct ieee80211_local *local, - struct cfg80211_crypto_settings *crypto, - enum nl80211_iftype iftype); void ieee80211_recalc_dtim(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 41531478437cf..fb8d102fca482 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -8,7 +8,7 @@ * Copyright 2008, Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #include #include @@ -1036,8 +1036,6 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) wiphy_name(local->hw.wiphy)); sdata->wdev.iftype = NL80211_IFTYPE_MONITOR; - sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; - ieee80211_set_default_queues(sdata); ret = drv_add_interface(local, sdata); @@ -1644,7 +1642,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, sdata->control_port_no_encrypt = false; sdata->control_port_over_nl80211 = false; sdata->control_port_no_preauth = false; - sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; sdata->vif.bss_conf.idle = true; sdata->vif.bss_conf.txpower = INT_MIN; /* unset */ @@ -2116,8 +2113,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; sdata->user_power_level = local->user_power_level; - sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; - /* setup type-dependent data */ ieee80211_setup_sdata(sdata, type); diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 0fcf8aebedc4e..c3476de4b14d8 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -6,7 +6,7 @@ * Copyright 2007-2008 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2015-2017 Intel Deutschland GmbH - * Copyright 2018-2020 Intel Corporation + * Copyright 2018-2020, 2022 Intel Corporation */ #include @@ -531,8 +531,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, struct ieee80211_key * ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, const u8 *key_data, - size_t seq_len, const u8 *seq, - const struct ieee80211_cipher_scheme *cs) + size_t seq_len, const u8 *seq) { struct ieee80211_key *key; int i, j, err; @@ -675,21 +674,6 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, return ERR_PTR(err); } break; - default: - if (cs) { - if (seq_len && seq_len != cs->pn_len) { - kfree(key); - return ERR_PTR(-EINVAL); - } - - key->conf.iv_len = cs->hdr_len; - key->conf.icv_len = cs->mic_len; - for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) - for (j = 0; j < seq_len; j++) - key->u.gen.rx_pn[i][j] = - seq[seq_len - j - 1]; - key->flags |= KEY_FLAG_CIPHER_SCHEME; - } } memcpy(key->conf.key, key_data, key_len); INIT_LIST_HEAD(&key->list); @@ -1294,7 +1278,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif, key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx, keyconf->keylen, keyconf->key, - 0, NULL, NULL); + 0, NULL); if (IS_ERR(key)) return ERR_CAST(key); diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 1e326c89d7217..e994dcea1ce3a 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -2,7 +2,7 @@ /* * Copyright 2002-2004, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. - * Copyright (C) 2019 Intel Corporation + * Copyright (C) 2019, 2022 Intel Corporation */ #ifndef IEEE80211_KEY_H @@ -30,12 +30,10 @@ struct sta_info; * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present * in the hardware for TX crypto hardware acceleration. * @KEY_FLAG_TAINTED: Key is tainted and packets should be dropped. - * @KEY_FLAG_CIPHER_SCHEME: This key is for a hardware cipher scheme */ enum ieee80211_internal_key_flags { KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), KEY_FLAG_TAINTED = BIT(1), - KEY_FLAG_CIPHER_SCHEME = BIT(2), }; enum ieee80211_internal_tkip_state { @@ -140,8 +138,7 @@ struct ieee80211_key { struct ieee80211_key * ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, const u8 *key_data, - size_t seq_len, const u8 *seq, - const struct ieee80211_cipher_scheme *cs); + size_t seq_len, const u8 *seq); /* * Insert a key into data structures (sdata, sta if necessary) * to make it used, free old key. On failure, also free the new key. @@ -166,6 +163,8 @@ void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata); #define key_mtx_dereference(local, ref) \ rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) +#define rcu_dereference_check_key_mtx(local, ref) \ + rcu_dereference_check(ref, lockdep_is_held(&((local)->key_mtx))) void ieee80211_delayed_tailroom_dec(struct work_struct *wk); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5a385d4146b9b..4f3e93c0819b2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -5,7 +5,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #include @@ -778,7 +778,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) { bool have_wep = !fips_enabled; /* FIPS does not permit the use of RC4 */ bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE); - int n_suites = 0, r = 0, w = 0; + int r = 0, w = 0; u32 *suites; static const u32 cipher_suites[] = { /* keep WEP first, it may be removed below */ @@ -824,10 +824,9 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) continue; suites[w++] = suite; } - } else if (!local->hw.cipher_schemes) { - /* If the driver doesn't have cipher schemes, there's nothing - * else to do other than assign the (software supported and - * perhaps offloaded) cipher suites. + } else { + /* assign the (software supported and perhaps offloaded) + * cipher suites */ local->hw.wiphy->cipher_suites = cipher_suites; local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); @@ -842,58 +841,6 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) /* not dynamically allocated, so just return */ return 0; - } else { - const struct ieee80211_cipher_scheme *cs; - - cs = local->hw.cipher_schemes; - - /* Driver specifies cipher schemes only (but not cipher suites - * including the schemes) - * - * We start counting ciphers defined by schemes, TKIP, CCMP, - * CCMP-256, GCMP, and GCMP-256 - */ - n_suites = local->hw.n_cipher_schemes + 5; - - /* check if we have WEP40 and WEP104 */ - if (have_wep) - n_suites += 2; - - /* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128, - * BIP-GMAC-256 - */ - if (have_mfp) - n_suites += 4; - - suites = kmalloc_array(n_suites, sizeof(u32), GFP_KERNEL); - if (!suites) - return -ENOMEM; - - suites[w++] = WLAN_CIPHER_SUITE_CCMP; - suites[w++] = WLAN_CIPHER_SUITE_CCMP_256; - suites[w++] = WLAN_CIPHER_SUITE_TKIP; - suites[w++] = WLAN_CIPHER_SUITE_GCMP; - suites[w++] = WLAN_CIPHER_SUITE_GCMP_256; - - if (have_wep) { - suites[w++] = WLAN_CIPHER_SUITE_WEP40; - suites[w++] = WLAN_CIPHER_SUITE_WEP104; - } - - if (have_mfp) { - suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; - suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256; - suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128; - suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; - } - - for (r = 0; r < local->hw.n_cipher_schemes; r++) { - suites[w++] = cs[r].cipher; - if (WARN_ON(cs[r].pn_len > IEEE80211_MAX_PN_LEN)) { - kfree(suites); - return -EINVAL; - } - } } local->hw.wiphy->cipher_suites = suites; @@ -1168,12 +1115,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (local->hw.wiphy->max_scan_ie_len) local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; - if (WARN_ON(!ieee80211_cs_list_valid(local->hw.cipher_schemes, - local->hw.n_cipher_schemes))) { - result = -EINVAL; - goto fail_workqueue; - } - result = ieee80211_init_cipher_suites(local); if (result < 0) goto fail_workqueue; diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 58ebdcd69d055..45e7c1b307bc6 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2008, 2009 open80211s Ltd. - * Copyright (C) 2019, 2021 Intel Corporation + * Copyright (C) 2019, 2021-2022 Intel Corporation * Author: Luis Carlos Cobo */ @@ -247,13 +247,13 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, return -EAGAIN; skb = dev_alloc_skb(local->tx_headroom + - sdata->encrypt_headroom + + IEEE80211_ENCRYPT_HEADROOM + IEEE80211_ENCRYPT_TAILROOM + hdr_len + 2 + 15 /* PERR IE */); if (!skb) return -1; - skb_reserve(skb, local->tx_headroom + sdata->encrypt_headroom); + skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); mgmt = skb_put_zero(skb, hdr_len); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 58d48dcae0303..6d5ad71ef02c2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -8,7 +8,7 @@ * Copyright 2007, Michael Wu * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 - 2021 Intel Corporation + * Copyright (C) 2018 - 2022 Intel Corporation */ #include @@ -2496,8 +2496,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, memset(ifmgd->tx_tspec, 0, sizeof(ifmgd->tx_tspec)); cancel_delayed_work_sync(&ifmgd->tx_tspec_wk); - sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; - bss_conf->pwr_reduction = 0; bss_conf->tx_pwr_env_num = 0; memset(bss_conf->tx_pwr_env, 0, sizeof(bss_conf->tx_pwr_env)); @@ -6071,8 +6069,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sdata->control_port_over_nl80211 = req->crypto.control_port_over_nl80211; sdata->control_port_no_preauth = req->crypto.control_port_no_preauth; - sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto, - sdata->vif.type); /* kick off associate process */ diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3c08ae04ddbc3..a9f4e90ad893f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -6,7 +6,7 @@ * Copyright 2007-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #include @@ -1009,43 +1009,20 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) return -1; } -static int ieee80211_get_keyid(struct sk_buff *skb, - const struct ieee80211_cipher_scheme *cs) +static int ieee80211_get_keyid(struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc; - int hdrlen; - int minlen; - u8 key_idx_off; - u8 key_idx_shift; + __le16 fc = hdr->frame_control; + int hdrlen = ieee80211_hdrlen(fc); u8 keyid; - fc = hdr->frame_control; - hdrlen = ieee80211_hdrlen(fc); - - if (cs) { - minlen = hdrlen + cs->hdr_len; - key_idx_off = hdrlen + cs->key_idx_off; - key_idx_shift = cs->key_idx_shift; - } else { - /* WEP, TKIP, CCMP and GCMP */ - minlen = hdrlen + IEEE80211_WEP_IV_LEN; - key_idx_off = hdrlen + 3; - key_idx_shift = 6; - } - - if (unlikely(skb->len < minlen)) + /* WEP, TKIP, CCMP and GCMP */ + if (unlikely(skb->len < hdrlen + IEEE80211_WEP_IV_LEN)) return -EINVAL; - skb_copy_bits(skb, key_idx_off, &keyid, 1); + skb_copy_bits(skb, hdrlen + 3, &keyid, 1); - if (cs) - keyid &= cs->key_idx_mask; - keyid >>= key_idx_shift; - - /* cs could use more than the usual two bits for the keyid */ - if (unlikely(keyid >= NUM_DEFAULT_KEYS)) - return -EINVAL; + keyid >>= 6; return keyid; } @@ -1916,7 +1893,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) struct ieee80211_key *ptk_idx = NULL; int mmie_keyidx = -1; __le16 fc; - const struct ieee80211_cipher_scheme *cs = NULL; if (ieee80211_is_ext(hdr->frame_control)) return RX_CONTINUE; @@ -1959,8 +1935,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) if (ieee80211_has_protected(fc) && !(status->flag & RX_FLAG_IV_STRIPPED)) { - cs = rx->sta->cipher_scheme; - keyid = ieee80211_get_keyid(rx->skb, cs); + keyid = ieee80211_get_keyid(rx->skb); if (unlikely(keyid < 0)) return RX_DROP_UNUSABLE; @@ -2065,7 +2040,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) (status->flag & RX_FLAG_IV_STRIPPED)) return RX_CONTINUE; - keyidx = ieee80211_get_keyid(rx->skb, cs); + keyidx = ieee80211_get_keyid(rx->skb); if (unlikely(keyidx < 0)) return RX_DROP_UNUSABLE; @@ -2131,7 +2106,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) result = ieee80211_crypto_gcmp_decrypt(rx); break; default: - result = ieee80211_crypto_hw_decrypt(rx); + result = RX_DROP_UNUSABLE; } /* the hdr variable is invalid after the decrypt handlers */ @@ -2945,7 +2920,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) tailroom = IEEE80211_ENCRYPT_TAILROOM; fwd_skb = skb_copy_expand(skb, local->tx_headroom + - sdata->encrypt_headroom, + IEEE80211_ENCRYPT_HEADROOM, tailroom, GFP_ATOMIC); if (!fwd_skb) goto out; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 35c390bedfba2..aa6950aa49a91 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -3,7 +3,7 @@ * Copyright 2002-2005, Devicescape Software, Inc. * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright(c) 2020-2021 Intel Corporation + * Copyright(c) 2020-2022 Intel Corporation */ #ifndef STA_INFO_H @@ -616,7 +616,6 @@ struct link_sta_info { * taken from HT/VHT capabilities or VHT operating mode notification * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for * AP only. - * @cipher_scheme: optional cipher scheme for this station * @cparams: CoDel parameters for this station. * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED) * @fast_tx: TX fastpath information @@ -700,7 +699,6 @@ struct sta_info { #endif enum ieee80211_smps_mode known_smps_mode; - const struct ieee80211_cipher_scheme *cipher_scheme; struct codel_params cparams; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0e4efc08c762d..37fe72bb5ab07 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -5,7 +5,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * * Transmit and frame generation functions. */ @@ -882,7 +882,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx, rem -= fraglen; tmp = dev_alloc_skb(local->tx_headroom + frag_threshold + - tx->sdata->encrypt_headroom + + IEEE80211_ENCRYPT_HEADROOM + IEEE80211_ENCRYPT_TAILROOM); if (!tmp) return -ENOMEM; @@ -890,7 +890,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx, __skb_queue_tail(&tx->skbs, tmp); skb_reserve(tmp, - local->tx_headroom + tx->sdata->encrypt_headroom); + local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); /* copy control information */ memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); @@ -1040,8 +1040,6 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: return ieee80211_crypto_gcmp_encrypt(tx); - default: - return ieee80211_crypto_hw_encrypt(tx); } return TX_DROP; @@ -2013,7 +2011,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, headroom = local->tx_headroom; if (encrypt != ENCRYPT_NO) - headroom += sdata->encrypt_headroom; + headroom += IEEE80211_ENCRYPT_HEADROOM; headroom -= skb_headroom(skb); headroom = max_t(int, 0, headroom); @@ -2867,7 +2865,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, */ if (head_need > 0 || skb_cloned(skb)) { - head_need += sdata->encrypt_headroom; + head_need += IEEE80211_ENCRYPT_HEADROOM; head_need += local->tx_headroom; head_need = max_t(int, 0, head_need); if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) { @@ -3128,15 +3126,6 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) /* we don't know how to generate IVs for this at all */ if (WARN_ON(gen_iv)) goto out; - /* pure hardware keys are OK, of course */ - if (!(build.key->flags & KEY_FLAG_CIPHER_SCHEME)) - break; - /* cipher scheme might require space allocation */ - if (iv_spc && - build.key->conf.iv_len > IEEE80211_FAST_XMIT_MAX_IV) - goto out; - if (iv_spc) - build.hdr_len += build.key->conf.iv_len; } fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1e26b5235add4..9e6c4dcef2800 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -6,7 +6,7 @@ * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * * utilities for mac80211 */ @@ -4212,74 +4212,6 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, return 0; } -bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs) -{ - return !(cs == NULL || cs->cipher == 0 || - cs->hdr_len < cs->pn_len + cs->pn_off || - cs->hdr_len <= cs->key_idx_off || - cs->key_idx_shift > 7 || - cs->key_idx_mask == 0); -} - -bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n) -{ - int i; - - /* Ensure we have enough iftype bitmap space for all iftype values */ - WARN_ON((NUM_NL80211_IFTYPES / 8 + 1) > sizeof(cs[0].iftype)); - - for (i = 0; i < n; i++) - if (!ieee80211_cs_valid(&cs[i])) - return false; - - return true; -} - -const struct ieee80211_cipher_scheme * -ieee80211_cs_get(struct ieee80211_local *local, u32 cipher, - enum nl80211_iftype iftype) -{ - const struct ieee80211_cipher_scheme *l = local->hw.cipher_schemes; - int n = local->hw.n_cipher_schemes; - int i; - const struct ieee80211_cipher_scheme *cs = NULL; - - for (i = 0; i < n; i++) { - if (l[i].cipher == cipher) { - cs = &l[i]; - break; - } - } - - if (!cs || !(cs->iftype & BIT(iftype))) - return NULL; - - return cs; -} - -int ieee80211_cs_headroom(struct ieee80211_local *local, - struct cfg80211_crypto_settings *crypto, - enum nl80211_iftype iftype) -{ - const struct ieee80211_cipher_scheme *cs; - int headroom = IEEE80211_ENCRYPT_HEADROOM; - int i; - - for (i = 0; i < crypto->n_ciphers_pairwise; i++) { - cs = ieee80211_cs_get(local, crypto->ciphers_pairwise[i], - iftype); - - if (cs && headroom < cs->hdr_len) - headroom = cs->hdr_len; - } - - cs = ieee80211_cs_get(local, crypto->cipher_group, iftype); - if (cs && headroom < cs->hdr_len) - headroom = cs->hdr_len; - - return headroom; -} - static bool ieee80211_extend_noa_desc(struct ieee80211_noa_data *data, u32 tsf, int i) { diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 5fd8a3e8b5b4e..93ec2f3497489 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -3,7 +3,7 @@ * Copyright 2002-2004, Instant802 Networks, Inc. * Copyright 2008, Jouni Malinen * Copyright (C) 2016-2017 Intel Deutschland GmbH - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation */ #include @@ -778,102 +778,6 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) return RX_CONTINUE; } -static ieee80211_tx_result -ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx, - struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_key *key = tx->key; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int hdrlen; - u8 *pos, iv_len = key->conf.iv_len; - - if (info->control.hw_key && - !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) { - /* hwaccel has no need for preallocated head room */ - return TX_CONTINUE; - } - - if (unlikely(skb_headroom(skb) < iv_len && - pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC))) - return TX_DROP; - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - - pos = skb_push(skb, iv_len); - memmove(pos, pos + iv_len, hdrlen); - - return TX_CONTINUE; -} - -static inline int ieee80211_crypto_cs_pn_compare(u8 *pn1, u8 *pn2, int len) -{ - int i; - - /* pn is little endian */ - for (i = len - 1; i >= 0; i--) { - if (pn1[i] < pn2[i]) - return -1; - else if (pn1[i] > pn2[i]) - return 1; - } - - return 0; -} - -static ieee80211_rx_result -ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx) -{ - struct ieee80211_key *key = rx->key; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; - const struct ieee80211_cipher_scheme *cs = NULL; - int hdrlen = ieee80211_hdrlen(hdr->frame_control); - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); - int data_len; - u8 *rx_pn; - u8 *skb_pn; - u8 qos_tid; - - if (!rx->sta || !rx->sta->cipher_scheme || - !(status->flag & RX_FLAG_DECRYPTED)) - return RX_DROP_UNUSABLE; - - if (!ieee80211_is_data(hdr->frame_control)) - return RX_CONTINUE; - - cs = rx->sta->cipher_scheme; - - data_len = rx->skb->len - hdrlen - cs->hdr_len; - - if (data_len < 0) - return RX_DROP_UNUSABLE; - - if (ieee80211_is_data_qos(hdr->frame_control)) - qos_tid = ieee80211_get_tid(hdr); - else - qos_tid = 0; - - if (skb_linearize(rx->skb)) - return RX_DROP_UNUSABLE; - - rx_pn = key->u.gen.rx_pn[qos_tid]; - skb_pn = rx->skb->data + hdrlen + cs->pn_off; - - if (ieee80211_crypto_cs_pn_compare(skb_pn, rx_pn, cs->pn_len) <= 0) - return RX_DROP_UNUSABLE; - - memcpy(rx_pn, skb_pn, cs->pn_len); - - /* remove security header and MIC */ - if (pskb_trim(rx->skb, rx->skb->len - cs->mic_len)) - return RX_DROP_UNUSABLE; - - memmove(rx->skb->data + cs->hdr_len, rx->skb->data, hdrlen); - skb_pull(rx->skb, cs->hdr_len); - - return RX_CONTINUE; -} - static void bip_aad(struct sk_buff *skb, u8 *aad) { __le16 mask_fc; @@ -1212,38 +1116,3 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) return RX_CONTINUE; } - -ieee80211_tx_result -ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx) -{ - struct sk_buff *skb; - struct ieee80211_tx_info *info = NULL; - ieee80211_tx_result res; - - skb_queue_walk(&tx->skbs, skb) { - info = IEEE80211_SKB_CB(skb); - - /* handle hw-only algorithm */ - if (!info->control.hw_key) - return TX_DROP; - - if (tx->key->flags & KEY_FLAG_CIPHER_SCHEME) { - res = ieee80211_crypto_cs_encrypt(tx, skb); - if (res != TX_CONTINUE) - return res; - } - } - - ieee80211_tx_set_protected(tx); - - return TX_CONTINUE; -} - -ieee80211_rx_result -ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx) -{ - if (rx->sta && rx->sta->cipher_scheme) - return ieee80211_crypto_cs_decrypt(rx); - - return RX_DROP_UNUSABLE; -} diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h index af3272284e852..a9a81abb54796 100644 --- a/net/mac80211/wpa.h +++ b/net/mac80211/wpa.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright 2002-2004, Instant802 Networks, Inc. + * Copyright (C) 2022 Intel Corporation */ #ifndef WPA_H @@ -39,10 +40,6 @@ ieee80211_tx_result ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx); ieee80211_rx_result ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx); -ieee80211_tx_result -ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); -ieee80211_rx_result -ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx); ieee80211_tx_result ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx);