Merge remote-tracking branch 'staging/staging-next'
[deliverable/linux.git] / drivers / staging / rtl8192e / rtl8192e / rtl_cam.c
CommitLineData
94a79942
LF
1/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 *
4 * Based on the r8180 driver, which is:
559a4c31 5 * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
94a79942
LF
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
94a79942
LF
15 * The full GNU General Public License is included in this distribution in the
16 * file called LICENSE.
17 *
18 * Contact Information:
19 * wlanfae <wlanfae@realtek.com>
20******************************************************************************/
21#include "rtl_core.h"
22#include "r8192E_phy.h"
23#include "r8192E_phyreg.h"
24#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
25#include "r8192E_cmdpkt.h"
26
358e4ee1 27void rtl92e_cam_reset(struct net_device *dev)
94a79942
LF
28{
29 u32 ulcommand = 0;
30
31 ulcommand |= BIT31|BIT30;
8ea54100 32 rtl92e_writel(dev, RWCAM, ulcommand);
94a79942
LF
33}
34
37420932 35void rtl92e_enable_hw_security_config(struct net_device *dev)
94a79942
LF
36{
37 u8 SECR_value = 0x0;
38 struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
b6da7313 39 struct rtllib_device *ieee = priv->rtllib;
3a6b70c3 40
94a79942 41 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
4c29207a
MK
42 if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) ||
43 (ieee->pairwise_key_type == KEY_TYPE_WEP104)) &&
b6da7313 44 (priv->rtllib->auth_mode != 2)) {
94a79942
LF
45 SECR_value |= SCR_RxUseDK;
46 SECR_value |= SCR_TxUseDK;
b6da7313
LF
47 } else if ((ieee->iw_mode == IW_MODE_ADHOC) &&
48 (ieee->pairwise_key_type & (KEY_TYPE_CCMP |
49 KEY_TYPE_TKIP))) {
94a79942
LF
50 SECR_value |= SCR_RxUseDK;
51 SECR_value |= SCR_TxUseDK;
52 }
53
54
55 ieee->hwsec_active = 1;
b6da7313 56 if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
94a79942
LF
57 ieee->hwsec_active = 0;
58 SECR_value &= ~SCR_RxDecEnable;
59 }
60
b6da7313
LF
61 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
62 __func__, ieee->hwsec_active, ieee->pairwise_key_type,
63 SECR_value);
d8ae1967 64 rtl92e_writeb(dev, SECR, SECR_value);
94a79942
LF
65}
66
aae7e72e
MK
67void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
68 u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
69 u32 *KeyContent, u8 is_mesh)
94a79942
LF
70{
71 struct r8192_priv *priv = rtllib_priv(dev);
72 struct rtllib_device *ieee = priv->rtllib;
3a6b70c3 73
0822339b
MK
74 RT_TRACE(COMP_DBG,
75 "===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",
76 __func__, EntryNo, KeyIndex, KeyType, is_mesh);
d1f0f311
DC
77
78 if (EntryNo >= TOTAL_CAM_ENTRY)
79 return;
80
b6da7313
LF
81 if (!is_mesh) {
82 ieee->swcamtable[EntryNo].bused = true;
83 ieee->swcamtable[EntryNo].key_index = KeyIndex;
84 ieee->swcamtable[EntryNo].key_type = KeyType;
85 memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
86 ieee->swcamtable[EntryNo].useDK = DefaultKey;
87 memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
94a79942
LF
88 }
89}
90
408bd7b7
MK
91void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
92 u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
93 u32 *KeyContent)
94a79942
LF
94{
95 u32 TargetCommand = 0;
96 u32 TargetContent = 0;
97 u16 usConfig = 0;
98 u8 i;
99 struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
de7c885a 100 enum rt_rf_power_state rtState;
3a6b70c3 101
94a79942 102 rtState = priv->rtllib->eRFPowerState;
b6da7313
LF
103 if (priv->rtllib->PowerSaveControl.bInactivePs) {
104 if (rtState == eRfOff) {
105 if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
3b4140af
MK
106 netdev_warn(dev, "%s(): RF is OFF.\n",
107 __func__);
dc986e3e 108 return;
b6da7313 109 }
38bee763 110 mutex_lock(&priv->rtllib->ips_mutex);
2ab2aba2 111 rtl92e_ips_leave(dev);
38bee763 112 mutex_unlock(&priv->rtllib->ips_mutex);
94a79942
LF
113 }
114 }
115 priv->rtllib->is_set_key = true;
a9cf7250 116 if (EntryNo >= TOTAL_CAM_ENTRY) {
3b4140af 117 netdev_info(dev, "%s(): Invalid CAM entry\n", __func__);
a9cf7250
DC
118 return;
119 }
94a79942 120
0822339b 121 RT_TRACE(COMP_SEC,
408bd7b7 122 "====>to rtl92e_set_key(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
0822339b 123 dev, EntryNo, KeyIndex, KeyType, MacAddr);
94a79942
LF
124
125 if (DefaultKey)
126 usConfig |= BIT15 | (KeyType<<2);
127 else
128 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
129
130
131 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
b6da7313 132 TargetCommand = i + CAM_CONTENT_COUNT * EntryNo;
94a79942
LF
133 TargetCommand |= BIT31|BIT16;
134
135 if (i == 0) {
b6da7313
LF
136 TargetContent = (u32)(*(MacAddr+0)) << 16 |
137 (u32)(*(MacAddr+1)) << 24 |
94a79942
LF
138 (u32)usConfig;
139
8ea54100
MK
140 rtl92e_writel(dev, WCAMI, TargetContent);
141 rtl92e_writel(dev, RWCAM, TargetCommand);
94a79942 142 } else if (i == 1) {
b6da7313
LF
143 TargetContent = (u32)(*(MacAddr+2)) |
144 (u32)(*(MacAddr+3)) << 8 |
145 (u32)(*(MacAddr+4)) << 16 |
94a79942 146 (u32)(*(MacAddr+5)) << 24;
8ea54100
MK
147 rtl92e_writel(dev, WCAMI, TargetContent);
148 rtl92e_writel(dev, RWCAM, TargetCommand);
94a79942
LF
149 } else {
150 if (KeyContent != NULL) {
8ea54100
MK
151 rtl92e_writel(dev, WCAMI,
152 (u32)(*(KeyContent+i-2)));
153 rtl92e_writel(dev, RWCAM, TargetCommand);
94a79942 154 udelay(100);
94a79942
LF
155 }
156 }
157 }
b6da7313 158 RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
94a79942
LF
159}
160
66497f02 161void rtl92e_cam_restore(struct net_device *dev)
94a79942
LF
162{
163 u8 EntryId = 0;
164 struct r8192_priv *priv = rtllib_priv(dev);
b6da7313 165 u8 *MacAddr = priv->rtllib->current_network.bssid;
94a79942
LF
166
167 static u8 CAM_CONST_ADDR[4][6] = {
168 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
169 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
170 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
b6da7313
LF
171 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
172 };
173 static u8 CAM_CONST_BROAD[] = {
174 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
175 };
94a79942 176
66497f02 177 RT_TRACE(COMP_SEC, "rtl92e_cam_restore:\n");
94a79942
LF
178
179
b6da7313
LF
180 if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
181 (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
94a79942 182
b6da7313
LF
183 for (EntryId = 0; EntryId < 4; EntryId++) {
184 MacAddr = CAM_CONST_ADDR[EntryId];
185 if (priv->rtllib->swcamtable[EntryId].bused) {
408bd7b7
MK
186 rtl92e_set_key(dev, EntryId, EntryId,
187 priv->rtllib->pairwise_key_type,
188 MacAddr, 0,
189 (u32 *)(&priv->rtllib->swcamtable
190 [EntryId].key_buf[0]));
94a79942
LF
191 }
192 }
193
b6da7313
LF
194 } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
195 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
408bd7b7
MK
196 rtl92e_set_key(dev, 4, 0,
197 priv->rtllib->pairwise_key_type,
198 (u8 *)dev->dev_addr, 0,
199 (u32 *)(&priv->rtllib->swcamtable[4].
200 key_buf[0]));
b6da7313 201 } else {
408bd7b7
MK
202 rtl92e_set_key(dev, 4, 0,
203 priv->rtllib->pairwise_key_type,
204 MacAddr, 0,
205 (u32 *)(&priv->rtllib->swcamtable[4].
206 key_buf[0]));
94a79942 207 }
94a79942 208
b6da7313
LF
209 } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
210 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
408bd7b7
MK
211 rtl92e_set_key(dev, 4, 0,
212 priv->rtllib->pairwise_key_type,
213 (u8 *)dev->dev_addr, 0,
214 (u32 *)(&priv->rtllib->swcamtable[4].
215 key_buf[0]));
b6da7313 216 } else {
408bd7b7
MK
217 rtl92e_set_key(dev, 4, 0,
218 priv->rtllib->pairwise_key_type, MacAddr,
219 0, (u32 *)(&priv->rtllib->swcamtable[4].
220 key_buf[0]));
94a79942 221 }
94a79942
LF
222 }
223
b6da7313 224 if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
94a79942 225 MacAddr = CAM_CONST_BROAD;
b6da7313
LF
226 for (EntryId = 1; EntryId < 4; EntryId++) {
227 if (priv->rtllib->swcamtable[EntryId].bused) {
408bd7b7
MK
228 rtl92e_set_key(dev, EntryId, EntryId,
229 priv->rtllib->group_key_type,
230 MacAddr, 0,
231 (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
94a79942
LF
232 }
233 }
b6da7313
LF
234 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
235 if (priv->rtllib->swcamtable[0].bused) {
408bd7b7
MK
236 rtl92e_set_key(dev, 0, 0,
237 priv->rtllib->group_key_type,
238 CAM_CONST_ADDR[0], 0,
239 (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
b6da7313 240 } else {
3b4140af
MK
241 netdev_warn(dev,
242 "%s(): ADHOC TKIP: missing key entry.\n",
243 __func__);
94a79942
LF
244 return;
245 }
246 }
247 } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
248 MacAddr = CAM_CONST_BROAD;
b6da7313
LF
249 for (EntryId = 1; EntryId < 4; EntryId++) {
250 if (priv->rtllib->swcamtable[EntryId].bused) {
408bd7b7
MK
251 rtl92e_set_key(dev, EntryId, EntryId,
252 priv->rtllib->group_key_type,
253 MacAddr, 0,
254 (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
94a79942
LF
255 }
256 }
257
258 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
259 if (priv->rtllib->swcamtable[0].bused) {
408bd7b7
MK
260 rtl92e_set_key(dev, 0, 0,
261 priv->rtllib->group_key_type,
262 CAM_CONST_ADDR[0], 0,
263 (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
94a79942 264 } else {
3b4140af
MK
265 netdev_warn(dev,
266 "%s(): ADHOC CCMP: missing key entry.\n",
267 __func__);
94a79942
LF
268 return;
269 }
270 }
271 }
272}
This page took 0.577492 seconds and 5 git commands to generate.