Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2012  Realtek Corporation.*/
0003 
0004 #include "wifi.h"
0005 #include "cam.h"
0006 #include <linux/export.h>
0007 
0008 void rtl_cam_reset_sec_info(struct ieee80211_hw *hw)
0009 {
0010     struct rtl_priv *rtlpriv = rtl_priv(hw);
0011 
0012     rtlpriv->sec.use_defaultkey = false;
0013     rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION;
0014     rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION;
0015     memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN);
0016     memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE);
0017     rtlpriv->sec.pairwise_key = NULL;
0018 }
0019 
0020 static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
0021                u8 *mac_addr, u8 *key_cont_128, u16 us_config)
0022 {
0023     struct rtl_priv *rtlpriv = rtl_priv(hw);
0024 
0025     u32 target_command;
0026     u32 target_content = 0;
0027     int entry_i;
0028 
0029     RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_DMESG, "Key content :",
0030               key_cont_128, 16);
0031 
0032     /* 0-1 config + mac, 2-5 fill 128key,6-7 are reserved */
0033     for (entry_i = CAM_CONTENT_COUNT - 1; entry_i >= 0; entry_i--) {
0034         target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
0035         target_command = target_command | BIT(31) | BIT(16);
0036 
0037         if (entry_i == 0) {
0038             target_content = (u32) (*(mac_addr + 0)) << 16 |
0039                 (u32) (*(mac_addr + 1)) << 24 | (u32) us_config;
0040 
0041             rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
0042                     target_content);
0043             rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
0044                     target_command);
0045 
0046             rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0047                 "WRITE %x: %x\n",
0048                 rtlpriv->cfg->maps[WCAMI], target_content);
0049             rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0050                 "The Key ID is %d\n", entry_no);
0051             rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0052                 "WRITE %x: %x\n",
0053                 rtlpriv->cfg->maps[RWCAM], target_command);
0054 
0055         } else if (entry_i == 1) {
0056 
0057             target_content = (u32) (*(mac_addr + 5)) << 24 |
0058                 (u32) (*(mac_addr + 4)) << 16 |
0059                 (u32) (*(mac_addr + 3)) << 8 |
0060                 (u32) (*(mac_addr + 2));
0061 
0062             rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
0063                     target_content);
0064             rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
0065                     target_command);
0066 
0067             rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0068                 "WRITE A4: %x\n", target_content);
0069             rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0070                 "WRITE A0: %x\n", target_command);
0071 
0072         } else {
0073 
0074             target_content =
0075                 (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 3)) <<
0076                 24 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 2))
0077                 << 16 |
0078                 (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8
0079                 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 0));
0080 
0081             rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
0082                     target_content);
0083             rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
0084                     target_command);
0085 
0086             rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0087                 "WRITE A4: %x\n", target_content);
0088             rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0089                 "WRITE A0: %x\n", target_command);
0090         }
0091     }
0092 
0093     rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0094         "after set key, usconfig:%x\n", us_config);
0095 }
0096 
0097 u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
0098              u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg,
0099              u32 ul_default_key, u8 *key_content)
0100 {
0101     u32 us_config;
0102     struct rtl_priv *rtlpriv = rtl_priv(hw);
0103 
0104     rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
0105         "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n",
0106         ul_entry_idx, ul_key_id, ul_enc_alg,
0107         ul_default_key, mac_addr);
0108 
0109     if (ul_key_id == TOTAL_CAM_ENTRY) {
0110         rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
0111             "ulKeyId exceed!\n");
0112         return 0;
0113     }
0114 
0115     if (ul_default_key == 1)
0116         us_config = CFG_VALID | ((u16) (ul_enc_alg) << 2);
0117     else
0118         us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id;
0119 
0120     rtl_cam_program_entry(hw, ul_entry_idx, mac_addr,
0121                   (u8 *)key_content, us_config);
0122 
0123     rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "end\n");
0124 
0125     return 1;
0126 
0127 }
0128 EXPORT_SYMBOL(rtl_cam_add_one_entry);
0129 
0130 int rtl_cam_delete_one_entry(struct ieee80211_hw *hw,
0131                  u8 *mac_addr, u32 ul_key_id)
0132 {
0133     u32 ul_command;
0134     struct rtl_priv *rtlpriv = rtl_priv(hw);
0135 
0136     rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id);
0137 
0138     ul_command = ul_key_id * CAM_CONTENT_COUNT;
0139     ul_command = ul_command | BIT(31) | BIT(16);
0140 
0141     rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0);
0142     rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
0143 
0144     rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
0145         "%s: WRITE A4: %x\n", __func__, 0);
0146     rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
0147         "%s: WRITE A0: %x\n", __func__, ul_command);
0148 
0149     return 0;
0150 
0151 }
0152 EXPORT_SYMBOL(rtl_cam_delete_one_entry);
0153 
0154 void rtl_cam_reset_all_entry(struct ieee80211_hw *hw)
0155 {
0156     u32 ul_command;
0157     struct rtl_priv *rtlpriv = rtl_priv(hw);
0158 
0159     ul_command = BIT(31) | BIT(30);
0160     rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
0161 }
0162 EXPORT_SYMBOL(rtl_cam_reset_all_entry);
0163 
0164 void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index)
0165 {
0166     struct rtl_priv *rtlpriv = rtl_priv(hw);
0167 
0168     u32 ul_command;
0169     u32 ul_content;
0170     u32 ul_enc_algo;
0171 
0172     switch (rtlpriv->sec.pairwise_enc_algorithm) {
0173     case WEP40_ENCRYPTION:
0174         ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40];
0175         break;
0176     case WEP104_ENCRYPTION:
0177         ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104];
0178         break;
0179     case TKIP_ENCRYPTION:
0180         ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP];
0181         break;
0182     case AESCCMP_ENCRYPTION:
0183         ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
0184         break;
0185     default:
0186         ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
0187     }
0188 
0189     ul_content = (uc_index & 3) | ((u16) (ul_enc_algo) << 2);
0190 
0191     ul_content |= BIT(15);
0192     ul_command = CAM_CONTENT_COUNT * uc_index;
0193     ul_command = ul_command | BIT(31) | BIT(16);
0194 
0195     rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
0196     rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
0197 
0198     rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
0199         "%s: WRITE A4: %x\n", __func__, ul_content);
0200     rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
0201         "%s: WRITE A0: %x\n", __func__, ul_command);
0202 }
0203 EXPORT_SYMBOL(rtl_cam_mark_invalid);
0204 
0205 void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index)
0206 {
0207     struct rtl_priv *rtlpriv = rtl_priv(hw);
0208 
0209     u32 ul_command;
0210     u32 ul_content;
0211     u32 ul_encalgo;
0212     u8 entry_i;
0213 
0214     switch (rtlpriv->sec.pairwise_enc_algorithm) {
0215     case WEP40_ENCRYPTION:
0216         ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40];
0217         break;
0218     case WEP104_ENCRYPTION:
0219         ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104];
0220         break;
0221     case TKIP_ENCRYPTION:
0222         ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP];
0223         break;
0224     case AESCCMP_ENCRYPTION:
0225         ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
0226         break;
0227     default:
0228         ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
0229     }
0230 
0231     for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
0232 
0233         if (entry_i == 0) {
0234             ul_content =
0235                 (uc_index & 0x03) | ((u16) (ul_encalgo) << 2);
0236             ul_content |= BIT(15);
0237 
0238         } else {
0239             ul_content = 0;
0240         }
0241 
0242         ul_command = CAM_CONTENT_COUNT * uc_index + entry_i;
0243         ul_command = ul_command | BIT(31) | BIT(16);
0244 
0245         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
0246         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
0247 
0248         rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0249             "%s: WRITE A4: %x\n", __func__, ul_content);
0250         rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
0251             "%s: WRITE A0: %x\n", __func__, ul_command);
0252     }
0253 
0254 }
0255 EXPORT_SYMBOL(rtl_cam_empty_entry);
0256 
0257 u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr)
0258 {
0259     struct rtl_priv *rtlpriv = rtl_priv(hw);
0260     u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4;
0261     u8 entry_idx = 0;
0262     u8 i, *addr;
0263 
0264     if (NULL == sta_addr) {
0265         pr_err("sta_addr is NULL.\n");
0266         return TOTAL_CAM_ENTRY;
0267     }
0268     /* Does STA already exist? */
0269     for (i = 4; i < TOTAL_CAM_ENTRY; i++) {
0270         addr = rtlpriv->sec.hwsec_cam_sta_addr[i];
0271         if (ether_addr_equal_unaligned(addr, sta_addr))
0272             return i;
0273     }
0274     /* Get a free CAM entry. */
0275     for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) {
0276         if ((bitmap & BIT(0)) == 0) {
0277             pr_err("-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n",
0278                    rtlpriv->sec.hwsec_cam_bitmap, entry_idx);
0279             rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx;
0280             memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx],
0281                    sta_addr, ETH_ALEN);
0282             return entry_idx;
0283         }
0284         bitmap = bitmap >> 1;
0285     }
0286     return TOTAL_CAM_ENTRY;
0287 }
0288 EXPORT_SYMBOL(rtl_cam_get_free_entry);
0289 
0290 void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
0291 {
0292     struct rtl_priv *rtlpriv = rtl_priv(hw);
0293     u32 bitmap;
0294     u8 i, *addr;
0295 
0296     if (NULL == sta_addr) {
0297         pr_err("sta_addr is NULL.\n");
0298         return;
0299     }
0300 
0301     if (is_zero_ether_addr(sta_addr)) {
0302         pr_err("sta_addr is %pM\n", sta_addr);
0303         return;
0304     }
0305     /* Does STA already exist? */
0306     for (i = 4; i < TOTAL_CAM_ENTRY; i++) {
0307         addr = rtlpriv->sec.hwsec_cam_sta_addr[i];
0308         bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i;
0309         if (((bitmap & BIT(0)) == BIT(0)) &&
0310             (ether_addr_equal_unaligned(addr, sta_addr))) {
0311             /* Remove from HW Security CAM */
0312             eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]);
0313             rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
0314             rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
0315                 "&&&&&&&&&del entry %d\n", i);
0316         }
0317     }
0318     return;
0319 }
0320 EXPORT_SYMBOL(rtl_cam_del_entry);