1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2009-2012 Realtek Corporation.*/ 3 4 #include "wifi.h" 5 #include "cam.h" 6 #include <linux/export.h> 7 8 void rtl_cam_reset_sec_info(struct ieee80211_hw *hw) 9 { 10 struct rtl_priv *rtlpriv = rtl_priv(hw); 11 12 rtlpriv->sec.use_defaultkey = false; 13 rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION; 14 rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION; 15 memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN); 16 memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE); 17 rtlpriv->sec.pairwise_key = NULL; 18 } 19 20 static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, 21 const u8 *mac_addr, u8 *key_cont_128, 22 u16 us_config) 23 { 24 struct rtl_priv *rtlpriv = rtl_priv(hw); 25 26 u32 target_command; 27 u32 target_content = 0; 28 int entry_i; 29 30 RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_DMESG, "Key content :", 31 key_cont_128, 16); 32 33 /* 0-1 config + mac, 2-5 fill 128key,6-7 are reserved */ 34 for (entry_i = CAM_CONTENT_COUNT - 1; entry_i >= 0; entry_i--) { 35 target_command = entry_i + CAM_CONTENT_COUNT * entry_no; 36 target_command = target_command | BIT(31) | BIT(16); 37 38 if (entry_i == 0) { 39 target_content = (u32) (*(mac_addr + 0)) << 16 | 40 (u32) (*(mac_addr + 1)) << 24 | (u32) us_config; 41 42 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 43 target_content); 44 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], 45 target_command); 46 47 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 48 "WRITE %x: %x\n", 49 rtlpriv->cfg->maps[WCAMI], target_content); 50 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 51 "The Key ID is %d\n", entry_no); 52 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 53 "WRITE %x: %x\n", 54 rtlpriv->cfg->maps[RWCAM], target_command); 55 56 } else if (entry_i == 1) { 57 58 target_content = (u32) (*(mac_addr + 5)) << 24 | 59 (u32) (*(mac_addr + 4)) << 16 | 60 (u32) (*(mac_addr + 3)) << 8 | 61 (u32) (*(mac_addr + 2)); 62 63 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 64 target_content); 65 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], 66 target_command); 67 68 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 69 "WRITE A4: %x\n", target_content); 70 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 71 "WRITE A0: %x\n", target_command); 72 73 } else { 74 75 target_content = 76 (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 3)) << 77 24 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 2)) 78 << 16 | 79 (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8 80 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 0)); 81 82 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 83 target_content); 84 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], 85 target_command); 86 87 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 88 "WRITE A4: %x\n", target_content); 89 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 90 "WRITE A0: %x\n", target_command); 91 } 92 } 93 94 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 95 "after set key, usconfig:%x\n", us_config); 96 } 97 98 u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, const u8 *mac_addr, 99 u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, 100 u32 ul_default_key, u8 *key_content) 101 { 102 u32 us_config; 103 struct rtl_priv *rtlpriv = rtl_priv(hw); 104 105 rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 106 "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n", 107 ul_entry_idx, ul_key_id, ul_enc_alg, 108 ul_default_key, mac_addr); 109 110 if (ul_key_id == TOTAL_CAM_ENTRY) { 111 rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, 112 "ulKeyId exceed!\n"); 113 return 0; 114 } 115 116 if (ul_default_key == 1) 117 us_config = CFG_VALID | ((u16) (ul_enc_alg) << 2); 118 else 119 us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id; 120 121 rtl_cam_program_entry(hw, ul_entry_idx, mac_addr, 122 (u8 *)key_content, us_config); 123 124 rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "end\n"); 125 126 return 1; 127 128 } 129 EXPORT_SYMBOL(rtl_cam_add_one_entry); 130 131 int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, 132 u8 *mac_addr, u32 ul_key_id) 133 { 134 u32 ul_command; 135 struct rtl_priv *rtlpriv = rtl_priv(hw); 136 137 rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id); 138 139 ul_command = ul_key_id * CAM_CONTENT_COUNT; 140 ul_command = ul_command | BIT(31) | BIT(16); 141 142 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0); 143 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); 144 145 rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 146 "%s: WRITE A4: %x\n", __func__, 0); 147 rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 148 "%s: WRITE A0: %x\n", __func__, ul_command); 149 150 return 0; 151 152 } 153 EXPORT_SYMBOL(rtl_cam_delete_one_entry); 154 155 void rtl_cam_reset_all_entry(struct ieee80211_hw *hw) 156 { 157 u32 ul_command; 158 struct rtl_priv *rtlpriv = rtl_priv(hw); 159 160 ul_command = BIT(31) | BIT(30); 161 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); 162 } 163 EXPORT_SYMBOL(rtl_cam_reset_all_entry); 164 165 void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index) 166 { 167 struct rtl_priv *rtlpriv = rtl_priv(hw); 168 169 u32 ul_command; 170 u32 ul_content; 171 u32 ul_enc_algo; 172 173 switch (rtlpriv->sec.pairwise_enc_algorithm) { 174 case WEP40_ENCRYPTION: 175 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; 176 break; 177 case WEP104_ENCRYPTION: 178 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; 179 break; 180 case TKIP_ENCRYPTION: 181 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; 182 break; 183 case AESCCMP_ENCRYPTION: 184 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; 185 break; 186 default: 187 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; 188 } 189 190 ul_content = (uc_index & 3) | ((u16) (ul_enc_algo) << 2); 191 192 ul_content |= BIT(15); 193 ul_command = CAM_CONTENT_COUNT * uc_index; 194 ul_command = ul_command | BIT(31) | BIT(16); 195 196 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); 197 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); 198 199 rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 200 "%s: WRITE A4: %x\n", __func__, ul_content); 201 rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 202 "%s: WRITE A0: %x\n", __func__, ul_command); 203 } 204 EXPORT_SYMBOL(rtl_cam_mark_invalid); 205 206 void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) 207 { 208 struct rtl_priv *rtlpriv = rtl_priv(hw); 209 210 u32 ul_command; 211 u32 ul_content; 212 u32 ul_encalgo; 213 u8 entry_i; 214 215 switch (rtlpriv->sec.pairwise_enc_algorithm) { 216 case WEP40_ENCRYPTION: 217 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; 218 break; 219 case WEP104_ENCRYPTION: 220 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; 221 break; 222 case TKIP_ENCRYPTION: 223 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; 224 break; 225 case AESCCMP_ENCRYPTION: 226 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; 227 break; 228 default: 229 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; 230 } 231 232 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { 233 234 if (entry_i == 0) { 235 ul_content = 236 (uc_index & 0x03) | ((u16) (ul_encalgo) << 2); 237 ul_content |= BIT(15); 238 239 } else { 240 ul_content = 0; 241 } 242 243 ul_command = CAM_CONTENT_COUNT * uc_index + entry_i; 244 ul_command = ul_command | BIT(31) | BIT(16); 245 246 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); 247 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); 248 249 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 250 "%s: WRITE A4: %x\n", __func__, ul_content); 251 rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, 252 "%s: WRITE A0: %x\n", __func__, ul_command); 253 } 254 255 } 256 EXPORT_SYMBOL(rtl_cam_empty_entry); 257 258 u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr) 259 { 260 struct rtl_priv *rtlpriv = rtl_priv(hw); 261 u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4; 262 u8 entry_idx = 0; 263 u8 i, *addr; 264 265 if (NULL == sta_addr) { 266 pr_err("sta_addr is NULL.\n"); 267 return TOTAL_CAM_ENTRY; 268 } 269 /* Does STA already exist? */ 270 for (i = 4; i < TOTAL_CAM_ENTRY; i++) { 271 addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; 272 if (ether_addr_equal_unaligned(addr, sta_addr)) 273 return i; 274 } 275 /* Get a free CAM entry. */ 276 for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) { 277 if ((bitmap & BIT(0)) == 0) { 278 pr_err("-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", 279 rtlpriv->sec.hwsec_cam_bitmap, entry_idx); 280 rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx; 281 memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], 282 sta_addr, ETH_ALEN); 283 return entry_idx; 284 } 285 bitmap = bitmap >> 1; 286 } 287 return TOTAL_CAM_ENTRY; 288 } 289 EXPORT_SYMBOL(rtl_cam_get_free_entry); 290 291 void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) 292 { 293 struct rtl_priv *rtlpriv = rtl_priv(hw); 294 u32 bitmap; 295 u8 i, *addr; 296 297 if (NULL == sta_addr) { 298 pr_err("sta_addr is NULL.\n"); 299 return; 300 } 301 302 if (is_zero_ether_addr(sta_addr)) { 303 pr_err("sta_addr is %pM\n", sta_addr); 304 return; 305 } 306 /* Does STA already exist? */ 307 for (i = 4; i < TOTAL_CAM_ENTRY; i++) { 308 addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; 309 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i; 310 if (((bitmap & BIT(0)) == BIT(0)) && 311 (ether_addr_equal_unaligned(addr, sta_addr))) { 312 /* Remove from HW Security CAM */ 313 eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]); 314 rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); 315 rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 316 "&&&&&&&&&del entry %d\n", i); 317 } 318 } 319 return; 320 } 321 EXPORT_SYMBOL(rtl_cam_del_entry); 322