1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
4  *
5  * Based on the r8180 driver, which is:
6  * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
7  *
8  * Contact Information: wlanfae <wlanfae@realtek.com>
9  */
10 #include "rtl_core.h"
11 #include "r8192E_phy.h"
12 #include "r8192E_phyreg.h"
13 #include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
14 #include "r8192E_cmdpkt.h"
15 
rtl92e_cam_reset(struct net_device * dev)16 void rtl92e_cam_reset(struct net_device *dev)
17 {
18 	u32 ulcommand = 0;
19 
20 	ulcommand |= BIT31|BIT30;
21 	rtl92e_writel(dev, RWCAM, ulcommand);
22 }
23 
rtl92e_enable_hw_security_config(struct net_device * dev)24 void rtl92e_enable_hw_security_config(struct net_device *dev)
25 {
26 	u8 SECR_value = 0x0;
27 	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
28 	struct rtllib_device *ieee = priv->rtllib;
29 
30 	SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
31 	if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) ||
32 	     (ieee->pairwise_key_type == KEY_TYPE_WEP104)) &&
33 	     (priv->rtllib->auth_mode != 2)) {
34 		SECR_value |= SCR_RxUseDK;
35 		SECR_value |= SCR_TxUseDK;
36 	} else if ((ieee->iw_mode == IW_MODE_ADHOC) &&
37 		   (ieee->pairwise_key_type & (KEY_TYPE_CCMP |
38 		   KEY_TYPE_TKIP))) {
39 		SECR_value |= SCR_RxUseDK;
40 		SECR_value |= SCR_TxUseDK;
41 	}
42 
43 
44 	ieee->hwsec_active = 1;
45 	if ((ieee->pHTInfo->iot_action & HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
46 		ieee->hwsec_active = 0;
47 		SECR_value &= ~SCR_RxDecEnable;
48 	}
49 	rtl92e_writeb(dev, SECR, SECR_value);
50 }
51 
rtl92e_set_swcam(struct net_device * dev,u8 EntryNo,u8 KeyIndex,u16 KeyType,const u8 * MacAddr,u8 DefaultKey,u32 * KeyContent,u8 is_mesh)52 void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
53 		      u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
54 		      u32 *KeyContent, u8 is_mesh)
55 {
56 	struct r8192_priv *priv = rtllib_priv(dev);
57 	struct rtllib_device *ieee = priv->rtllib;
58 
59 	if (EntryNo >= TOTAL_CAM_ENTRY)
60 		return;
61 
62 	if (!is_mesh) {
63 		ieee->swcamtable[EntryNo].bused = true;
64 		ieee->swcamtable[EntryNo].key_index = KeyIndex;
65 		ieee->swcamtable[EntryNo].key_type = KeyType;
66 		memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
67 		ieee->swcamtable[EntryNo].useDK = DefaultKey;
68 		memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
69 	}
70 }
71 
rtl92e_set_key(struct net_device * dev,u8 EntryNo,u8 KeyIndex,u16 KeyType,const u8 * MacAddr,u8 DefaultKey,u32 * KeyContent)72 void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
73 		    u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
74 		    u32 *KeyContent)
75 {
76 	u32 TargetCommand = 0;
77 	u32 TargetContent = 0;
78 	u16 usConfig = 0;
79 	u8 i;
80 	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
81 	enum rt_rf_power_state rt_state;
82 
83 	rt_state = priv->rtllib->rf_power_state;
84 	if (priv->rtllib->PowerSaveControl.bInactivePs) {
85 		if (rt_state == rf_off) {
86 			if (priv->rtllib->rf_off_reason > RF_CHANGE_BY_IPS) {
87 				netdev_warn(dev, "%s(): RF is OFF.\n",
88 					    __func__);
89 				return;
90 			}
91 			mutex_lock(&priv->rtllib->ips_mutex);
92 			rtl92e_ips_leave(dev);
93 			mutex_unlock(&priv->rtllib->ips_mutex);
94 		}
95 	}
96 	priv->rtllib->is_set_key = true;
97 	if (EntryNo >= TOTAL_CAM_ENTRY) {
98 		netdev_info(dev, "%s(): Invalid CAM entry\n", __func__);
99 		return;
100 	}
101 
102 	if (DefaultKey)
103 		usConfig |= BIT15 | (KeyType<<2);
104 	else
105 		usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
106 
107 
108 	for (i = 0; i < CAM_CONTENT_COUNT; i++) {
109 		TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
110 		TargetCommand |= BIT31|BIT16;
111 
112 		if (i == 0) {
113 			TargetContent = (u32)(*(MacAddr+0)) << 16 |
114 				(u32)(*(MacAddr+1)) << 24 |
115 				(u32)usConfig;
116 
117 			rtl92e_writel(dev, WCAMI, TargetContent);
118 			rtl92e_writel(dev, RWCAM, TargetCommand);
119 		} else if (i == 1) {
120 			TargetContent = (u32)(*(MacAddr+2)) |
121 				(u32)(*(MacAddr+3)) <<  8 |
122 				(u32)(*(MacAddr+4)) << 16 |
123 				(u32)(*(MacAddr+5)) << 24;
124 			rtl92e_writel(dev, WCAMI, TargetContent);
125 			rtl92e_writel(dev, RWCAM, TargetCommand);
126 		} else {
127 			if (KeyContent != NULL) {
128 				rtl92e_writel(dev, WCAMI,
129 					      (u32)(*(KeyContent+i-2)));
130 				rtl92e_writel(dev, RWCAM, TargetCommand);
131 				udelay(100);
132 			}
133 		}
134 	}
135 }
136 
rtl92e_cam_restore(struct net_device * dev)137 void rtl92e_cam_restore(struct net_device *dev)
138 {
139 	u8 EntryId = 0;
140 	struct r8192_priv *priv = rtllib_priv(dev);
141 	u8 *MacAddr = priv->rtllib->current_network.bssid;
142 
143 	static u8	CAM_CONST_ADDR[4][6] = {
144 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
145 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
146 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
147 		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
148 	};
149 	static u8	CAM_CONST_BROAD[] = {
150 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
151 	};
152 
153 	if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
154 	    (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
155 
156 		for (EntryId = 0; EntryId < 4; EntryId++) {
157 			MacAddr = CAM_CONST_ADDR[EntryId];
158 			if (priv->rtllib->swcamtable[EntryId].bused) {
159 				rtl92e_set_key(dev, EntryId, EntryId,
160 					       priv->rtllib->pairwise_key_type,
161 					       MacAddr, 0,
162 					       (u32 *)(&priv->rtllib->swcamtable
163 						       [EntryId].key_buf[0]));
164 			}
165 		}
166 
167 	} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
168 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
169 			rtl92e_set_key(dev, 4, 0,
170 				       priv->rtllib->pairwise_key_type,
171 				       (const u8 *)dev->dev_addr, 0,
172 				       (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
173 		} else {
174 			rtl92e_set_key(dev, 4, 0,
175 				       priv->rtllib->pairwise_key_type,
176 				       MacAddr, 0,
177 				       (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
178 		}
179 
180 	} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
181 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
182 			rtl92e_set_key(dev, 4, 0,
183 				       priv->rtllib->pairwise_key_type,
184 				       (const u8 *)dev->dev_addr, 0,
185 				       (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
186 		} else {
187 			rtl92e_set_key(dev, 4, 0,
188 				       priv->rtllib->pairwise_key_type, MacAddr,
189 				       0, (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
190 			}
191 	}
192 
193 	if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
194 		MacAddr = CAM_CONST_BROAD;
195 		for (EntryId = 1; EntryId < 4; EntryId++) {
196 			if (priv->rtllib->swcamtable[EntryId].bused) {
197 				rtl92e_set_key(dev, EntryId, EntryId,
198 					       priv->rtllib->group_key_type,
199 					       MacAddr, 0,
200 					       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
201 			}
202 		}
203 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
204 			if (priv->rtllib->swcamtable[0].bused) {
205 				rtl92e_set_key(dev, 0, 0,
206 					       priv->rtllib->group_key_type,
207 					       CAM_CONST_ADDR[0], 0,
208 					       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
209 			} else {
210 				netdev_warn(dev,
211 					    "%s(): ADHOC TKIP: missing key entry.\n",
212 					    __func__);
213 				return;
214 			}
215 		}
216 	} else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
217 		MacAddr = CAM_CONST_BROAD;
218 		for (EntryId = 1; EntryId < 4; EntryId++) {
219 			if (priv->rtllib->swcamtable[EntryId].bused) {
220 				rtl92e_set_key(dev, EntryId, EntryId,
221 					       priv->rtllib->group_key_type,
222 					       MacAddr, 0,
223 					       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
224 			}
225 		}
226 
227 		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
228 			if (priv->rtllib->swcamtable[0].bused) {
229 				rtl92e_set_key(dev, 0, 0,
230 					       priv->rtllib->group_key_type,
231 					       CAM_CONST_ADDR[0], 0,
232 					       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
233 			} else {
234 				netdev_warn(dev,
235 					    "%s(): ADHOC CCMP: missing key entry.\n",
236 					    __func__);
237 				return;
238 			}
239 		}
240 	}
241 }
242