18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 2009-2012 Realtek Corporation.*/ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "wifi.h" 58c2ecf20Sopenharmony_ci#include "cam.h" 68c2ecf20Sopenharmony_ci#include <linux/export.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_civoid rtl_cam_reset_sec_info(struct ieee80211_hw *hw) 98c2ecf20Sopenharmony_ci{ 108c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci rtlpriv->sec.use_defaultkey = false; 138c2ecf20Sopenharmony_ci rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION; 148c2ecf20Sopenharmony_ci rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION; 158c2ecf20Sopenharmony_ci memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN); 168c2ecf20Sopenharmony_ci memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE); 178c2ecf20Sopenharmony_ci rtlpriv->sec.pairwise_key = NULL; 188c2ecf20Sopenharmony_ci} 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, 218c2ecf20Sopenharmony_ci u8 *mac_addr, u8 *key_cont_128, u16 us_config) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci u32 target_command; 268c2ecf20Sopenharmony_ci u32 target_content = 0; 278c2ecf20Sopenharmony_ci int entry_i; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_DMESG, "Key content :", 308c2ecf20Sopenharmony_ci key_cont_128, 16); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci /* 0-1 config + mac, 2-5 fill 128key,6-7 are reserved */ 338c2ecf20Sopenharmony_ci for (entry_i = CAM_CONTENT_COUNT - 1; entry_i >= 0; entry_i--) { 348c2ecf20Sopenharmony_ci target_command = entry_i + CAM_CONTENT_COUNT * entry_no; 358c2ecf20Sopenharmony_ci target_command = target_command | BIT(31) | BIT(16); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci if (entry_i == 0) { 388c2ecf20Sopenharmony_ci target_content = (u32) (*(mac_addr + 0)) << 16 | 398c2ecf20Sopenharmony_ci (u32) (*(mac_addr + 1)) << 24 | (u32) us_config; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 428c2ecf20Sopenharmony_ci target_content); 438c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], 448c2ecf20Sopenharmony_ci target_command); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 478c2ecf20Sopenharmony_ci "WRITE %x: %x\n", 488c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[WCAMI], target_content); 498c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 508c2ecf20Sopenharmony_ci "The Key ID is %d\n", entry_no); 518c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 528c2ecf20Sopenharmony_ci "WRITE %x: %x\n", 538c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RWCAM], target_command); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci } else if (entry_i == 1) { 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci target_content = (u32) (*(mac_addr + 5)) << 24 | 588c2ecf20Sopenharmony_ci (u32) (*(mac_addr + 4)) << 16 | 598c2ecf20Sopenharmony_ci (u32) (*(mac_addr + 3)) << 8 | 608c2ecf20Sopenharmony_ci (u32) (*(mac_addr + 2)); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 638c2ecf20Sopenharmony_ci target_content); 648c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], 658c2ecf20Sopenharmony_ci target_command); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 688c2ecf20Sopenharmony_ci "WRITE A4: %x\n", target_content); 698c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 708c2ecf20Sopenharmony_ci "WRITE A0: %x\n", target_command); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci } else { 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci target_content = 758c2ecf20Sopenharmony_ci (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 3)) << 768c2ecf20Sopenharmony_ci 24 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 2)) 778c2ecf20Sopenharmony_ci << 16 | 788c2ecf20Sopenharmony_ci (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8 798c2ecf20Sopenharmony_ci | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 0)); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 828c2ecf20Sopenharmony_ci target_content); 838c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], 848c2ecf20Sopenharmony_ci target_command); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 878c2ecf20Sopenharmony_ci "WRITE A4: %x\n", target_content); 888c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 898c2ecf20Sopenharmony_ci "WRITE A0: %x\n", target_command); 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 948c2ecf20Sopenharmony_ci "after set key, usconfig:%x\n", us_config); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciu8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, 988c2ecf20Sopenharmony_ci u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, 998c2ecf20Sopenharmony_ci u32 ul_default_key, u8 *key_content) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci u32 us_config; 1028c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 1058c2ecf20Sopenharmony_ci "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n", 1068c2ecf20Sopenharmony_ci ul_entry_idx, ul_key_id, ul_enc_alg, 1078c2ecf20Sopenharmony_ci ul_default_key, mac_addr); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (ul_key_id == TOTAL_CAM_ENTRY) { 1108c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, 1118c2ecf20Sopenharmony_ci "ulKeyId exceed!\n"); 1128c2ecf20Sopenharmony_ci return 0; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (ul_default_key == 1) 1168c2ecf20Sopenharmony_ci us_config = CFG_VALID | ((u16) (ul_enc_alg) << 2); 1178c2ecf20Sopenharmony_ci else 1188c2ecf20Sopenharmony_ci us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci rtl_cam_program_entry(hw, ul_entry_idx, mac_addr, 1218c2ecf20Sopenharmony_ci (u8 *)key_content, us_config); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "end\n"); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci return 1; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_cam_add_one_entry); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ciint rtl_cam_delete_one_entry(struct ieee80211_hw *hw, 1318c2ecf20Sopenharmony_ci u8 *mac_addr, u32 ul_key_id) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci u32 ul_command; 1348c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci ul_command = ul_key_id * CAM_CONTENT_COUNT; 1398c2ecf20Sopenharmony_ci ul_command = ul_command | BIT(31) | BIT(16); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0); 1428c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 1458c2ecf20Sopenharmony_ci "%s: WRITE A4: %x\n", __func__, 0); 1468c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 1478c2ecf20Sopenharmony_ci "%s: WRITE A0: %x\n", __func__, ul_command); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci return 0; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_cam_delete_one_entry); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_civoid rtl_cam_reset_all_entry(struct ieee80211_hw *hw) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci u32 ul_command; 1578c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci ul_command = BIT(31) | BIT(30); 1608c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_cam_reset_all_entry); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_civoid rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci u32 ul_command; 1698c2ecf20Sopenharmony_ci u32 ul_content; 1708c2ecf20Sopenharmony_ci u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci switch (rtlpriv->sec.pairwise_enc_algorithm) { 1738c2ecf20Sopenharmony_ci case WEP40_ENCRYPTION: 1748c2ecf20Sopenharmony_ci ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; 1758c2ecf20Sopenharmony_ci break; 1768c2ecf20Sopenharmony_ci case WEP104_ENCRYPTION: 1778c2ecf20Sopenharmony_ci ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; 1788c2ecf20Sopenharmony_ci break; 1798c2ecf20Sopenharmony_ci case TKIP_ENCRYPTION: 1808c2ecf20Sopenharmony_ci ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; 1818c2ecf20Sopenharmony_ci break; 1828c2ecf20Sopenharmony_ci case AESCCMP_ENCRYPTION: 1838c2ecf20Sopenharmony_ci ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; 1848c2ecf20Sopenharmony_ci break; 1858c2ecf20Sopenharmony_ci default: 1868c2ecf20Sopenharmony_ci ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci ul_content = (uc_index & 3) | ((u16) (ul_enc_algo) << 2); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci ul_content |= BIT(15); 1928c2ecf20Sopenharmony_ci ul_command = CAM_CONTENT_COUNT * uc_index; 1938c2ecf20Sopenharmony_ci ul_command = ul_command | BIT(31) | BIT(16); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); 1968c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 1998c2ecf20Sopenharmony_ci "%s: WRITE A4: %x\n", __func__, ul_content); 2008c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 2018c2ecf20Sopenharmony_ci "%s: WRITE A0: %x\n", __func__, ul_command); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_cam_mark_invalid); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_civoid rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci u32 ul_command; 2108c2ecf20Sopenharmony_ci u32 ul_content; 2118c2ecf20Sopenharmony_ci u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; 2128c2ecf20Sopenharmony_ci u8 entry_i; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci switch (rtlpriv->sec.pairwise_enc_algorithm) { 2158c2ecf20Sopenharmony_ci case WEP40_ENCRYPTION: 2168c2ecf20Sopenharmony_ci ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; 2178c2ecf20Sopenharmony_ci break; 2188c2ecf20Sopenharmony_ci case WEP104_ENCRYPTION: 2198c2ecf20Sopenharmony_ci ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; 2208c2ecf20Sopenharmony_ci break; 2218c2ecf20Sopenharmony_ci case TKIP_ENCRYPTION: 2228c2ecf20Sopenharmony_ci ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; 2238c2ecf20Sopenharmony_ci break; 2248c2ecf20Sopenharmony_ci case AESCCMP_ENCRYPTION: 2258c2ecf20Sopenharmony_ci ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; 2268c2ecf20Sopenharmony_ci break; 2278c2ecf20Sopenharmony_ci default: 2288c2ecf20Sopenharmony_ci ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (entry_i == 0) { 2348c2ecf20Sopenharmony_ci ul_content = 2358c2ecf20Sopenharmony_ci (uc_index & 0x03) | ((u16) (ul_encalgo) << 2); 2368c2ecf20Sopenharmony_ci ul_content |= BIT(15); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci } else { 2398c2ecf20Sopenharmony_ci ul_content = 0; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci ul_command = CAM_CONTENT_COUNT * uc_index + entry_i; 2438c2ecf20Sopenharmony_ci ul_command = ul_command | BIT(31) | BIT(16); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); 2468c2ecf20Sopenharmony_ci rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 2498c2ecf20Sopenharmony_ci "%s: WRITE A4: %x\n", __func__, ul_content); 2508c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 2518c2ecf20Sopenharmony_ci "%s: WRITE A0: %x\n", __func__, ul_command); 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_cam_empty_entry); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ciu8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2608c2ecf20Sopenharmony_ci u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4; 2618c2ecf20Sopenharmony_ci u8 entry_idx = 0; 2628c2ecf20Sopenharmony_ci u8 i, *addr; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (NULL == sta_addr) { 2658c2ecf20Sopenharmony_ci pr_err("sta_addr is NULL.\n"); 2668c2ecf20Sopenharmony_ci return TOTAL_CAM_ENTRY; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci /* Does STA already exist? */ 2698c2ecf20Sopenharmony_ci for (i = 4; i < TOTAL_CAM_ENTRY; i++) { 2708c2ecf20Sopenharmony_ci addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; 2718c2ecf20Sopenharmony_ci if (ether_addr_equal_unaligned(addr, sta_addr)) 2728c2ecf20Sopenharmony_ci return i; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci /* Get a free CAM entry. */ 2758c2ecf20Sopenharmony_ci for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) { 2768c2ecf20Sopenharmony_ci if ((bitmap & BIT(0)) == 0) { 2778c2ecf20Sopenharmony_ci pr_err("-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", 2788c2ecf20Sopenharmony_ci rtlpriv->sec.hwsec_cam_bitmap, entry_idx); 2798c2ecf20Sopenharmony_ci rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx; 2808c2ecf20Sopenharmony_ci memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], 2818c2ecf20Sopenharmony_ci sta_addr, ETH_ALEN); 2828c2ecf20Sopenharmony_ci return entry_idx; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci bitmap = bitmap >> 1; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci return TOTAL_CAM_ENTRY; 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_cam_get_free_entry); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_civoid rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2938c2ecf20Sopenharmony_ci u32 bitmap; 2948c2ecf20Sopenharmony_ci u8 i, *addr; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci if (NULL == sta_addr) { 2978c2ecf20Sopenharmony_ci pr_err("sta_addr is NULL.\n"); 2988c2ecf20Sopenharmony_ci return; 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (is_zero_ether_addr(sta_addr)) { 3028c2ecf20Sopenharmony_ci pr_err("sta_addr is %pM\n", sta_addr); 3038c2ecf20Sopenharmony_ci return; 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci /* Does STA already exist? */ 3068c2ecf20Sopenharmony_ci for (i = 4; i < TOTAL_CAM_ENTRY; i++) { 3078c2ecf20Sopenharmony_ci addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; 3088c2ecf20Sopenharmony_ci bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i; 3098c2ecf20Sopenharmony_ci if (((bitmap & BIT(0)) == BIT(0)) && 3108c2ecf20Sopenharmony_ci (ether_addr_equal_unaligned(addr, sta_addr))) { 3118c2ecf20Sopenharmony_ci /* Remove from HW Security CAM */ 3128c2ecf20Sopenharmony_ci eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]); 3138c2ecf20Sopenharmony_ci rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); 3148c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 3158c2ecf20Sopenharmony_ci "&&&&&&&&&del entry %d\n", i); 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci return; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_cam_del_entry); 321