hwmon: (applesmc) Ignore some temperature registers
[pandora-kernel.git] / drivers / net / wireless / rtlwifi / cam.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2012  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  * The full GNU General Public License is included in this distribution in the
19  * file called LICENSE.
20  *
21  * Contact Information:
22  * wlanfae <wlanfae@realtek.com>
23  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24  * Hsinchu 300, Taiwan.
25  *
26  * Larry Finger <Larry.Finger@lwfinger.net>
27  *
28  *****************************************************************************/
29
30 #include <linux/export.h>
31 #include "wifi.h"
32 #include "cam.h"
33
34 void rtl_cam_reset_sec_info(struct ieee80211_hw *hw)
35 {
36         struct rtl_priv *rtlpriv = rtl_priv(hw);
37
38         rtlpriv->sec.use_defaultkey = false;
39         rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION;
40         rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION;
41         memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN);
42         memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE);
43         rtlpriv->sec.pairwise_key = NULL;
44 }
45
46 static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
47                            u8 *mac_addr, u8 *key_cont_128, u16 us_config)
48 {
49         struct rtl_priv *rtlpriv = rtl_priv(hw);
50
51         u32 target_command;
52         u32 target_content = 0;
53         u8 entry_i;
54
55         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
56                  "key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
57                  key_cont_128[0], key_cont_128[1],
58                  key_cont_128[2], key_cont_128[3],
59                  key_cont_128[4], key_cont_128[5]);
60
61         for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
62                 target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
63                 target_command = target_command | BIT(31) | BIT(16);
64
65                 if (entry_i == 0) {
66                         target_content = (u32) (*(mac_addr + 0)) << 16 |
67                             (u32) (*(mac_addr + 1)) << 24 | (u32) us_config;
68
69                         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
70                                         target_content);
71                         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
72                                         target_command);
73
74                         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "WRITE %x: %x\n",
75                                  rtlpriv->cfg->maps[WCAMI], target_content);
76                         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
77                                  "The Key ID is %d\n", entry_no);
78                         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "WRITE %x: %x\n",
79                                  rtlpriv->cfg->maps[RWCAM], target_command);
80
81                 } else if (entry_i == 1) {
82
83                         target_content = (u32) (*(mac_addr + 5)) << 24 |
84                             (u32) (*(mac_addr + 4)) << 16 |
85                             (u32) (*(mac_addr + 3)) << 8 |
86                             (u32) (*(mac_addr + 2));
87
88                         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
89                                         target_content);
90                         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
91                                         target_command);
92
93                         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "WRITE A4: %x\n",
94                                  target_content);
95                         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "WRITE A0: %x\n",
96                                  target_command);
97
98                 } else {
99
100                         target_content =
101                             (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 3)) <<
102                             24 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 2))
103                             << 16 |
104                             (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8
105                             | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 0));
106
107                         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
108                                         target_content);
109                         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
110                                         target_command);
111                         udelay(100);
112
113                         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "WRITE A4: %x\n",
114                                  target_content);
115                         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "WRITE A0: %x\n",
116                                  target_command);
117                 }
118         }
119
120         RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "after set key, usconfig:%x\n",
121                  us_config);
122 }
123
124 u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
125                          u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg,
126                          u32 ul_default_key, u8 *key_content)
127 {
128         u32 us_config;
129         struct rtl_priv *rtlpriv = rtl_priv(hw);
130
131         RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
132                  "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n",
133                  ul_entry_idx, ul_key_id, ul_enc_alg,
134                  ul_default_key, mac_addr);
135
136         if (ul_key_id == TOTAL_CAM_ENTRY) {
137                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
138                          "<=== ulKeyId exceed!\n");
139                 return 0;
140         }
141
142         if (ul_default_key == 1) {
143                 us_config = CFG_VALID | ((u16) (ul_enc_alg) << 2);
144         } else {
145                 us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id;
146         }
147
148         rtl_cam_program_entry(hw, ul_entry_idx, mac_addr,
149                               (u8 *) key_content, us_config);
150
151         RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "<===\n");
152
153         return 1;
154
155 }
156 EXPORT_SYMBOL(rtl_cam_add_one_entry);
157
158 int rtl_cam_delete_one_entry(struct ieee80211_hw *hw,
159                              u8 *mac_addr, u32 ul_key_id)
160 {
161         u32 ul_command;
162         struct rtl_priv *rtlpriv = rtl_priv(hw);
163
164         RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id);
165
166         ul_command = ul_key_id * CAM_CONTENT_COUNT;
167         ul_command = ul_command | BIT(31) | BIT(16);
168
169         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0);
170         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
171
172         RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
173                  "rtl_cam_delete_one_entry(): WRITE A4: %x\n", 0);
174         RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
175                  "rtl_cam_delete_one_entry(): WRITE A0: %x\n", ul_command);
176
177         return 0;
178
179 }
180 EXPORT_SYMBOL(rtl_cam_delete_one_entry);
181
182 void rtl_cam_reset_all_entry(struct ieee80211_hw *hw)
183 {
184         u32 ul_command;
185         struct rtl_priv *rtlpriv = rtl_priv(hw);
186
187         ul_command = BIT(31) | BIT(30);
188         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
189 }
190 EXPORT_SYMBOL(rtl_cam_reset_all_entry);
191
192 void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index)
193 {
194         struct rtl_priv *rtlpriv = rtl_priv(hw);
195
196         u32 ul_command;
197         u32 ul_content;
198         u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
199
200         switch (rtlpriv->sec.pairwise_enc_algorithm) {
201         case WEP40_ENCRYPTION:
202                 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40];
203                 break;
204         case WEP104_ENCRYPTION:
205                 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104];
206                 break;
207         case TKIP_ENCRYPTION:
208                 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP];
209                 break;
210         case AESCCMP_ENCRYPTION:
211                 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
212                 break;
213         default:
214                 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
215         }
216
217         ul_content = (uc_index & 3) | ((u16) (ul_enc_algo) << 2);
218
219         ul_content |= BIT(15);
220         ul_command = CAM_CONTENT_COUNT * uc_index;
221         ul_command = ul_command | BIT(31) | BIT(16);
222
223         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
224         rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
225
226         RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
227                  "rtl_cam_mark_invalid(): WRITE A4: %x\n", ul_content);
228         RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
229                  "rtl_cam_mark_invalid(): WRITE A0: %x\n", ul_command);
230 }
231 EXPORT_SYMBOL(rtl_cam_mark_invalid);
232
233 void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index)
234 {
235         struct rtl_priv *rtlpriv = rtl_priv(hw);
236
237         u32 ul_command;
238         u32 ul_content;
239         u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
240         u8 entry_i;
241
242         switch (rtlpriv->sec.pairwise_enc_algorithm) {
243         case WEP40_ENCRYPTION:
244                 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40];
245                 break;
246         case WEP104_ENCRYPTION:
247                 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104];
248                 break;
249         case TKIP_ENCRYPTION:
250                 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP];
251                 break;
252         case AESCCMP_ENCRYPTION:
253                 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
254                 break;
255         default:
256                 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
257         }
258
259         for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
260
261                 if (entry_i == 0) {
262                         ul_content =
263                             (uc_index & 0x03) | ((u16) (ul_encalgo) << 2);
264                         ul_content |= BIT(15);
265
266                 } else {
267                         ul_content = 0;
268                 }
269
270                 ul_command = CAM_CONTENT_COUNT * uc_index + entry_i;
271                 ul_command = ul_command | BIT(31) | BIT(16);
272
273                 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
274                 rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
275
276                 RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
277                          "rtl_cam_empty_entry(): WRITE A4: %x\n",
278                          ul_content);
279                 RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
280                          "rtl_cam_empty_entry(): WRITE A0: %x\n",
281                          ul_command);
282         }
283
284 }
285 EXPORT_SYMBOL(rtl_cam_empty_entry);
286
287 u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr)
288 {
289         struct rtl_priv *rtlpriv = rtl_priv(hw);
290         u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4;
291         u8 entry_idx = 0;
292         u8 i, *addr;
293
294         if (NULL == sta_addr) {
295                 RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, "sta_addr is NULL\n");
296                 return TOTAL_CAM_ENTRY;
297         }
298         /* Does STA already exist? */
299         for (i = 4; i < TOTAL_CAM_ENTRY; i++) {
300                 addr = rtlpriv->sec.hwsec_cam_sta_addr[i];
301                 if (memcmp(addr, sta_addr, ETH_ALEN) == 0)
302                         return i;
303         }
304         /* Get a free CAM entry. */
305         for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) {
306                 if ((bitmap & BIT(0)) == 0) {
307                         RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG,
308                                  "-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n",
309                                  rtlpriv->sec.hwsec_cam_bitmap, entry_idx);
310                         rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx;
311                         memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx],
312                                sta_addr, ETH_ALEN);
313                         return entry_idx;
314                 }
315                 bitmap = bitmap >> 1;
316         }
317         return TOTAL_CAM_ENTRY;
318 }
319 EXPORT_SYMBOL(rtl_cam_get_free_entry);
320
321 void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
322 {
323         struct rtl_priv *rtlpriv = rtl_priv(hw);
324         u32 bitmap;
325         u8 i, *addr;
326
327         if (NULL == sta_addr) {
328                 RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, "sta_addr is NULL\n");
329         }
330
331         if (is_zero_ether_addr(sta_addr)) {
332                 RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG,
333                          "sta_addr is %pM\n", sta_addr);
334                 return;
335         }
336         /* Does STA already exist? */
337         for (i = 4; i < TOTAL_CAM_ENTRY; i++) {
338                 addr = rtlpriv->sec.hwsec_cam_sta_addr[i];
339                 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i;
340                 if (((bitmap & BIT(0)) == BIT(0)) &&
341                     (memcmp(addr, sta_addr, ETH_ALEN) == 0)) {
342                         /* Remove from HW Security CAM */
343                         memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN);
344                         rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
345                         pr_info("&&&&&&&&&del entry %d\n", i);
346                 }
347         }
348         return;
349 }
350 EXPORT_SYMBOL(rtl_cam_del_entry);