brintos

brintos / linux-shallow public Read only

0
0
Text · 8.7 KiB · f9d0d13 Raw
322 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2009-2012  Realtek Corporation.*/3 4#include "wifi.h"5#include "cam.h"6#include <linux/export.h>7 8void 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 20static 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)) << 880			    | (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 98u8 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	else119		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}129EXPORT_SYMBOL(rtl_cam_add_one_entry);130 131int 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}153EXPORT_SYMBOL(rtl_cam_delete_one_entry);154 155void 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}163EXPORT_SYMBOL(rtl_cam_reset_all_entry);164 165void 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}204EXPORT_SYMBOL(rtl_cam_mark_invalid);205 206void 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}256EXPORT_SYMBOL(rtl_cam_empty_entry);257 258u8 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}289EXPORT_SYMBOL(rtl_cam_get_free_entry);290 291void 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}321EXPORT_SYMBOL(rtl_cam_del_entry);322