18e93258fSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 28e93258fSBjoern A. Zeeb /* Copyright(c) 2019-2020 Realtek Corporation 38e93258fSBjoern A. Zeeb */ 48e93258fSBjoern A. Zeeb 58e93258fSBjoern A. Zeeb #include "cam.h" 68e93258fSBjoern A. Zeeb #include "debug.h" 78e93258fSBjoern A. Zeeb #include "fw.h" 88e93258fSBjoern A. Zeeb #include "mac.h" 98e93258fSBjoern A. Zeeb 108e93258fSBjoern A. Zeeb static struct sk_buff * 118e93258fSBjoern A. Zeeb rtw89_cam_get_sec_key_cmd(struct rtw89_dev *rtwdev, 128e93258fSBjoern A. Zeeb struct rtw89_sec_cam_entry *sec_cam, 138e93258fSBjoern A. Zeeb bool ext_key) 148e93258fSBjoern A. Zeeb { 158e93258fSBjoern A. Zeeb struct sk_buff *skb; 168e93258fSBjoern A. Zeeb u32 cmd_len = H2C_SEC_CAM_LEN; 178e93258fSBjoern A. Zeeb u32 key32[4]; 188e93258fSBjoern A. Zeeb u8 *cmd; 198e93258fSBjoern A. Zeeb int i, j; 208e93258fSBjoern A. Zeeb 218e93258fSBjoern A. Zeeb skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, cmd_len); 228e93258fSBjoern A. Zeeb if (!skb) 238e93258fSBjoern A. Zeeb return NULL; 248e93258fSBjoern A. Zeeb 258e93258fSBjoern A. Zeeb skb_put_zero(skb, cmd_len); 268e93258fSBjoern A. Zeeb 278e93258fSBjoern A. Zeeb for (i = 0; i < 4; i++) { 288e93258fSBjoern A. Zeeb j = i * 4; 298e93258fSBjoern A. Zeeb j += ext_key ? 16 : 0; 308e93258fSBjoern A. Zeeb key32[i] = FIELD_PREP(GENMASK(7, 0), sec_cam->key[j + 0]) | 318e93258fSBjoern A. Zeeb FIELD_PREP(GENMASK(15, 8), sec_cam->key[j + 1]) | 328e93258fSBjoern A. Zeeb FIELD_PREP(GENMASK(23, 16), sec_cam->key[j + 2]) | 338e93258fSBjoern A. Zeeb FIELD_PREP(GENMASK(31, 24), sec_cam->key[j + 3]); 348e93258fSBjoern A. Zeeb } 358e93258fSBjoern A. Zeeb 368e93258fSBjoern A. Zeeb cmd = skb->data; 378e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_IDX(cmd, sec_cam->sec_cam_idx + (ext_key ? 1 : 0)); 388e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_OFFSET(cmd, sec_cam->offset); 398e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_LEN(cmd, sec_cam->len); 408e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_TYPE(cmd, sec_cam->type); 418e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_EXT_KEY(cmd, ext_key); 428e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_SPP_MODE(cmd, sec_cam->spp_mode); 438e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_KEY0(cmd, key32[0]); 448e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_KEY1(cmd, key32[1]); 458e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_KEY2(cmd, key32[2]); 468e93258fSBjoern A. Zeeb RTW89_SET_FWCMD_SEC_KEY3(cmd, key32[3]); 478e93258fSBjoern A. Zeeb 488e93258fSBjoern A. Zeeb return skb; 498e93258fSBjoern A. Zeeb } 508e93258fSBjoern A. Zeeb 518e93258fSBjoern A. Zeeb static int rtw89_cam_send_sec_key_cmd(struct rtw89_dev *rtwdev, 528e93258fSBjoern A. Zeeb struct rtw89_sec_cam_entry *sec_cam) 538e93258fSBjoern A. Zeeb { 548e93258fSBjoern A. Zeeb struct sk_buff *skb, *ext_skb; 558e93258fSBjoern A. Zeeb int ret; 568e93258fSBjoern A. Zeeb 578e93258fSBjoern A. Zeeb skb = rtw89_cam_get_sec_key_cmd(rtwdev, sec_cam, false); 588e93258fSBjoern A. Zeeb if (!skb) { 598e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to get sec key command\n"); 608e93258fSBjoern A. Zeeb return -ENOMEM; 618e93258fSBjoern A. Zeeb } 628e93258fSBjoern A. Zeeb 638e93258fSBjoern A. Zeeb rtw89_h2c_pkt_set_hdr(rtwdev, skb, 648e93258fSBjoern A. Zeeb FWCMD_TYPE_H2C, 658e93258fSBjoern A. Zeeb H2C_CAT_MAC, 668e93258fSBjoern A. Zeeb H2C_CL_MAC_SEC_CAM, 678e93258fSBjoern A. Zeeb H2C_FUNC_MAC_SEC_UPD, 1, 0, 688e93258fSBjoern A. Zeeb H2C_SEC_CAM_LEN); 698e93258fSBjoern A. Zeeb ret = rtw89_h2c_tx(rtwdev, skb, false); 708e93258fSBjoern A. Zeeb if (ret) { 718e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to send sec key h2c: %d\n", ret); 728e93258fSBjoern A. Zeeb dev_kfree_skb(skb); 738e93258fSBjoern A. Zeeb return ret; 748e93258fSBjoern A. Zeeb } 758e93258fSBjoern A. Zeeb 768e93258fSBjoern A. Zeeb if (!sec_cam->ext_key) 778e93258fSBjoern A. Zeeb return 0; 788e93258fSBjoern A. Zeeb 798e93258fSBjoern A. Zeeb ext_skb = rtw89_cam_get_sec_key_cmd(rtwdev, sec_cam, true); 808e93258fSBjoern A. Zeeb if (!ext_skb) { 818e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to get ext sec key command\n"); 828e93258fSBjoern A. Zeeb return -ENOMEM; 838e93258fSBjoern A. Zeeb } 848e93258fSBjoern A. Zeeb 858e93258fSBjoern A. Zeeb rtw89_h2c_pkt_set_hdr(rtwdev, ext_skb, 868e93258fSBjoern A. Zeeb FWCMD_TYPE_H2C, 878e93258fSBjoern A. Zeeb H2C_CAT_MAC, 888e93258fSBjoern A. Zeeb H2C_CL_MAC_SEC_CAM, 898e93258fSBjoern A. Zeeb H2C_FUNC_MAC_SEC_UPD, 908e93258fSBjoern A. Zeeb 1, 0, H2C_SEC_CAM_LEN); 918e93258fSBjoern A. Zeeb ret = rtw89_h2c_tx(rtwdev, ext_skb, false); 928e93258fSBjoern A. Zeeb if (ret) { 938e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to send ext sec key h2c: %d\n", ret); 948e93258fSBjoern A. Zeeb dev_kfree_skb(ext_skb); 958e93258fSBjoern A. Zeeb return ret; 968e93258fSBjoern A. Zeeb } 978e93258fSBjoern A. Zeeb 988e93258fSBjoern A. Zeeb return 0; 998e93258fSBjoern A. Zeeb } 1008e93258fSBjoern A. Zeeb 1018e93258fSBjoern A. Zeeb static int rtw89_cam_get_avail_sec_cam(struct rtw89_dev *rtwdev, 1028e93258fSBjoern A. Zeeb u8 *sec_cam_idx, bool ext_key) 1038e93258fSBjoern A. Zeeb { 1048e93258fSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 1058e93258fSBjoern A. Zeeb struct rtw89_cam_info *cam_info = &rtwdev->cam_info; 1068e93258fSBjoern A. Zeeb u8 sec_cam_num = chip->scam_num; 1078e93258fSBjoern A. Zeeb u8 idx = 0; 1088e93258fSBjoern A. Zeeb 1098e93258fSBjoern A. Zeeb if (!ext_key) { 1108e93258fSBjoern A. Zeeb idx = find_first_zero_bit(cam_info->sec_cam_map, sec_cam_num); 1118e93258fSBjoern A. Zeeb if (idx >= sec_cam_num) 1128e93258fSBjoern A. Zeeb return -EBUSY; 1138e93258fSBjoern A. Zeeb 1148e93258fSBjoern A. Zeeb set_bit(idx, cam_info->sec_cam_map); 1158e93258fSBjoern A. Zeeb *sec_cam_idx = idx; 1168e93258fSBjoern A. Zeeb 1178e93258fSBjoern A. Zeeb return 0; 1188e93258fSBjoern A. Zeeb } 1198e93258fSBjoern A. Zeeb 1208e93258fSBjoern A. Zeeb again: 1218e93258fSBjoern A. Zeeb idx = find_next_zero_bit(cam_info->sec_cam_map, sec_cam_num, idx); 1228e93258fSBjoern A. Zeeb if (idx >= sec_cam_num - 1) 1238e93258fSBjoern A. Zeeb return -EBUSY; 1248e93258fSBjoern A. Zeeb /* ext keys need two cam entries for 256-bit key */ 1258e93258fSBjoern A. Zeeb if (test_bit(idx + 1, cam_info->sec_cam_map)) { 1268e93258fSBjoern A. Zeeb idx++; 1278e93258fSBjoern A. Zeeb goto again; 1288e93258fSBjoern A. Zeeb } 1298e93258fSBjoern A. Zeeb 1308e93258fSBjoern A. Zeeb set_bit(idx, cam_info->sec_cam_map); 1318e93258fSBjoern A. Zeeb set_bit(idx + 1, cam_info->sec_cam_map); 1328e93258fSBjoern A. Zeeb *sec_cam_idx = idx; 1338e93258fSBjoern A. Zeeb 1348e93258fSBjoern A. Zeeb return 0; 1358e93258fSBjoern A. Zeeb } 1368e93258fSBjoern A. Zeeb 1378e93258fSBjoern A. Zeeb static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam, 1388e93258fSBjoern A. Zeeb struct rtw89_sec_cam_entry *sec_cam, 1398e93258fSBjoern A. Zeeb struct ieee80211_key_conf *key, 1408e93258fSBjoern A. Zeeb u8 *key_idx) 1418e93258fSBjoern A. Zeeb { 1428e93258fSBjoern A. Zeeb u8 idx; 1438e93258fSBjoern A. Zeeb 1448e93258fSBjoern A. Zeeb /* RTW89_ADDR_CAM_SEC_NONE : not enabled 1458e93258fSBjoern A. Zeeb * RTW89_ADDR_CAM_SEC_ALL_UNI : 0 - 6 unicast 1468e93258fSBjoern A. Zeeb * RTW89_ADDR_CAM_SEC_NORMAL : 0 - 1 unicast, 2 - 4 group, 5 - 6 BIP 1478e93258fSBjoern A. Zeeb * RTW89_ADDR_CAM_SEC_4GROUP : 0 - 1 unicast, 2 - 5 group, 6 BIP 1488e93258fSBjoern A. Zeeb */ 1498e93258fSBjoern A. Zeeb switch (addr_cam->sec_ent_mode) { 1508e93258fSBjoern A. Zeeb case RTW89_ADDR_CAM_SEC_NONE: 1518e93258fSBjoern A. Zeeb return -EINVAL; 1528e93258fSBjoern A. Zeeb case RTW89_ADDR_CAM_SEC_ALL_UNI: 1538e93258fSBjoern A. Zeeb idx = find_first_zero_bit(addr_cam->sec_cam_map, 1548e93258fSBjoern A. Zeeb RTW89_SEC_CAM_IN_ADDR_CAM); 1558e93258fSBjoern A. Zeeb if (idx >= RTW89_SEC_CAM_IN_ADDR_CAM) 1568e93258fSBjoern A. Zeeb return -EBUSY; 1578e93258fSBjoern A. Zeeb *key_idx = idx; 1588e93258fSBjoern A. Zeeb break; 1598e93258fSBjoern A. Zeeb case RTW89_ADDR_CAM_SEC_NORMAL: 1608e93258fSBjoern A. Zeeb if (sec_cam->type == RTW89_SEC_KEY_TYPE_BIP_CCMP128) { 1618e93258fSBjoern A. Zeeb idx = find_next_zero_bit(addr_cam->sec_cam_map, 1628e93258fSBjoern A. Zeeb RTW89_SEC_CAM_IN_ADDR_CAM, 5); 1638e93258fSBjoern A. Zeeb if (idx > 6) 1648e93258fSBjoern A. Zeeb return -EBUSY; 1658e93258fSBjoern A. Zeeb *key_idx = idx; 1668e93258fSBjoern A. Zeeb break; 1678e93258fSBjoern A. Zeeb } 1688e93258fSBjoern A. Zeeb 1698e93258fSBjoern A. Zeeb if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { 1708e93258fSBjoern A. Zeeb idx = find_next_zero_bit(addr_cam->sec_cam_map, 1718e93258fSBjoern A. Zeeb RTW89_SEC_CAM_IN_ADDR_CAM, 0); 1728e93258fSBjoern A. Zeeb if (idx > 1) 1738e93258fSBjoern A. Zeeb return -EBUSY; 1748e93258fSBjoern A. Zeeb *key_idx = idx; 1758e93258fSBjoern A. Zeeb break; 1768e93258fSBjoern A. Zeeb } 1778e93258fSBjoern A. Zeeb 1788e93258fSBjoern A. Zeeb /* Group keys */ 1798e93258fSBjoern A. Zeeb idx = find_next_zero_bit(addr_cam->sec_cam_map, 1808e93258fSBjoern A. Zeeb RTW89_SEC_CAM_IN_ADDR_CAM, 2); 1818e93258fSBjoern A. Zeeb if (idx > 4) 1828e93258fSBjoern A. Zeeb return -EBUSY; 1838e93258fSBjoern A. Zeeb *key_idx = idx; 1848e93258fSBjoern A. Zeeb break; 1858e93258fSBjoern A. Zeeb case RTW89_ADDR_CAM_SEC_4GROUP: 1868e93258fSBjoern A. Zeeb if (sec_cam->type == RTW89_SEC_KEY_TYPE_BIP_CCMP128) { 1878e93258fSBjoern A. Zeeb if (test_bit(6, addr_cam->sec_cam_map)) 1888e93258fSBjoern A. Zeeb return -EINVAL; 1898e93258fSBjoern A. Zeeb *key_idx = 6; 1908e93258fSBjoern A. Zeeb break; 1918e93258fSBjoern A. Zeeb } 1928e93258fSBjoern A. Zeeb 1938e93258fSBjoern A. Zeeb if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { 1948e93258fSBjoern A. Zeeb idx = find_next_zero_bit(addr_cam->sec_cam_map, 1958e93258fSBjoern A. Zeeb RTW89_SEC_CAM_IN_ADDR_CAM, 0); 1968e93258fSBjoern A. Zeeb if (idx > 1) 1978e93258fSBjoern A. Zeeb return -EBUSY; 1988e93258fSBjoern A. Zeeb *key_idx = idx; 1998e93258fSBjoern A. Zeeb break; 2008e93258fSBjoern A. Zeeb } 2018e93258fSBjoern A. Zeeb 2028e93258fSBjoern A. Zeeb /* Group keys */ 2038e93258fSBjoern A. Zeeb idx = find_next_zero_bit(addr_cam->sec_cam_map, 2048e93258fSBjoern A. Zeeb RTW89_SEC_CAM_IN_ADDR_CAM, 2); 2058e93258fSBjoern A. Zeeb if (idx > 5) 2068e93258fSBjoern A. Zeeb return -EBUSY; 2078e93258fSBjoern A. Zeeb *key_idx = idx; 2088e93258fSBjoern A. Zeeb break; 2098e93258fSBjoern A. Zeeb } 2108e93258fSBjoern A. Zeeb 2118e93258fSBjoern A. Zeeb return 0; 2128e93258fSBjoern A. Zeeb } 2138e93258fSBjoern A. Zeeb 214*6d67aabdSBjoern A. Zeeb static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, 215*6d67aabdSBjoern A. Zeeb struct ieee80211_vif *vif, 216*6d67aabdSBjoern A. Zeeb struct ieee80211_sta *sta, 217*6d67aabdSBjoern A. Zeeb const struct rtw89_sec_cam_entry *sec_cam, 218*6d67aabdSBjoern A. Zeeb bool inform_fw) 219*6d67aabdSBjoern A. Zeeb { 220*6d67aabdSBjoern A. Zeeb struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); 221*6d67aabdSBjoern A. Zeeb struct rtw89_vif *rtwvif; 222*6d67aabdSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam; 223*6d67aabdSBjoern A. Zeeb unsigned int i; 224*6d67aabdSBjoern A. Zeeb int ret = 0; 225*6d67aabdSBjoern A. Zeeb 226*6d67aabdSBjoern A. Zeeb if (!vif) { 227*6d67aabdSBjoern A. Zeeb rtw89_err(rtwdev, "No iface for deleting sec cam\n"); 228*6d67aabdSBjoern A. Zeeb return -EINVAL; 229*6d67aabdSBjoern A. Zeeb } 230*6d67aabdSBjoern A. Zeeb 231*6d67aabdSBjoern A. Zeeb rtwvif = (struct rtw89_vif *)vif->drv_priv; 232*6d67aabdSBjoern A. Zeeb addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); 233*6d67aabdSBjoern A. Zeeb 234*6d67aabdSBjoern A. Zeeb for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) { 235*6d67aabdSBjoern A. Zeeb if (addr_cam->sec_ent[i] != sec_cam->sec_cam_idx) 236*6d67aabdSBjoern A. Zeeb continue; 237*6d67aabdSBjoern A. Zeeb 238*6d67aabdSBjoern A. Zeeb clear_bit(i, addr_cam->sec_cam_map); 239*6d67aabdSBjoern A. Zeeb } 240*6d67aabdSBjoern A. Zeeb 241*6d67aabdSBjoern A. Zeeb if (inform_fw) { 242*6d67aabdSBjoern A. Zeeb ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); 243*6d67aabdSBjoern A. Zeeb if (ret) 244*6d67aabdSBjoern A. Zeeb rtw89_err(rtwdev, 245*6d67aabdSBjoern A. Zeeb "failed to update dctl cam del key: %d\n", ret); 246*6d67aabdSBjoern A. Zeeb ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); 247*6d67aabdSBjoern A. Zeeb if (ret) 248*6d67aabdSBjoern A. Zeeb rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret); 249*6d67aabdSBjoern A. Zeeb } 250*6d67aabdSBjoern A. Zeeb 251*6d67aabdSBjoern A. Zeeb return ret; 252*6d67aabdSBjoern A. Zeeb } 253*6d67aabdSBjoern A. Zeeb 2548e93258fSBjoern A. Zeeb static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, 2558e93258fSBjoern A. Zeeb struct ieee80211_vif *vif, 2568e93258fSBjoern A. Zeeb struct ieee80211_sta *sta, 2578e93258fSBjoern A. Zeeb struct ieee80211_key_conf *key, 2588e93258fSBjoern A. Zeeb struct rtw89_sec_cam_entry *sec_cam) 2598e93258fSBjoern A. Zeeb { 2608e93258fSBjoern A. Zeeb struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); 2618e93258fSBjoern A. Zeeb struct rtw89_vif *rtwvif; 2628e93258fSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam; 2638e93258fSBjoern A. Zeeb u8 key_idx = 0; 2648e93258fSBjoern A. Zeeb int ret; 2658e93258fSBjoern A. Zeeb 2668e93258fSBjoern A. Zeeb if (!vif) { 2678e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "No iface for adding sec cam\n"); 2688e93258fSBjoern A. Zeeb return -EINVAL; 2698e93258fSBjoern A. Zeeb } 2708e93258fSBjoern A. Zeeb 2718e93258fSBjoern A. Zeeb rtwvif = (struct rtw89_vif *)vif->drv_priv; 2728e93258fSBjoern A. Zeeb addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); 273*6d67aabdSBjoern A. Zeeb 274*6d67aabdSBjoern A. Zeeb if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || 275*6d67aabdSBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_WEP104) 276*6d67aabdSBjoern A. Zeeb addr_cam->sec_ent_mode = RTW89_ADDR_CAM_SEC_ALL_UNI; 277*6d67aabdSBjoern A. Zeeb 2788e93258fSBjoern A. Zeeb ret = rtw89_cam_get_addr_cam_key_idx(addr_cam, sec_cam, key, &key_idx); 2798e93258fSBjoern A. Zeeb if (ret) { 2808e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to get addr cam key idx %d, %d\n", 2818e93258fSBjoern A. Zeeb addr_cam->sec_ent_mode, sec_cam->type); 2828e93258fSBjoern A. Zeeb return ret; 2838e93258fSBjoern A. Zeeb } 2848e93258fSBjoern A. Zeeb 2858e93258fSBjoern A. Zeeb addr_cam->sec_ent_keyid[key_idx] = key->keyidx; 2868e93258fSBjoern A. Zeeb addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx; 2878e93258fSBjoern A. Zeeb set_bit(key_idx, addr_cam->sec_cam_map); 2888e93258fSBjoern A. Zeeb ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); 2898e93258fSBjoern A. Zeeb if (ret) { 2908e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", 2918e93258fSBjoern A. Zeeb ret); 2928e93258fSBjoern A. Zeeb return ret; 2938e93258fSBjoern A. Zeeb } 2948e93258fSBjoern A. Zeeb ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); 2958e93258fSBjoern A. Zeeb if (ret) { 2968e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n", 2978e93258fSBjoern A. Zeeb ret); 2988e93258fSBjoern A. Zeeb clear_bit(key_idx, addr_cam->sec_cam_map); 2998e93258fSBjoern A. Zeeb return ret; 3008e93258fSBjoern A. Zeeb } 3018e93258fSBjoern A. Zeeb 3028e93258fSBjoern A. Zeeb return 0; 3038e93258fSBjoern A. Zeeb } 3048e93258fSBjoern A. Zeeb 3058e93258fSBjoern A. Zeeb static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev, 3068e93258fSBjoern A. Zeeb struct ieee80211_vif *vif, 3078e93258fSBjoern A. Zeeb struct ieee80211_sta *sta, 3088e93258fSBjoern A. Zeeb struct ieee80211_key_conf *key, 3098e93258fSBjoern A. Zeeb u8 hw_key_type, bool ext_key) 3108e93258fSBjoern A. Zeeb { 3118e93258fSBjoern A. Zeeb struct rtw89_sec_cam_entry *sec_cam = NULL; 3128e93258fSBjoern A. Zeeb struct rtw89_cam_info *cam_info = &rtwdev->cam_info; 3138e93258fSBjoern A. Zeeb u8 sec_cam_idx; 3148e93258fSBjoern A. Zeeb int ret; 3158e93258fSBjoern A. Zeeb 3168e93258fSBjoern A. Zeeb /* maximum key length 256-bit */ 3178e93258fSBjoern A. Zeeb if (key->keylen > 32) { 3188e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "invalid sec key length %d\n", key->keylen); 3198e93258fSBjoern A. Zeeb return -EINVAL; 3208e93258fSBjoern A. Zeeb } 3218e93258fSBjoern A. Zeeb 3228e93258fSBjoern A. Zeeb ret = rtw89_cam_get_avail_sec_cam(rtwdev, &sec_cam_idx, ext_key); 3238e93258fSBjoern A. Zeeb if (ret) { 3248e93258fSBjoern A. Zeeb rtw89_warn(rtwdev, "no available sec cam: %d ext: %d\n", 3258e93258fSBjoern A. Zeeb ret, ext_key); 3268e93258fSBjoern A. Zeeb return ret; 3278e93258fSBjoern A. Zeeb } 3288e93258fSBjoern A. Zeeb 3298e93258fSBjoern A. Zeeb sec_cam = kzalloc(sizeof(*sec_cam), GFP_KERNEL); 3308e93258fSBjoern A. Zeeb if (!sec_cam) { 3318e93258fSBjoern A. Zeeb ret = -ENOMEM; 3328e93258fSBjoern A. Zeeb goto err_release_cam; 3338e93258fSBjoern A. Zeeb } 3348e93258fSBjoern A. Zeeb 335*6d67aabdSBjoern A. Zeeb key->hw_key_idx = sec_cam_idx; 336*6d67aabdSBjoern A. Zeeb cam_info->sec_entries[sec_cam_idx] = sec_cam; 337*6d67aabdSBjoern A. Zeeb 3388e93258fSBjoern A. Zeeb sec_cam->sec_cam_idx = sec_cam_idx; 3398e93258fSBjoern A. Zeeb sec_cam->type = hw_key_type; 3408e93258fSBjoern A. Zeeb sec_cam->len = RTW89_SEC_CAM_LEN; 3418e93258fSBjoern A. Zeeb sec_cam->ext_key = ext_key; 3428e93258fSBjoern A. Zeeb memcpy(sec_cam->key, key->key, key->keylen); 3438e93258fSBjoern A. Zeeb ret = rtw89_cam_send_sec_key_cmd(rtwdev, sec_cam); 3448e93258fSBjoern A. Zeeb if (ret) { 3458e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to send sec key cmd: %d\n", ret); 3468e93258fSBjoern A. Zeeb goto err_release_cam; 3478e93258fSBjoern A. Zeeb } 3488e93258fSBjoern A. Zeeb 3498e93258fSBjoern A. Zeeb /* associate with addr cam */ 3508e93258fSBjoern A. Zeeb ret = rtw89_cam_attach_sec_cam(rtwdev, vif, sta, key, sec_cam); 3518e93258fSBjoern A. Zeeb if (ret) { 3528e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to attach sec cam: %d\n", ret); 3538e93258fSBjoern A. Zeeb goto err_release_cam; 3548e93258fSBjoern A. Zeeb } 3558e93258fSBjoern A. Zeeb 3568e93258fSBjoern A. Zeeb return 0; 3578e93258fSBjoern A. Zeeb 3588e93258fSBjoern A. Zeeb err_release_cam: 359*6d67aabdSBjoern A. Zeeb cam_info->sec_entries[sec_cam_idx] = NULL; 3608e93258fSBjoern A. Zeeb kfree(sec_cam); 3618e93258fSBjoern A. Zeeb clear_bit(sec_cam_idx, cam_info->sec_cam_map); 3628e93258fSBjoern A. Zeeb if (ext_key) 3638e93258fSBjoern A. Zeeb clear_bit(sec_cam_idx + 1, cam_info->sec_cam_map); 3648e93258fSBjoern A. Zeeb 3658e93258fSBjoern A. Zeeb return ret; 3668e93258fSBjoern A. Zeeb } 3678e93258fSBjoern A. Zeeb 3688e93258fSBjoern A. Zeeb int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev, 3698e93258fSBjoern A. Zeeb struct ieee80211_vif *vif, 3708e93258fSBjoern A. Zeeb struct ieee80211_sta *sta, 3718e93258fSBjoern A. Zeeb struct ieee80211_key_conf *key) 3728e93258fSBjoern A. Zeeb { 3738e93258fSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 3748e93258fSBjoern A. Zeeb u8 hw_key_type; 3758e93258fSBjoern A. Zeeb bool ext_key = false; 3768e93258fSBjoern A. Zeeb int ret; 3778e93258fSBjoern A. Zeeb 3788e93258fSBjoern A. Zeeb switch (key->cipher) { 3798e93258fSBjoern A. Zeeb case WLAN_CIPHER_SUITE_WEP40: 3808e93258fSBjoern A. Zeeb hw_key_type = RTW89_SEC_KEY_TYPE_WEP40; 3818e93258fSBjoern A. Zeeb break; 3828e93258fSBjoern A. Zeeb case WLAN_CIPHER_SUITE_WEP104: 3838e93258fSBjoern A. Zeeb hw_key_type = RTW89_SEC_KEY_TYPE_WEP104; 3848e93258fSBjoern A. Zeeb break; 3858e93258fSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP: 3868e93258fSBjoern A. Zeeb hw_key_type = RTW89_SEC_KEY_TYPE_CCMP128; 3878e93258fSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; 3888e93258fSBjoern A. Zeeb break; 3898e93258fSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP_256: 3908e93258fSBjoern A. Zeeb hw_key_type = RTW89_SEC_KEY_TYPE_CCMP256; 3918e93258fSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; 3928e93258fSBjoern A. Zeeb ext_key = true; 3938e93258fSBjoern A. Zeeb break; 3948e93258fSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP: 3958e93258fSBjoern A. Zeeb hw_key_type = RTW89_SEC_KEY_TYPE_GCMP128; 3968e93258fSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; 3978e93258fSBjoern A. Zeeb break; 3988e93258fSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP_256: 3998e93258fSBjoern A. Zeeb hw_key_type = RTW89_SEC_KEY_TYPE_GCMP256; 4008e93258fSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; 4018e93258fSBjoern A. Zeeb ext_key = true; 4028e93258fSBjoern A. Zeeb break; 403*6d67aabdSBjoern A. Zeeb case WLAN_CIPHER_SUITE_AES_CMAC: 404*6d67aabdSBjoern A. Zeeb hw_key_type = RTW89_SEC_KEY_TYPE_BIP_CCMP128; 405*6d67aabdSBjoern A. Zeeb break; 4068e93258fSBjoern A. Zeeb default: 4078e93258fSBjoern A. Zeeb return -EOPNOTSUPP; 4088e93258fSBjoern A. Zeeb } 4098e93258fSBjoern A. Zeeb 4108e93258fSBjoern A. Zeeb if (!chip->hw_sec_hdr) 4118e93258fSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 4128e93258fSBjoern A. Zeeb 4138e93258fSBjoern A. Zeeb ret = rtw89_cam_sec_key_install(rtwdev, vif, sta, key, hw_key_type, 4148e93258fSBjoern A. Zeeb ext_key); 4158e93258fSBjoern A. Zeeb if (ret) { 4168e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to install key type %d ext %d: %d\n", 4178e93258fSBjoern A. Zeeb hw_key_type, ext_key, ret); 4188e93258fSBjoern A. Zeeb return ret; 4198e93258fSBjoern A. Zeeb } 4208e93258fSBjoern A. Zeeb 4218e93258fSBjoern A. Zeeb return 0; 4228e93258fSBjoern A. Zeeb } 4238e93258fSBjoern A. Zeeb 4248e93258fSBjoern A. Zeeb int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev, 4258e93258fSBjoern A. Zeeb struct ieee80211_vif *vif, 4268e93258fSBjoern A. Zeeb struct ieee80211_sta *sta, 4278e93258fSBjoern A. Zeeb struct ieee80211_key_conf *key, 4288e93258fSBjoern A. Zeeb bool inform_fw) 4298e93258fSBjoern A. Zeeb { 4308e93258fSBjoern A. Zeeb struct rtw89_cam_info *cam_info = &rtwdev->cam_info; 431*6d67aabdSBjoern A. Zeeb const struct rtw89_sec_cam_entry *sec_cam; 4328e93258fSBjoern A. Zeeb u8 sec_cam_idx; 433*6d67aabdSBjoern A. Zeeb int ret; 4348e93258fSBjoern A. Zeeb 435*6d67aabdSBjoern A. Zeeb sec_cam_idx = key->hw_key_idx; 436*6d67aabdSBjoern A. Zeeb sec_cam = cam_info->sec_entries[sec_cam_idx]; 4378e93258fSBjoern A. Zeeb if (!sec_cam) 4388e93258fSBjoern A. Zeeb return -EINVAL; 4398e93258fSBjoern A. Zeeb 440*6d67aabdSBjoern A. Zeeb ret = rtw89_cam_detach_sec_cam(rtwdev, vif, sta, sec_cam, inform_fw); 4418e93258fSBjoern A. Zeeb 4428e93258fSBjoern A. Zeeb /* clear valid bit in addr cam will disable sec cam, 4438e93258fSBjoern A. Zeeb * so we don't need to send H2C command again 4448e93258fSBjoern A. Zeeb */ 445*6d67aabdSBjoern A. Zeeb cam_info->sec_entries[sec_cam_idx] = NULL; 4468e93258fSBjoern A. Zeeb clear_bit(sec_cam_idx, cam_info->sec_cam_map); 4478e93258fSBjoern A. Zeeb if (sec_cam->ext_key) 4488e93258fSBjoern A. Zeeb clear_bit(sec_cam_idx + 1, cam_info->sec_cam_map); 4498e93258fSBjoern A. Zeeb 4508e93258fSBjoern A. Zeeb kfree(sec_cam); 4518e93258fSBjoern A. Zeeb 4528e93258fSBjoern A. Zeeb return ret; 4538e93258fSBjoern A. Zeeb } 4548e93258fSBjoern A. Zeeb 4558e93258fSBjoern A. Zeeb static void rtw89_cam_reset_key_iter(struct ieee80211_hw *hw, 4568e93258fSBjoern A. Zeeb struct ieee80211_vif *vif, 4578e93258fSBjoern A. Zeeb struct ieee80211_sta *sta, 4588e93258fSBjoern A. Zeeb struct ieee80211_key_conf *key, 4598e93258fSBjoern A. Zeeb void *data) 4608e93258fSBjoern A. Zeeb { 4618e93258fSBjoern A. Zeeb struct rtw89_dev *rtwdev = (struct rtw89_dev *)data; 4628e93258fSBjoern A. Zeeb 4638e93258fSBjoern A. Zeeb rtw89_cam_sec_key_del(rtwdev, vif, sta, key, false); 4648e93258fSBjoern A. Zeeb } 4658e93258fSBjoern A. Zeeb 4668e93258fSBjoern A. Zeeb void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev, 4678e93258fSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam) 4688e93258fSBjoern A. Zeeb { 4698e93258fSBjoern A. Zeeb struct rtw89_cam_info *cam_info = &rtwdev->cam_info; 4708e93258fSBjoern A. Zeeb 4718e93258fSBjoern A. Zeeb addr_cam->valid = false; 4728e93258fSBjoern A. Zeeb clear_bit(addr_cam->addr_cam_idx, cam_info->addr_cam_map); 4738e93258fSBjoern A. Zeeb } 4748e93258fSBjoern A. Zeeb 4758e93258fSBjoern A. Zeeb void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, 4768e93258fSBjoern A. Zeeb struct rtw89_bssid_cam_entry *bssid_cam) 4778e93258fSBjoern A. Zeeb { 4788e93258fSBjoern A. Zeeb struct rtw89_cam_info *cam_info = &rtwdev->cam_info; 4798e93258fSBjoern A. Zeeb 4808e93258fSBjoern A. Zeeb bssid_cam->valid = false; 4818e93258fSBjoern A. Zeeb clear_bit(bssid_cam->bssid_cam_idx, cam_info->bssid_cam_map); 4828e93258fSBjoern A. Zeeb } 4838e93258fSBjoern A. Zeeb 4848e93258fSBjoern A. Zeeb void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) 4858e93258fSBjoern A. Zeeb { 4868e93258fSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam; 4878e93258fSBjoern A. Zeeb struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; 4888e93258fSBjoern A. Zeeb 4898e93258fSBjoern A. Zeeb rtw89_cam_deinit_addr_cam(rtwdev, addr_cam); 4908e93258fSBjoern A. Zeeb rtw89_cam_deinit_bssid_cam(rtwdev, bssid_cam); 4918e93258fSBjoern A. Zeeb } 4928e93258fSBjoern A. Zeeb 4938e93258fSBjoern A. Zeeb void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev) 4948e93258fSBjoern A. Zeeb { 4958e93258fSBjoern A. Zeeb rcu_read_lock(); 4968e93258fSBjoern A. Zeeb ieee80211_iter_keys_rcu(rtwdev->hw, NULL, rtw89_cam_reset_key_iter, rtwdev); 4978e93258fSBjoern A. Zeeb rcu_read_unlock(); 4988e93258fSBjoern A. Zeeb } 4998e93258fSBjoern A. Zeeb 5008e93258fSBjoern A. Zeeb static int rtw89_cam_get_avail_addr_cam(struct rtw89_dev *rtwdev, 5018e93258fSBjoern A. Zeeb u8 *addr_cam_idx) 5028e93258fSBjoern A. Zeeb { 5038e93258fSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 5048e93258fSBjoern A. Zeeb struct rtw89_cam_info *cam_info = &rtwdev->cam_info; 5058e93258fSBjoern A. Zeeb u8 addr_cam_num = chip->acam_num; 5068e93258fSBjoern A. Zeeb u8 idx; 5078e93258fSBjoern A. Zeeb 5088e93258fSBjoern A. Zeeb idx = find_first_zero_bit(cam_info->addr_cam_map, addr_cam_num); 5098e93258fSBjoern A. Zeeb if (idx >= addr_cam_num) 5108e93258fSBjoern A. Zeeb return -EBUSY; 5118e93258fSBjoern A. Zeeb 5128e93258fSBjoern A. Zeeb set_bit(idx, cam_info->addr_cam_map); 5138e93258fSBjoern A. Zeeb *addr_cam_idx = idx; 5148e93258fSBjoern A. Zeeb 5158e93258fSBjoern A. Zeeb return 0; 5168e93258fSBjoern A. Zeeb } 5178e93258fSBjoern A. Zeeb 518*6d67aabdSBjoern A. Zeeb static u8 rtw89_get_addr_cam_entry_size(struct rtw89_dev *rtwdev) 519*6d67aabdSBjoern A. Zeeb { 520*6d67aabdSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 521*6d67aabdSBjoern A. Zeeb 522*6d67aabdSBjoern A. Zeeb switch (chip->chip_id) { 523*6d67aabdSBjoern A. Zeeb case RTL8852A: 524*6d67aabdSBjoern A. Zeeb case RTL8852B: 525*6d67aabdSBjoern A. Zeeb case RTL8851B: 526*6d67aabdSBjoern A. Zeeb case RTL8852BT: 527*6d67aabdSBjoern A. Zeeb return ADDR_CAM_ENT_SIZE; 528*6d67aabdSBjoern A. Zeeb default: 529*6d67aabdSBjoern A. Zeeb return ADDR_CAM_ENT_SHORT_SIZE; 530*6d67aabdSBjoern A. Zeeb } 531*6d67aabdSBjoern A. Zeeb } 532*6d67aabdSBjoern A. Zeeb 5338e93258fSBjoern A. Zeeb int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev, 5348e93258fSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam, 5358e93258fSBjoern A. Zeeb const struct rtw89_bssid_cam_entry *bssid_cam) 5368e93258fSBjoern A. Zeeb { 5378e93258fSBjoern A. Zeeb u8 addr_cam_idx; 5388e93258fSBjoern A. Zeeb int i; 5398e93258fSBjoern A. Zeeb int ret; 5408e93258fSBjoern A. Zeeb 5418e93258fSBjoern A. Zeeb if (unlikely(addr_cam->valid)) { 5428e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_FW, 5438e93258fSBjoern A. Zeeb "addr cam is already valid; skip init\n"); 5448e93258fSBjoern A. Zeeb return 0; 5458e93258fSBjoern A. Zeeb } 5468e93258fSBjoern A. Zeeb 5478e93258fSBjoern A. Zeeb ret = rtw89_cam_get_avail_addr_cam(rtwdev, &addr_cam_idx); 5488e93258fSBjoern A. Zeeb if (ret) { 5498e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to get available addr cam\n"); 5508e93258fSBjoern A. Zeeb return ret; 5518e93258fSBjoern A. Zeeb } 5528e93258fSBjoern A. Zeeb 5538e93258fSBjoern A. Zeeb addr_cam->addr_cam_idx = addr_cam_idx; 554*6d67aabdSBjoern A. Zeeb addr_cam->len = rtw89_get_addr_cam_entry_size(rtwdev); 5558e93258fSBjoern A. Zeeb addr_cam->offset = 0; 5568e93258fSBjoern A. Zeeb addr_cam->valid = true; 5578e93258fSBjoern A. Zeeb addr_cam->addr_mask = 0; 5588e93258fSBjoern A. Zeeb addr_cam->mask_sel = RTW89_NO_MSK; 5598e93258fSBjoern A. Zeeb addr_cam->sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL; 5608e93258fSBjoern A. Zeeb bitmap_zero(addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM); 5618e93258fSBjoern A. Zeeb 5628e93258fSBjoern A. Zeeb for (i = 0; i < RTW89_SEC_CAM_IN_ADDR_CAM; i++) { 5638e93258fSBjoern A. Zeeb addr_cam->sec_ent_keyid[i] = 0; 5648e93258fSBjoern A. Zeeb addr_cam->sec_ent[i] = 0; 5658e93258fSBjoern A. Zeeb } 5668e93258fSBjoern A. Zeeb 5678e93258fSBjoern A. Zeeb /* associate addr cam with bssid cam */ 5688e93258fSBjoern A. Zeeb addr_cam->bssid_cam_idx = bssid_cam->bssid_cam_idx; 5698e93258fSBjoern A. Zeeb 5708e93258fSBjoern A. Zeeb return 0; 5718e93258fSBjoern A. Zeeb } 5728e93258fSBjoern A. Zeeb 5738e93258fSBjoern A. Zeeb static int rtw89_cam_get_avail_bssid_cam(struct rtw89_dev *rtwdev, 5748e93258fSBjoern A. Zeeb u8 *bssid_cam_idx) 5758e93258fSBjoern A. Zeeb { 5768e93258fSBjoern A. Zeeb const struct rtw89_chip_info *chip = rtwdev->chip; 5778e93258fSBjoern A. Zeeb struct rtw89_cam_info *cam_info = &rtwdev->cam_info; 5788e93258fSBjoern A. Zeeb u8 bssid_cam_num = chip->bcam_num; 5798e93258fSBjoern A. Zeeb u8 idx; 5808e93258fSBjoern A. Zeeb 5818e93258fSBjoern A. Zeeb idx = find_first_zero_bit(cam_info->bssid_cam_map, bssid_cam_num); 5828e93258fSBjoern A. Zeeb if (idx >= bssid_cam_num) 5838e93258fSBjoern A. Zeeb return -EBUSY; 5848e93258fSBjoern A. Zeeb 5858e93258fSBjoern A. Zeeb set_bit(idx, cam_info->bssid_cam_map); 5868e93258fSBjoern A. Zeeb *bssid_cam_idx = idx; 5878e93258fSBjoern A. Zeeb 5888e93258fSBjoern A. Zeeb return 0; 5898e93258fSBjoern A. Zeeb } 5908e93258fSBjoern A. Zeeb 5918e93258fSBjoern A. Zeeb int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, 5928e93258fSBjoern A. Zeeb struct rtw89_vif *rtwvif, 5938e93258fSBjoern A. Zeeb struct rtw89_bssid_cam_entry *bssid_cam, 5948e93258fSBjoern A. Zeeb const u8 *bssid) 5958e93258fSBjoern A. Zeeb { 5968e93258fSBjoern A. Zeeb u8 bssid_cam_idx; 5978e93258fSBjoern A. Zeeb int ret; 5988e93258fSBjoern A. Zeeb 5998e93258fSBjoern A. Zeeb if (unlikely(bssid_cam->valid)) { 6008e93258fSBjoern A. Zeeb rtw89_debug(rtwdev, RTW89_DBG_FW, 6018e93258fSBjoern A. Zeeb "bssid cam is already valid; skip init\n"); 6028e93258fSBjoern A. Zeeb return 0; 6038e93258fSBjoern A. Zeeb } 6048e93258fSBjoern A. Zeeb 6058e93258fSBjoern A. Zeeb ret = rtw89_cam_get_avail_bssid_cam(rtwdev, &bssid_cam_idx); 6068e93258fSBjoern A. Zeeb if (ret) { 6078e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to get available bssid cam\n"); 6088e93258fSBjoern A. Zeeb return ret; 6098e93258fSBjoern A. Zeeb } 6108e93258fSBjoern A. Zeeb 6118e93258fSBjoern A. Zeeb bssid_cam->bssid_cam_idx = bssid_cam_idx; 6128e93258fSBjoern A. Zeeb bssid_cam->phy_idx = rtwvif->phy_idx; 6138e93258fSBjoern A. Zeeb bssid_cam->len = BSSID_CAM_ENT_SIZE; 6148e93258fSBjoern A. Zeeb bssid_cam->offset = 0; 6158e93258fSBjoern A. Zeeb bssid_cam->valid = true; 6168e93258fSBjoern A. Zeeb ether_addr_copy(bssid_cam->bssid, bssid); 6178e93258fSBjoern A. Zeeb 6188e93258fSBjoern A. Zeeb return 0; 6198e93258fSBjoern A. Zeeb } 6208e93258fSBjoern A. Zeeb 6218e93258fSBjoern A. Zeeb void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) 6228e93258fSBjoern A. Zeeb { 6238e93258fSBjoern A. Zeeb struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; 6248e93258fSBjoern A. Zeeb 6258e93258fSBjoern A. Zeeb ether_addr_copy(bssid_cam->bssid, rtwvif->bssid); 6268e93258fSBjoern A. Zeeb } 6278e93258fSBjoern A. Zeeb 6288e93258fSBjoern A. Zeeb int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) 6298e93258fSBjoern A. Zeeb { 6308e93258fSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam; 6318e93258fSBjoern A. Zeeb struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; 6328e93258fSBjoern A. Zeeb int ret; 6338e93258fSBjoern A. Zeeb 6348e93258fSBjoern A. Zeeb ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, rtwvif->bssid); 6358e93258fSBjoern A. Zeeb if (ret) { 6368e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to init bssid cam\n"); 6378e93258fSBjoern A. Zeeb return ret; 6388e93258fSBjoern A. Zeeb } 6398e93258fSBjoern A. Zeeb 6408e93258fSBjoern A. Zeeb ret = rtw89_cam_init_addr_cam(rtwdev, addr_cam, bssid_cam); 6418e93258fSBjoern A. Zeeb if (ret) { 6428e93258fSBjoern A. Zeeb rtw89_err(rtwdev, "failed to init addr cam\n"); 6438e93258fSBjoern A. Zeeb return ret; 6448e93258fSBjoern A. Zeeb } 6458e93258fSBjoern A. Zeeb 6468e93258fSBjoern A. Zeeb return 0; 6478e93258fSBjoern A. Zeeb } 6488e93258fSBjoern A. Zeeb 6498e93258fSBjoern A. Zeeb int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, 6508e93258fSBjoern A. Zeeb struct rtw89_vif *rtwvif, 6518e93258fSBjoern A. Zeeb struct rtw89_sta *rtwsta, u8 *cmd) 6528e93258fSBjoern A. Zeeb { 6538e93258fSBjoern A. Zeeb struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 6548e93258fSBjoern A. Zeeb struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); 6558e93258fSBjoern A. Zeeb u8 bss_color = vif->bss_conf.he_bss_color.color; 6568e93258fSBjoern A. Zeeb u8 bss_mask; 6578e93258fSBjoern A. Zeeb 6588e93258fSBjoern A. Zeeb if (vif->bss_conf.nontransmitted) 6598e93258fSBjoern A. Zeeb bss_mask = RTW89_BSSID_MATCH_5_BYTES; 6608e93258fSBjoern A. Zeeb else 6618e93258fSBjoern A. Zeeb bss_mask = RTW89_BSSID_MATCH_ALL; 6628e93258fSBjoern A. Zeeb 6638e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx); 6648e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset); 6658e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len); 6668e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_VALID(cmd, bssid_cam->valid); 6678e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_MASK(cmd, bss_mask); 6688e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_BB_SEL(cmd, bssid_cam->phy_idx); 6698e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_BSS_COLOR(cmd, bss_color); 6708e93258fSBjoern A. Zeeb 6718e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_BSSID0(cmd, bssid_cam->bssid[0]); 6728e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_BSSID1(cmd, bssid_cam->bssid[1]); 6738e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_BSSID2(cmd, bssid_cam->bssid[2]); 6748e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_BSSID3(cmd, bssid_cam->bssid[3]); 6758e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_BSSID4(cmd, bssid_cam->bssid[4]); 6768e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_BSSID5(cmd, bssid_cam->bssid[5]); 6778e93258fSBjoern A. Zeeb 6788e93258fSBjoern A. Zeeb return 0; 6798e93258fSBjoern A. Zeeb } 6808e93258fSBjoern A. Zeeb 6818e93258fSBjoern A. Zeeb static u8 rtw89_cam_addr_hash(u8 start, const u8 *addr) 6828e93258fSBjoern A. Zeeb { 6838e93258fSBjoern A. Zeeb u8 hash = 0; 6848e93258fSBjoern A. Zeeb u8 i; 6858e93258fSBjoern A. Zeeb 6868e93258fSBjoern A. Zeeb for (i = start; i < ETH_ALEN; i++) 6878e93258fSBjoern A. Zeeb hash ^= addr[i]; 6888e93258fSBjoern A. Zeeb 6898e93258fSBjoern A. Zeeb return hash; 6908e93258fSBjoern A. Zeeb } 6918e93258fSBjoern A. Zeeb 6928e93258fSBjoern A. Zeeb void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, 6938e93258fSBjoern A. Zeeb struct rtw89_vif *rtwvif, 6948e93258fSBjoern A. Zeeb struct rtw89_sta *rtwsta, 6958e93258fSBjoern A. Zeeb const u8 *scan_mac_addr, 6968e93258fSBjoern A. Zeeb u8 *cmd) 6978e93258fSBjoern A. Zeeb { 6988e93258fSBjoern A. Zeeb struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 6998e93258fSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); 7008e93258fSBjoern A. Zeeb struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); 7018e93258fSBjoern A. Zeeb const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif->mac_addr; 7028e93258fSBjoern A. Zeeb u8 sma_hash, tma_hash, addr_msk_start; 7038e93258fSBjoern A. Zeeb u8 sma_start = 0; 7048e93258fSBjoern A. Zeeb u8 tma_start = 0; 7058e93258fSBjoern A. Zeeb u8 *tma = sta ? sta->addr : rtwvif->bssid; 7068e93258fSBjoern A. Zeeb 7078e93258fSBjoern A. Zeeb if (addr_cam->addr_mask != 0) { 7088e93258fSBjoern A. Zeeb addr_msk_start = __ffs(addr_cam->addr_mask); 7098e93258fSBjoern A. Zeeb if (addr_cam->mask_sel == RTW89_SMA) 7108e93258fSBjoern A. Zeeb sma_start = addr_msk_start; 7118e93258fSBjoern A. Zeeb else if (addr_cam->mask_sel == RTW89_TMA) 7128e93258fSBjoern A. Zeeb tma_start = addr_msk_start; 7138e93258fSBjoern A. Zeeb } 7148e93258fSBjoern A. Zeeb sma_hash = rtw89_cam_addr_hash(sma_start, sma); 7158e93258fSBjoern A. Zeeb tma_hash = rtw89_cam_addr_hash(tma_start, tma); 7168e93258fSBjoern A. Zeeb 7178e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_IDX(cmd, addr_cam->addr_cam_idx); 7188e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_OFFSET(cmd, addr_cam->offset); 7198e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_LEN(cmd, addr_cam->len); 7208e93258fSBjoern A. Zeeb 7218e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid); 7228e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif->net_type); 7238e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif->bcn_hit_cond); 7248e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif->hit_rule); 7258e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif->phy_idx); 7268e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask); 7278e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel); 7288e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash); 7298e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TMA_HASH(cmd, tma_hash); 7308e93258fSBjoern A. Zeeb 7318e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_BSSID_CAM_IDX(cmd, addr_cam->bssid_cam_idx); 7328e93258fSBjoern A. Zeeb 7338e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SMA0(cmd, sma[0]); 7348e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SMA1(cmd, sma[1]); 7358e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SMA2(cmd, sma[2]); 7368e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SMA3(cmd, sma[3]); 7378e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SMA4(cmd, sma[4]); 7388e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SMA5(cmd, sma[5]); 7398e93258fSBjoern A. Zeeb 7408e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TMA0(cmd, tma[0]); 7418e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TMA1(cmd, tma[1]); 7428e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TMA2(cmd, tma[2]); 7438e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TMA3(cmd, tma[3]); 7448e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TMA4(cmd, tma[4]); 7458e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TMA5(cmd, tma[5]); 7468e93258fSBjoern A. Zeeb 7478e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif->port); 7488e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif->port); 7498e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif->trigger); 7508e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif->lsig_txop); 7518e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif->tgt_ind); 7528e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif->frm_tgt_ind); 7538e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id); 7548e93258fSBjoern A. Zeeb if (rtwvif->net_type == RTW89_NET_TYPE_INFRA) 7558e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff); 7568e93258fSBjoern A. Zeeb else if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) 7578e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0); 7588e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif->wowlan_pattern); 7598e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif->wowlan_uc); 7608e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif->wowlan_magic); 7618e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi); 7628e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode); 7638e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]); 7648e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT1_KEYID(cmd, addr_cam->sec_ent_keyid[1]); 7658e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT2_KEYID(cmd, addr_cam->sec_ent_keyid[2]); 7668e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT3_KEYID(cmd, addr_cam->sec_ent_keyid[3]); 7678e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT4_KEYID(cmd, addr_cam->sec_ent_keyid[4]); 7688e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT5_KEYID(cmd, addr_cam->sec_ent_keyid[5]); 7698e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT6_KEYID(cmd, addr_cam->sec_ent_keyid[6]); 7708e93258fSBjoern A. Zeeb 7718e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT_VALID(cmd, addr_cam->sec_cam_map[0] & 0xff); 7728e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT0(cmd, addr_cam->sec_ent[0]); 7738e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT1(cmd, addr_cam->sec_ent[1]); 7748e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT2(cmd, addr_cam->sec_ent[2]); 7758e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT3(cmd, addr_cam->sec_ent[3]); 7768e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]); 7778e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]); 7788e93258fSBjoern A. Zeeb FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]); 7798e93258fSBjoern A. Zeeb } 7808e93258fSBjoern A. Zeeb 7818e93258fSBjoern A. Zeeb void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, 7828e93258fSBjoern A. Zeeb struct rtw89_vif *rtwvif, 7838e93258fSBjoern A. Zeeb struct rtw89_sta *rtwsta, 784*6d67aabdSBjoern A. Zeeb struct rtw89_h2c_dctlinfo_ud_v1 *h2c) 7858e93258fSBjoern A. Zeeb { 7868e93258fSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); 787*6d67aabdSBjoern A. Zeeb struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 788*6d67aabdSBjoern A. Zeeb u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; 7898e93258fSBjoern A. Zeeb 790*6d67aabdSBjoern A. Zeeb h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id, 791*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_C0_MACID) | 792*6d67aabdSBjoern A. Zeeb le32_encode_bits(1, DCTLINFO_V1_C0_OP); 7938e93258fSBjoern A. Zeeb 794*6d67aabdSBjoern A. Zeeb h2c->w4 = le32_encode_bits(addr_cam->sec_ent_keyid[0], 795*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT0_KEYID) | 796*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[1], 797*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT1_KEYID) | 798*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[2], 799*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT2_KEYID) | 800*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[3], 801*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT3_KEYID) | 802*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[4], 803*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT4_KEYID) | 804*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[5], 805*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT5_KEYID) | 806*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[6], 807*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT6_KEYID); 808*6d67aabdSBjoern A. Zeeb h2c->m4 = cpu_to_le32(DCTLINFO_V1_W4_SEC_ENT0_KEYID | 809*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT1_KEYID | 810*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT2_KEYID | 811*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT3_KEYID | 812*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT4_KEYID | 813*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT5_KEYID | 814*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_ENT6_KEYID); 8158e93258fSBjoern A. Zeeb 816*6d67aabdSBjoern A. Zeeb h2c->w5 = le32_encode_bits(addr_cam->sec_cam_map[0] & 0xff, 817*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W5_SEC_ENT_VALID) | 818*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[0], 819*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W5_SEC_ENT0) | 820*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[1], 821*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W5_SEC_ENT1) | 822*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[2], 823*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W5_SEC_ENT2); 824*6d67aabdSBjoern A. Zeeb h2c->m5 = cpu_to_le32(DCTLINFO_V1_W5_SEC_ENT_VALID | 825*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W5_SEC_ENT0 | 826*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W5_SEC_ENT1 | 827*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W5_SEC_ENT2); 828*6d67aabdSBjoern A. Zeeb 829*6d67aabdSBjoern A. Zeeb h2c->w6 = le32_encode_bits(addr_cam->sec_ent[3], 830*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W6_SEC_ENT3) | 831*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[4], 832*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W6_SEC_ENT4) | 833*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[5], 834*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W6_SEC_ENT5) | 835*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[6], 836*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W6_SEC_ENT6); 837*6d67aabdSBjoern A. Zeeb h2c->m6 = cpu_to_le32(DCTLINFO_V1_W6_SEC_ENT3 | 838*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W6_SEC_ENT4 | 839*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W6_SEC_ENT5 | 840*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W6_SEC_ENT6); 841*6d67aabdSBjoern A. Zeeb 842*6d67aabdSBjoern A. Zeeb if (rtw_wow->ptk_alg) { 843*6d67aabdSBjoern A. Zeeb h2c->w0 = le32_encode_bits(ptk_tx_iv[0] | ptk_tx_iv[1] << 8, 844*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W0_AES_IV_L); 845*6d67aabdSBjoern A. Zeeb h2c->m0 = cpu_to_le32(DCTLINFO_V1_W0_AES_IV_L); 846*6d67aabdSBjoern A. Zeeb 847*6d67aabdSBjoern A. Zeeb h2c->w1 = le32_encode_bits(ptk_tx_iv[4] | 848*6d67aabdSBjoern A. Zeeb ptk_tx_iv[5] << 8 | 849*6d67aabdSBjoern A. Zeeb ptk_tx_iv[6] << 16 | 850*6d67aabdSBjoern A. Zeeb ptk_tx_iv[7] << 24, 851*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W1_AES_IV_H); 852*6d67aabdSBjoern A. Zeeb h2c->m1 = cpu_to_le32(DCTLINFO_V1_W1_AES_IV_H); 853*6d67aabdSBjoern A. Zeeb 854*6d67aabdSBjoern A. Zeeb h2c->w4 |= le32_encode_bits(rtw_wow->ptk_keyidx, 855*6d67aabdSBjoern A. Zeeb DCTLINFO_V1_W4_SEC_KEY_ID); 856*6d67aabdSBjoern A. Zeeb h2c->m4 |= cpu_to_le32(DCTLINFO_V1_W4_SEC_KEY_ID); 857*6d67aabdSBjoern A. Zeeb } 858*6d67aabdSBjoern A. Zeeb } 859*6d67aabdSBjoern A. Zeeb 860*6d67aabdSBjoern A. Zeeb void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, 861*6d67aabdSBjoern A. Zeeb struct rtw89_vif *rtwvif, 862*6d67aabdSBjoern A. Zeeb struct rtw89_sta *rtwsta, 863*6d67aabdSBjoern A. Zeeb struct rtw89_h2c_dctlinfo_ud_v2 *h2c) 864*6d67aabdSBjoern A. Zeeb { 865*6d67aabdSBjoern A. Zeeb struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); 866*6d67aabdSBjoern A. Zeeb struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 867*6d67aabdSBjoern A. Zeeb u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; 868*6d67aabdSBjoern A. Zeeb 869*6d67aabdSBjoern A. Zeeb h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id, 870*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_C0_MACID) | 871*6d67aabdSBjoern A. Zeeb le32_encode_bits(1, DCTLINFO_V2_C0_OP); 872*6d67aabdSBjoern A. Zeeb 873*6d67aabdSBjoern A. Zeeb h2c->w4 = le32_encode_bits(addr_cam->sec_ent_keyid[0], 874*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT0_KEYID) | 875*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[1], 876*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT1_KEYID) | 877*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[2], 878*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT2_KEYID) | 879*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[3], 880*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT3_KEYID) | 881*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[4], 882*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT4_KEYID) | 883*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[5], 884*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT5_KEYID) | 885*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent_keyid[6], 886*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT6_KEYID); 887*6d67aabdSBjoern A. Zeeb h2c->m4 = cpu_to_le32(DCTLINFO_V2_W4_SEC_ENT0_KEYID | 888*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT1_KEYID | 889*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT2_KEYID | 890*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT3_KEYID | 891*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT4_KEYID | 892*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT5_KEYID | 893*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_ENT6_KEYID); 894*6d67aabdSBjoern A. Zeeb 895*6d67aabdSBjoern A. Zeeb h2c->w5 = le32_encode_bits(addr_cam->sec_cam_map[0], 896*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W5_SEC_ENT_VALID_V1) | 897*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[0], 898*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W5_SEC_ENT0_V1); 899*6d67aabdSBjoern A. Zeeb h2c->m5 = cpu_to_le32(DCTLINFO_V2_W5_SEC_ENT_VALID_V1 | 900*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W5_SEC_ENT0_V1); 901*6d67aabdSBjoern A. Zeeb 902*6d67aabdSBjoern A. Zeeb h2c->w6 = le32_encode_bits(addr_cam->sec_ent[1], 903*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W6_SEC_ENT1_V1) | 904*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[2], 905*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W6_SEC_ENT2_V1) | 906*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[3], 907*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W6_SEC_ENT3_V1) | 908*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[4], 909*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W6_SEC_ENT4_V1); 910*6d67aabdSBjoern A. Zeeb h2c->m6 = cpu_to_le32(DCTLINFO_V2_W6_SEC_ENT1_V1 | 911*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W6_SEC_ENT2_V1 | 912*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W6_SEC_ENT3_V1 | 913*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W6_SEC_ENT4_V1); 914*6d67aabdSBjoern A. Zeeb 915*6d67aabdSBjoern A. Zeeb h2c->w7 = le32_encode_bits(addr_cam->sec_ent[5], 916*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W7_SEC_ENT5_V1) | 917*6d67aabdSBjoern A. Zeeb le32_encode_bits(addr_cam->sec_ent[6], 918*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W7_SEC_ENT6_V1); 919*6d67aabdSBjoern A. Zeeb h2c->m7 = cpu_to_le32(DCTLINFO_V2_W7_SEC_ENT5_V1 | 920*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W7_SEC_ENT6_V1); 921*6d67aabdSBjoern A. Zeeb 922*6d67aabdSBjoern A. Zeeb if (rtw_wow->ptk_alg) { 923*6d67aabdSBjoern A. Zeeb h2c->w0 = le32_encode_bits(ptk_tx_iv[0] | ptk_tx_iv[1] << 8, 924*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W0_AES_IV_L); 925*6d67aabdSBjoern A. Zeeb h2c->m0 = cpu_to_le32(DCTLINFO_V2_W0_AES_IV_L); 926*6d67aabdSBjoern A. Zeeb 927*6d67aabdSBjoern A. Zeeb h2c->w1 = le32_encode_bits(ptk_tx_iv[4] | 928*6d67aabdSBjoern A. Zeeb ptk_tx_iv[5] << 8 | 929*6d67aabdSBjoern A. Zeeb ptk_tx_iv[6] << 16 | 930*6d67aabdSBjoern A. Zeeb ptk_tx_iv[7] << 24, 931*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W1_AES_IV_H); 932*6d67aabdSBjoern A. Zeeb h2c->m1 = cpu_to_le32(DCTLINFO_V2_W1_AES_IV_H); 933*6d67aabdSBjoern A. Zeeb 934*6d67aabdSBjoern A. Zeeb h2c->w4 |= le32_encode_bits(rtw_wow->ptk_keyidx, 935*6d67aabdSBjoern A. Zeeb DCTLINFO_V2_W4_SEC_KEY_ID); 936*6d67aabdSBjoern A. Zeeb h2c->m4 |= cpu_to_le32(DCTLINFO_V2_W4_SEC_KEY_ID); 937*6d67aabdSBjoern A. Zeeb } 9388e93258fSBjoern A. Zeeb } 939