forked from Minki/linux
wireless-next patches for v5.20
Here's a first set of patches for v5.20. This is just a queue flush, before we get things back from net-next that are causing conflicts, and then can start merging a lot of MLO (multi-link operation, part of 802.11be) code. Lots of cleanups all over. The only notable change is perhaps wilc1000 being the first driver to disable WEP (while enabling WPA3). -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAmKjUdAACgkQB8qZga/f l8RE0xAAhVNBB3r0n8bcZXNxmb/zswjyQcRV3BrSxRwfOGppB4iqHuTEx7U7iBOK 9hMacse+myVlFNncWzGnOiZ9XIIElepPATfHXYPlVOrUO5AzqvtuuZG/6cBShO+G A1YrdVPYd87WiowTovY2x7tknZYMoQYeVeGmIMIEViM0RjULkXPC9AhpKbiHoV4I Ayn97E0j2+6R/gCtlhYTm0ASvzbVVoIB9cHMwvopzEXtsIjcE5Tglgrhygtw0FI3 w2EZi5091c6IA2lc+kEmN2saAX72f6G3cewYID84/l8U2+VuwzdDUnXsyXYgGFF8 UM47qizFSrwAn7eSiUNpLK0b8um/C2+ryBBUDrhbCvlR6/8shwvV1YMSX5eo00Av rPtC7/7wXF0ox8Os+FTTqAptyWDFQMI4dYkbQjZ4KsR7/jXssReIsYLLPlYGRgU5 zemdd1onofZN4N9QXMtMxR7xwoKvPBRGqZa0YgnbSGF7dSjL+fleVlRwuhLZsWvb KJQyut9/InC9C2kKjsdK+bcv8lLmJE65PdFM5CZBLnEZvf7stOkeg2WcuqNSzjca VO7UIv8yQeJV2cpSBgmC4XchAU21r2rEzViz7PDLTFB9ZfYgcBIad9G10Mx5u11L 2GHmDX5r2X1QD91nsTqOBCn0xO67jpcgxMpiGC31VReV7BTKvSc= =E0Dx -----END PGP SIGNATURE----- Merge tag 'wireless-next-2022-06-10' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next Johannes Berg says: ==================== wireless-next patches for v5.20 Here's a first set of patches for v5.20. This is just a queue flush, before we get things back from net-next that are causing conflicts, and then can start merging a lot of MLO (multi-link operation, part of 802.11be) code. Lots of cleanups all over. The only notable change is perhaps wilc1000 being the first driver to disable WEP (while enabling WPA3). * tag 'wireless-next-2022-06-10' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (29 commits) wifi: mac80211_hwsim: Directly use ida_alloc()/free() wifi: mac80211: refactor some key code wifi: mac80211: remove cipher scheme support wifi: nl80211: fix typo in comment wifi: virt_wifi: fix typo in comment rtw89: add new state to CFO state machine for UL-OFDMA rtw89: 8852c: add trigger frame counter ieee80211: add trigger frame definition wifi: wfx: Remove redundant NULL check before release_firmware() call wifi: rtw89: support MULTI_BSSID and correct BSSID mask of H2C wifi: ray_cs: Drop useless status variable in parse_addr() wifi: ray_cs: Utilize strnlen() in parse_addr() wifi: rtw88: use %*ph to print small buffer wifi: wilc1000: add IGTK support wifi: wilc1000: add WPA3 SAE support wifi: wilc1000: remove WEP security support wifi: wilc1000: use correct sequence of RESET for chip Power-UP/Down wifi: rtlwifi: fix error codes in rtl_debugfs_set_write_h2c() wifi: rtw88: Fix Sparse warning for rtw8821c_hw_spec wifi: rtw88: Fix Sparse warning for rtw8723d_hw_spec ... ==================== Link: https://lore.kernel.org/r/20220610142838.330862-1-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
b97dcb8575
@ -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 = {
|
||||
|
@ -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;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev,
|
||||
u8 key_index)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(netdev);
|
||||
|
||||
wilc_set_wep_default_keyid(vif, key_index);
|
||||
|
||||
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);
|
||||
|
@ -41,12 +41,6 @@ struct wilc_drv_handler {
|
||||
u8 mode;
|
||||
} __packed;
|
||||
|
||||
struct wilc_wep_key {
|
||||
u8 index;
|
||||
u8 key_len;
|
||||
u8 key[];
|
||||
} __packed;
|
||||
|
||||
struct wilc_sta_wpa_ptk {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 key_len;
|
||||
@ -60,6 +54,14 @@ struct wilc_ap_wpa_ptk {
|
||||
u8 key[];
|
||||
} __packed;
|
||||
|
||||
struct wilc_wpa_igtk {
|
||||
u8 index;
|
||||
u8 pn_len;
|
||||
u8 pn[6];
|
||||
u8 key_len;
|
||||
u8 key[];
|
||||
} __packed;
|
||||
|
||||
struct wilc_gtk_key {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 rsc[8];
|
||||
@ -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
|
||||
|
@ -271,12 +271,19 @@ error:
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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))
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "pci.h"
|
||||
#include "rtw8723de.h"
|
||||
#include "rtw8723d.h"
|
||||
|
||||
static const struct pci_device_id rtw_8723de_id_table[] = {
|
||||
{
|
||||
|
@ -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
|
@ -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",
|
||||
|
@ -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); \
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "pci.h"
|
||||
#include "rtw8821ce.h"
|
||||
#include "rtw8821c.h"
|
||||
|
||||
static const struct pci_device_id rtw_8821ce_id_table[] = {
|
||||
{
|
||||
|
@ -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
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "pci.h"
|
||||
#include "rtw8822be.h"
|
||||
#include "rtw8822b.h"
|
||||
|
||||
static const struct pci_device_id rtw_8822be_id_table[] = {
|
||||
{
|
||||
|
@ -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
|
@ -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",
|
||||
|
@ -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, \
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "pci.h"
|
||||
#include "rtw8822ce.h"
|
||||
#include "rtw8822c.h"
|
||||
|
||||
static const struct pci_device_id rtw_8822ce_id_table[] = {
|
||||
{
|
||||
|
@ -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
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 (!rtwsar->set[subband])
|
||||
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_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 @@ exit:
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* 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 <linux/ieee80211.h>
|
||||
@ -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;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* 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,
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
|
||||
* 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 <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -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);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
|
||||
* 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 <linux/if_ether.h>
|
||||
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* 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 <net/mac80211.h>
|
||||
@ -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;
|
||||
|
@ -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 <luisca@cozybit.com>
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* 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 <linux/delay.h>
|
||||
@ -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 */
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* 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 <linux/jiffies.h>
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* 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);
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* 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)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright 2002-2004, Instant802 Networks, Inc.
|
||||
* Copyright 2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2020-2021 Intel Corporation
|
||||
* Copyright (C) 2020-2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user