These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / rtl8192e / rtl8192e / rtl_cam.c
1 /******************************************************************************
2  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3  *
4  * Based on the r8180 driver, which is:
5  * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
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  *
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
27 void rtl92e_cam_reset(struct net_device *dev)
28 {
29         u32 ulcommand = 0;
30
31         ulcommand |= BIT31|BIT30;
32         rtl92e_writel(dev, RWCAM, ulcommand);
33 }
34
35 void rtl92e_enable_hw_security_config(struct net_device *dev)
36 {
37         u8 SECR_value = 0x0;
38         struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
39         struct rtllib_device *ieee = priv->rtllib;
40
41         SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
42         if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) ||
43              (ieee->pairwise_key_type == KEY_TYPE_WEP104)) &&
44              (priv->rtllib->auth_mode != 2)) {
45                 SECR_value |= SCR_RxUseDK;
46                 SECR_value |= SCR_TxUseDK;
47         } else if ((ieee->iw_mode == IW_MODE_ADHOC) &&
48                    (ieee->pairwise_key_type & (KEY_TYPE_CCMP |
49                    KEY_TYPE_TKIP))) {
50                 SECR_value |= SCR_RxUseDK;
51                 SECR_value |= SCR_TxUseDK;
52         }
53
54
55         ieee->hwsec_active = 1;
56         if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
57                 ieee->hwsec_active = 0;
58                 SECR_value &= ~SCR_RxDecEnable;
59         }
60
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);
64         rtl92e_writeb(dev, SECR, SECR_value);
65 }
66
67 void 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)
70 {
71         struct r8192_priv *priv = rtllib_priv(dev);
72         struct rtllib_device *ieee = priv->rtllib;
73
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);
77
78         if (EntryNo >= TOTAL_CAM_ENTRY)
79                 return;
80
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);
88         }
89 }
90
91 void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
92                     u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
93                     u32 *KeyContent)
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);
100         enum rt_rf_power_state rtState;
101
102         rtState = priv->rtllib->eRFPowerState;
103         if (priv->rtllib->PowerSaveControl.bInactivePs) {
104                 if (rtState == eRfOff) {
105                         if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
106                                 netdev_warn(dev, "%s(): RF is OFF.\n",
107                                             __func__);
108                                 return;
109                         }
110                         down(&priv->rtllib->ips_sem);
111                         rtl92e_ips_leave(dev);
112                         up(&priv->rtllib->ips_sem);
113                 }
114         }
115         priv->rtllib->is_set_key = true;
116         if (EntryNo >= TOTAL_CAM_ENTRY) {
117                 netdev_info(dev, "%s(): Invalid CAM entry\n", __func__);
118                 return;
119         }
120
121         RT_TRACE(COMP_SEC,
122                  "====>to rtl92e_set_key(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
123                  dev, EntryNo, KeyIndex, KeyType, MacAddr);
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++) {
132                 TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
133                 TargetCommand |= BIT31|BIT16;
134
135                 if (i == 0) {
136                         TargetContent = (u32)(*(MacAddr+0)) << 16 |
137                                 (u32)(*(MacAddr+1)) << 24 |
138                                 (u32)usConfig;
139
140                         rtl92e_writel(dev, WCAMI, TargetContent);
141                         rtl92e_writel(dev, RWCAM, TargetCommand);
142                 } else if (i == 1) {
143                         TargetContent = (u32)(*(MacAddr+2)) |
144                                 (u32)(*(MacAddr+3)) <<  8 |
145                                 (u32)(*(MacAddr+4)) << 16 |
146                                 (u32)(*(MacAddr+5)) << 24;
147                         rtl92e_writel(dev, WCAMI, TargetContent);
148                         rtl92e_writel(dev, RWCAM, TargetCommand);
149                 } else {
150                         if (KeyContent != NULL) {
151                                 rtl92e_writel(dev, WCAMI,
152                                               (u32)(*(KeyContent+i-2)));
153                                 rtl92e_writel(dev, RWCAM, TargetCommand);
154                                 udelay(100);
155                         }
156                 }
157         }
158         RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
159 }
160
161 void rtl92e_cam_restore(struct net_device *dev)
162 {
163         u8 EntryId = 0;
164         struct r8192_priv *priv = rtllib_priv(dev);
165         u8 *MacAddr = priv->rtllib->current_network.bssid;
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},
171                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
172         };
173         static u8       CAM_CONST_BROAD[] = {
174                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
175         };
176
177         RT_TRACE(COMP_SEC, "rtl92e_cam_restore:\n");
178
179
180         if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
181             (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
182
183                 for (EntryId = 0; EntryId < 4; EntryId++) {
184                         MacAddr = CAM_CONST_ADDR[EntryId];
185                         if (priv->rtllib->swcamtable[EntryId].bused) {
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]));
191                         }
192                 }
193
194         } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
195                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
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]));
201                 } else {
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]));
207                 }
208
209         } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
210                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
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]));
216                 } else {
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]));
221                         }
222         }
223
224         if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
225                 MacAddr = CAM_CONST_BROAD;
226                 for (EntryId = 1; EntryId < 4; EntryId++) {
227                         if (priv->rtllib->swcamtable[EntryId].bused) {
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]));
232                         }
233                 }
234                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
235                         if (priv->rtllib->swcamtable[0].bused) {
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]));
240                         } else {
241                                 netdev_warn(dev,
242                                             "%s(): ADHOC TKIP: missing key entry.\n",
243                                             __func__);
244                                 return;
245                         }
246                 }
247         } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
248                 MacAddr = CAM_CONST_BROAD;
249                 for (EntryId = 1; EntryId < 4; EntryId++) {
250                         if (priv->rtllib->swcamtable[EntryId].bused) {
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]));
255                         }
256                 }
257
258                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
259                         if (priv->rtllib->swcamtable[0].bused) {
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]));
264                         } else {
265                                 netdev_warn(dev,
266                                             "%s(): ADHOC CCMP: missing key entry.\n",
267                                             __func__);
268                                 return;
269                         }
270                 }
271         }
272 }