GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / staging / rtl8192e / rtl8192e / rtl_cam.c
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
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
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->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
46                 ieee->hwsec_active = 0;
47                 SECR_value &= ~SCR_RxDecEnable;
48         }
49
50         RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
51                  __func__, ieee->hwsec_active, ieee->pairwise_key_type,
52                  SECR_value);
53         rtl92e_writeb(dev, SECR, SECR_value);
54 }
55
56 void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
57                       u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
58                       u32 *KeyContent, u8 is_mesh)
59 {
60         struct r8192_priv *priv = rtllib_priv(dev);
61         struct rtllib_device *ieee = priv->rtllib;
62
63         RT_TRACE(COMP_DBG,
64                  "===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",
65                  __func__, EntryNo, KeyIndex, KeyType, is_mesh);
66
67         if (EntryNo >= TOTAL_CAM_ENTRY)
68                 return;
69
70         if (!is_mesh) {
71                 ieee->swcamtable[EntryNo].bused = true;
72                 ieee->swcamtable[EntryNo].key_index = KeyIndex;
73                 ieee->swcamtable[EntryNo].key_type = KeyType;
74                 memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
75                 ieee->swcamtable[EntryNo].useDK = DefaultKey;
76                 memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
77         }
78 }
79
80 void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
81                     u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
82                     u32 *KeyContent)
83 {
84         u32 TargetCommand = 0;
85         u32 TargetContent = 0;
86         u16 usConfig = 0;
87         u8 i;
88         struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
89         enum rt_rf_power_state rtState;
90
91         rtState = priv->rtllib->eRFPowerState;
92         if (priv->rtllib->PowerSaveControl.bInactivePs) {
93                 if (rtState == eRfOff) {
94                         if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
95                                 netdev_warn(dev, "%s(): RF is OFF.\n",
96                                             __func__);
97                                 return;
98                         }
99                         mutex_lock(&priv->rtllib->ips_mutex);
100                         rtl92e_ips_leave(dev);
101                         mutex_unlock(&priv->rtllib->ips_mutex);
102                 }
103         }
104         priv->rtllib->is_set_key = true;
105         if (EntryNo >= TOTAL_CAM_ENTRY) {
106                 netdev_info(dev, "%s(): Invalid CAM entry\n", __func__);
107                 return;
108         }
109
110         RT_TRACE(COMP_SEC,
111                  "====>to %s, dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
112                  __func__, dev, EntryNo, KeyIndex, KeyType, MacAddr);
113
114         if (DefaultKey)
115                 usConfig |= BIT15 | (KeyType<<2);
116         else
117                 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
118
119
120         for (i = 0; i < CAM_CONTENT_COUNT; i++) {
121                 TargetCommand  = i + CAM_CONTENT_COUNT * EntryNo;
122                 TargetCommand |= BIT31|BIT16;
123
124                 if (i == 0) {
125                         TargetContent = (u32)(*(MacAddr+0)) << 16 |
126                                 (u32)(*(MacAddr+1)) << 24 |
127                                 (u32)usConfig;
128
129                         rtl92e_writel(dev, WCAMI, TargetContent);
130                         rtl92e_writel(dev, RWCAM, TargetCommand);
131                 } else if (i == 1) {
132                         TargetContent = (u32)(*(MacAddr+2)) |
133                                 (u32)(*(MacAddr+3)) <<  8 |
134                                 (u32)(*(MacAddr+4)) << 16 |
135                                 (u32)(*(MacAddr+5)) << 24;
136                         rtl92e_writel(dev, WCAMI, TargetContent);
137                         rtl92e_writel(dev, RWCAM, TargetCommand);
138                 } else {
139                         if (KeyContent != NULL) {
140                                 rtl92e_writel(dev, WCAMI,
141                                               (u32)(*(KeyContent+i-2)));
142                                 rtl92e_writel(dev, RWCAM, TargetCommand);
143                                 udelay(100);
144                         }
145                 }
146         }
147         RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
148 }
149
150 void rtl92e_cam_restore(struct net_device *dev)
151 {
152         u8 EntryId = 0;
153         struct r8192_priv *priv = rtllib_priv(dev);
154         u8 *MacAddr = priv->rtllib->current_network.bssid;
155
156         static u8       CAM_CONST_ADDR[4][6] = {
157                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
158                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
159                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
160                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
161         };
162         static u8       CAM_CONST_BROAD[] = {
163                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
164         };
165
166         RT_TRACE(COMP_SEC, "%s:\n", __func__);
167
168
169         if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
170             (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
171
172                 for (EntryId = 0; EntryId < 4; EntryId++) {
173                         MacAddr = CAM_CONST_ADDR[EntryId];
174                         if (priv->rtllib->swcamtable[EntryId].bused) {
175                                 rtl92e_set_key(dev, EntryId, EntryId,
176                                                priv->rtllib->pairwise_key_type,
177                                                MacAddr, 0,
178                                                (u32 *)(&priv->rtllib->swcamtable
179                                                        [EntryId].key_buf[0]));
180                         }
181                 }
182
183         } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
184                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
185                         rtl92e_set_key(dev, 4, 0,
186                                        priv->rtllib->pairwise_key_type,
187                                        (const u8 *)dev->dev_addr, 0,
188                                        (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
189                 } else {
190                         rtl92e_set_key(dev, 4, 0,
191                                        priv->rtllib->pairwise_key_type,
192                                        MacAddr, 0,
193                                        (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
194                 }
195
196         } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
197                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
198                         rtl92e_set_key(dev, 4, 0,
199                                        priv->rtllib->pairwise_key_type,
200                                        (const u8 *)dev->dev_addr, 0,
201                                        (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
202                 } else {
203                         rtl92e_set_key(dev, 4, 0,
204                                        priv->rtllib->pairwise_key_type, MacAddr,
205                                        0, (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
206                         }
207         }
208
209         if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
210                 MacAddr = CAM_CONST_BROAD;
211                 for (EntryId = 1; EntryId < 4; EntryId++) {
212                         if (priv->rtllib->swcamtable[EntryId].bused) {
213                                 rtl92e_set_key(dev, EntryId, EntryId,
214                                                priv->rtllib->group_key_type,
215                                                MacAddr, 0,
216                                                (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
217                         }
218                 }
219                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
220                         if (priv->rtllib->swcamtable[0].bused) {
221                                 rtl92e_set_key(dev, 0, 0,
222                                                priv->rtllib->group_key_type,
223                                                CAM_CONST_ADDR[0], 0,
224                                                (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
225                         } else {
226                                 netdev_warn(dev,
227                                             "%s(): ADHOC TKIP: missing key entry.\n",
228                                             __func__);
229                                 return;
230                         }
231                 }
232         } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
233                 MacAddr = CAM_CONST_BROAD;
234                 for (EntryId = 1; EntryId < 4; EntryId++) {
235                         if (priv->rtllib->swcamtable[EntryId].bused) {
236                                 rtl92e_set_key(dev, EntryId, EntryId,
237                                                priv->rtllib->group_key_type,
238                                                MacAddr, 0,
239                                                (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
240                         }
241                 }
242
243                 if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
244                         if (priv->rtllib->swcamtable[0].bused) {
245                                 rtl92e_set_key(dev, 0, 0,
246                                                priv->rtllib->group_key_type,
247                                                CAM_CONST_ADDR[0], 0,
248                                                (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
249                         } else {
250                                 netdev_warn(dev,
251                                             "%s(): ADHOC CCMP: missing key entry.\n",
252                                             __func__);
253                                 return;
254                         }
255                 }
256         }
257 }