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:
Jakub Kicinski 2022-06-10 08:57:33 -07:00
commit b97dcb8575
70 changed files with 780 additions and 831 deletions

View File

@ -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 = {

View File

@ -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,6 +652,17 @@ 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 (!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;
@ -666,7 +672,6 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
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;
@ -675,12 +680,6 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
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);
}
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) {
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);

View File

@ -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

View File

@ -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,6 +313,9 @@ static int wilc_send_connect_wid(struct wilc_vif *vif)
netdev_err(vif->ndev, "failed to send config packet\n");
goto error;
} else {
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;
}
@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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);
}

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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;
}
/*===========================================================================*/

View File

@ -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];

View File

@ -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);

View File

@ -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);

View File

@ -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",

View File

@ -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))

View File

@ -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[] = {
{

View File

@ -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

View File

@ -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",

View File

@ -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); \

View File

@ -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[] = {
{

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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[] = {
{

View File

@ -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

View File

@ -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",

View File

@ -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, \

View File

@ -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[] = {
{

View File

@ -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

View File

@ -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);

View File

@ -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));

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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;
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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -286,7 +286,6 @@ static int load_firmware_secure(struct wfx_dev *wdev)
error:
kfree(buf);
if (fw)
release_firmware(fw);
if (ret)
print_boot_status(wdev);

View File

@ -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;
}
return 0;
err:
if (skb_rx) {
dev_kfree_skb(skb_rx);
skb_rx = NULL;
}
return -1;
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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,
&params->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,
&params->crypto,
vlan->vif.type);
}
sdata->vif.bss_conf.dtim_period = params->dtim_period;

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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))
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;

View File

@ -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;

View File

@ -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);

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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);