1250003Sadrian/*
2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc.
3250003Sadrian *
4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any
5250003Sadrian * purpose with or without fee is hereby granted, provided that the above
6250003Sadrian * copyright notice and this permission notice appear in all copies.
7250003Sadrian *
8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14250003Sadrian * PERFORMANCE OF THIS SOFTWARE.
15250003Sadrian */
16250003Sadrian
17250003Sadrian#include "opt_ah.h"
18250003Sadrian
19250003Sadrian#include "ah.h"
20250003Sadrian#include "ah_internal.h"
21250003Sadrian
22250003Sadrian#include "ar9300/ar9300.h"
23250003Sadrian#include "ar9300/ar9300reg.h"
24250003Sadrian
25250003Sadrian/*
26250003Sadrian * Note: The key cache hardware requires that each double-word
27250003Sadrian * pair be written in even/odd order (since the destination is
28250003Sadrian * a 64-bit register).  Don't reorder the writes in this code
29250003Sadrian * w/o considering this!
30250003Sadrian */
31250003Sadrian#define KEY_XOR         0xaa
32250003Sadrian
33250003Sadrian#define IS_MIC_ENABLED(ah) \
34250003Sadrian    (AH9300(ah)->ah_sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
35250003Sadrian
36250003Sadrian/*
37250008Sadrian * This isn't the keytable type; this is actually something separate
38250008Sadrian * for the TX descriptor.
39250008Sadrian */
40250008Sadrianstatic const int keyType[] = {
41250008Sadrian	1,	/* HAL_CIPHER_WEP */
42250008Sadrian	0,	/* HAL_CIPHER_AES_OCB */
43250008Sadrian	2,	/* HAL_CIPHER_AES_CCM */
44250008Sadrian	0,	/* HAL_CIPHER_CKIP */
45250008Sadrian	3,	/* HAL_CIPHER_TKIP */
46250008Sadrian	0	/* HAL_CIPHER_CLR */
47250008Sadrian};
48250008Sadrian
49250008Sadrian/*
50250003Sadrian * Return the size of the hardware key cache.
51250003Sadrian */
52250003Sadrianu_int32_t
53250003Sadrianar9300_get_key_cache_size(struct ath_hal *ah)
54250003Sadrian{
55250008Sadrian    return AH_PRIVATE(ah)->ah_caps.halKeyCacheSize;
56250003Sadrian}
57250003Sadrian
58250003Sadrian/*
59250003Sadrian * Return AH_TRUE if the specific key cache entry is valid.
60250003Sadrian */
61250003SadrianHAL_BOOL
62250003Sadrianar9300_is_key_cache_entry_valid(struct ath_hal *ah, u_int16_t entry)
63250003Sadrian{
64250008Sadrian    if (entry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
65250003Sadrian        u_int32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
66250003Sadrian        if (val & AR_KEYTABLE_VALID) {
67250003Sadrian            return AH_TRUE;
68250003Sadrian        }
69250003Sadrian    }
70250003Sadrian    return AH_FALSE;
71250003Sadrian}
72250003Sadrian
73250003Sadrian/*
74250003Sadrian * Clear the specified key cache entry and any associated MIC entry.
75250003Sadrian */
76250003SadrianHAL_BOOL
77250003Sadrianar9300_reset_key_cache_entry(struct ath_hal *ah, u_int16_t entry)
78250003Sadrian{
79250003Sadrian    u_int32_t key_type;
80250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
81250003Sadrian
82250008Sadrian    if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
83250003Sadrian        HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
84250003Sadrian            "%s: entry %u out of range\n", __func__, entry);
85250003Sadrian        return AH_FALSE;
86250003Sadrian    }
87250008Sadrian
88250008Sadrian    ahp->ah_keytype[entry] = keyType[HAL_CIPHER_CLR];
89250008Sadrian
90250003Sadrian    key_type = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry));
91250003Sadrian
92250003Sadrian    /* XXX why not clear key type/valid bit first? */
93250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
94250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
95250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
96250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
97250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
98250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
99250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
100250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
101250003Sadrian    if (key_type == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
102250003Sadrian        u_int16_t micentry = entry + 64;  /* MIC goes at slot+64 */
103250003Sadrian
104250008Sadrian        HALASSERT(micentry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize);
105250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
106250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
107250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
108250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
109250003Sadrian        /* NB: key type and MAC are known to be ok */
110250003Sadrian    }
111250003Sadrian
112250003Sadrian    if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) {
113250003Sadrian        return AH_TRUE;
114250003Sadrian    }
115250003Sadrian
116250003Sadrian    if (ar9300_get_capability(ah, HAL_CAP_BB_RIFS_HANG, 0, AH_NULL)
117250003Sadrian        == HAL_OK) {
118250003Sadrian        if (key_type == AR_KEYTABLE_TYPE_TKIP    ||
119250003Sadrian            key_type == AR_KEYTABLE_TYPE_40      ||
120250003Sadrian            key_type == AR_KEYTABLE_TYPE_104     ||
121250003Sadrian            key_type == AR_KEYTABLE_TYPE_128) {
122250003Sadrian            /* SW WAR for Bug 31602 */
123250003Sadrian            if (--ahp->ah_rifs_sec_cnt == 0) {
124250003Sadrian                HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
125250003Sadrian                    "%s: Count = %d, enabling RIFS\n",
126250003Sadrian                    __func__, ahp->ah_rifs_sec_cnt);
127250003Sadrian                ar9300_set_rifs_delay(ah, AH_TRUE);
128250003Sadrian            }
129250003Sadrian        }
130250003Sadrian    }
131250003Sadrian    return AH_TRUE;
132250003Sadrian}
133250003Sadrian
134250003Sadrian/*
135250003Sadrian * Sets the mac part of the specified key cache entry (and any
136250003Sadrian * associated MIC entry) and mark them valid.
137250003Sadrian */
138250003SadrianHAL_BOOL
139250003Sadrianar9300_set_key_cache_entry_mac(
140250003Sadrian    struct ath_hal *ah,
141250003Sadrian    u_int16_t entry,
142250003Sadrian    const u_int8_t *mac)
143250003Sadrian{
144250003Sadrian    u_int32_t mac_hi, mac_lo;
145250003Sadrian    u_int32_t unicast_addr = AR_KEYTABLE_VALID;
146250003Sadrian
147250008Sadrian    if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
148250003Sadrian        HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
149250003Sadrian            "%s: entry %u out of range\n", __func__, entry);
150250003Sadrian        return AH_FALSE;
151250003Sadrian    }
152250003Sadrian    /*
153250003Sadrian     * Set MAC address -- shifted right by 1.  mac_lo is
154250003Sadrian     * the 4 MSBs, and mac_hi is the 2 LSBs.
155250003Sadrian     */
156250003Sadrian    if (mac != AH_NULL) {
157250003Sadrian        /*
158250003Sadrian         *  If upper layers have requested mcast MACaddr lookup, then
159250003Sadrian         *  signify this to the hw by setting the (poorly named) valid_bit
160250003Sadrian         *  to 0.  Yes, really 0. The hardware specs, pcu_registers.txt, is
161250003Sadrian         *  has incorrectly named valid_bit. It should be called "Unicast".
162250003Sadrian         *  When the Key Cache entry is to decrypt Unicast frames, this bit
163250003Sadrian         *  should be '1'; for multicast and broadcast frames, this bit is '0'.
164250003Sadrian         */
165250003Sadrian        if (mac[0] & 0x01) {
166250003Sadrian            unicast_addr = 0;    /* Not an unicast address */
167250003Sadrian        }
168250003Sadrian
169250003Sadrian        mac_hi = (mac[5] << 8)  |  mac[4];
170250003Sadrian        mac_lo = (mac[3] << 24) | (mac[2] << 16)
171250003Sadrian              | (mac[1] << 8)  |  mac[0];
172250003Sadrian        mac_lo >>= 1; /* Note that the bit 0 is shifted out. This bit is used to
173250003Sadrian                      * indicate that this is a multicast key cache. */
174250003Sadrian        mac_lo |= (mac_hi & 1) << 31; /* carry */
175250003Sadrian        mac_hi >>= 1;
176250003Sadrian    } else {
177250003Sadrian        mac_lo = mac_hi = 0;
178250003Sadrian    }
179250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), mac_lo);
180250003Sadrian    OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), mac_hi | unicast_addr);
181250003Sadrian    return AH_TRUE;
182250003Sadrian}
183250003Sadrian
184250003Sadrian/*
185250003Sadrian * Sets the contents of the specified key cache entry
186250003Sadrian * and any associated MIC entry.
187250003Sadrian */
188250003SadrianHAL_BOOL
189250003Sadrianar9300_set_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
190250003Sadrian                       const HAL_KEYVAL *k, const u_int8_t *mac,
191250003Sadrian                       int xor_key)
192250003Sadrian{
193250003Sadrian    const HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
194250003Sadrian    u_int32_t key0, key1, key2, key3, key4;
195250003Sadrian    u_int32_t key_type;
196250003Sadrian    u_int32_t xor_mask = xor_key ?
197250003Sadrian        (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
198250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
199250003Sadrian    u_int32_t pwrmgt, pwrmgt_mic, uapsd_cfg, psta = 0;
200250003Sadrian    int is_proxysta_key = k->kv_type & HAL_KEY_PROXY_STA_MASK;
201250003Sadrian
202250003Sadrian
203250008Sadrian    if (entry >= p_cap->halKeyCacheSize) {
204250003Sadrian        HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
205250003Sadrian            "%s: entry %u out of range\n", __func__, entry);
206250003Sadrian        return AH_FALSE;
207250003Sadrian    }
208250003Sadrian    HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s[%d] mac %s proxy %d\n",
209250003Sadrian        __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null",
210250003Sadrian        is_proxysta_key);
211250003Sadrian
212250003Sadrian    switch (k->kv_type & AH_KEYTYPE_MASK) {
213250003Sadrian    case HAL_CIPHER_AES_OCB:
214250003Sadrian        key_type = AR_KEYTABLE_TYPE_AES;
215250003Sadrian        break;
216250003Sadrian    case HAL_CIPHER_AES_CCM:
217250008Sadrian        if (!p_cap->halCipherAesCcmSupport) {
218250003Sadrian            HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: AES-CCM not supported by "
219250003Sadrian                "mac rev 0x%x\n",
220250003Sadrian                __func__, AH_PRIVATE(ah)->ah_macRev);
221250003Sadrian            return AH_FALSE;
222250003Sadrian        }
223250003Sadrian        key_type = AR_KEYTABLE_TYPE_CCM;
224250003Sadrian        break;
225250003Sadrian    case HAL_CIPHER_TKIP:
226250003Sadrian        key_type = AR_KEYTABLE_TYPE_TKIP;
227250008Sadrian        if (IS_MIC_ENABLED(ah) && entry + 64 >= p_cap->halKeyCacheSize) {
228250003Sadrian            HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
229250003Sadrian                "%s: entry %u inappropriate for TKIP\n",
230250003Sadrian                __func__, entry);
231250003Sadrian            return AH_FALSE;
232250003Sadrian        }
233250003Sadrian        break;
234250003Sadrian    case HAL_CIPHER_WEP:
235250003Sadrian        if (k->kv_len < 40 / NBBY) {
236250003Sadrian            HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: WEP key length %u too small\n",
237250003Sadrian                __func__, k->kv_len);
238250003Sadrian            return AH_FALSE;
239250003Sadrian        }
240250003Sadrian        if (k->kv_len <= 40 / NBBY) {
241250003Sadrian            key_type = AR_KEYTABLE_TYPE_40;
242250003Sadrian        } else if (k->kv_len <= 104 / NBBY) {
243250003Sadrian            key_type = AR_KEYTABLE_TYPE_104;
244250003Sadrian        } else {
245250003Sadrian            key_type = AR_KEYTABLE_TYPE_128;
246250003Sadrian        }
247250003Sadrian        break;
248250003Sadrian    case HAL_CIPHER_CLR:
249250003Sadrian        key_type = AR_KEYTABLE_TYPE_CLR;
250250003Sadrian        break;
251250003Sadrian    default:
252250003Sadrian        HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: cipher %u not supported\n",
253250003Sadrian            __func__, k->kv_type);
254250003Sadrian        return AH_FALSE;
255250003Sadrian    }
256250003Sadrian
257250003Sadrian    key0 =  LE_READ_4(k->kv_val +  0) ^ xor_mask;
258250003Sadrian    key1 = (LE_READ_2(k->kv_val +  4) ^ xor_mask) & 0xffff;
259250003Sadrian    key2 =  LE_READ_4(k->kv_val +  6) ^ xor_mask;
260250003Sadrian    key3 = (LE_READ_2(k->kv_val + 10) ^ xor_mask) & 0xffff;
261250003Sadrian    key4 =  LE_READ_4(k->kv_val + 12) ^ xor_mask;
262250003Sadrian    if (k->kv_len <= 104 / NBBY) {
263250003Sadrian        key4 &= 0xff;
264250003Sadrian    }
265250003Sadrian
266250003Sadrian    /* Extract the UAPSD AC bits and shift it appropriately */
267250003Sadrian    uapsd_cfg = k->kv_apsd;
268250003Sadrian    uapsd_cfg = (u_int32_t) SM(uapsd_cfg, AR_KEYTABLE_UAPSD);
269250003Sadrian
270250003Sadrian    /* Need to preserve the power management bit used by MAC */
271250003Sadrian    pwrmgt = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEYTABLE_PWRMGT;
272250003Sadrian
273250003Sadrian    if (is_proxysta_key) {
274250003Sadrian        u_int8_t bcast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
275250008Sadrian        if (!mac || OS_MEMCMP(mac, bcast_mac, 6)) {
276250003Sadrian            psta = AR_KEYTABLE_DIR_ACK_BIT;
277250003Sadrian        }
278250003Sadrian    }
279250003Sadrian    /*
280250003Sadrian     * Note: key cache hardware requires that each double-word
281250003Sadrian     * pair be written in even/odd order (since the destination is
282250003Sadrian     * a 64-bit register).  Don't reorder these writes w/o
283250003Sadrian     * considering this!
284250003Sadrian     */
285250003Sadrian    if (key_type == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
286250003Sadrian        u_int16_t micentry = entry + 64;  /* MIC goes at slot+64 */
287250003Sadrian
288250003Sadrian        /* Need to preserve the power management bit used by MAC */
289250003Sadrian        pwrmgt_mic =
290250003Sadrian            OS_REG_READ(ah, AR_KEYTABLE_TYPE(micentry)) & AR_KEYTABLE_PWRMGT;
291250003Sadrian
292250003Sadrian        /*
293250003Sadrian         * Invalidate the encrypt/decrypt key until the MIC
294250003Sadrian         * key is installed so pending rx frames will fail
295250003Sadrian         * with decrypt errors rather than a MIC error.
296250003Sadrian         */
297250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
298250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
299250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
300250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
301250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
302250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry),
303250003Sadrian            key_type | pwrmgt | uapsd_cfg | psta);
304250003Sadrian        ar9300_set_key_cache_entry_mac(ah, entry, mac);
305250003Sadrian
306250003Sadrian        /*
307250003Sadrian         * since the AR_MISC_MODE register was written with the contents of
308250003Sadrian         * ah_misc_mode (if any) in ar9300_attach, just check ah_misc_mode and
309250003Sadrian         * save a pci read per key set.
310250003Sadrian         */
311250003Sadrian        if (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
312250003Sadrian            u_int32_t mic0, mic1, mic2, mic3, mic4;
313250003Sadrian            /*
314250003Sadrian             * both RX and TX mic values can be combined into
315250003Sadrian             * one cache slot entry.
316250003Sadrian             * 8*N + 800         31:0    RX Michael key 0
317250003Sadrian             * 8*N + 804         15:0    TX Michael key 0 [31:16]
318250003Sadrian             * 8*N + 808         31:0    RX Michael key 1
319250003Sadrian             * 8*N + 80C         15:0    TX Michael key 0 [15:0]
320250003Sadrian             * 8*N + 810         31:0    TX Michael key 1
321250003Sadrian             * 8*N + 814         15:0    reserved
322250003Sadrian             * 8*N + 818         31:0    reserved
323250003Sadrian             * 8*N + 81C         14:0    reserved
324250003Sadrian             *                   15      key valid == 0
325250003Sadrian             */
326250003Sadrian            /* RX mic */
327250003Sadrian            mic0 = LE_READ_4(k->kv_mic + 0);
328250003Sadrian            mic2 = LE_READ_4(k->kv_mic + 4);
329250003Sadrian            /* TX mic */
330250003Sadrian            mic1 = LE_READ_2(k->kv_txmic + 2) & 0xffff;
331250003Sadrian            mic3 = LE_READ_2(k->kv_txmic + 0) & 0xffff;
332250003Sadrian            mic4 = LE_READ_4(k->kv_txmic + 4);
333250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
334250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
335250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
336250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
337250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
338250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
339250003Sadrian                         AR_KEYTABLE_TYPE_CLR | pwrmgt_mic | uapsd_cfg);
340250003Sadrian
341250003Sadrian        } else {
342250003Sadrian            u_int32_t mic0, mic2;
343250003Sadrian
344250003Sadrian            mic0 = LE_READ_4(k->kv_mic + 0);
345250003Sadrian            mic2 = LE_READ_4(k->kv_mic + 4);
346250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
347250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
348250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
349250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
350250003Sadrian            OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
351250003Sadrian            OS_REG_WRITE(ah,
352250003Sadrian                AR_KEYTABLE_TYPE(micentry | pwrmgt_mic | uapsd_cfg),
353250003Sadrian                AR_KEYTABLE_TYPE_CLR);
354250003Sadrian        }
355250003Sadrian        /* NB: MIC key is not marked valid and has no MAC address */
356250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
357250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
358250003Sadrian
359250003Sadrian        /* correct intentionally corrupted key */
360250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
361250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
362250003Sadrian    } else {
363250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
364250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
365250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
366250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
367250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
368250003Sadrian        OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry),
369250003Sadrian            key_type | pwrmgt | uapsd_cfg | psta);
370250003Sadrian
371250003Sadrian        /*
372250003Sadrian        ath_hal_printf(ah, "%s[%d] mac %s proxy %d\n",
373250003Sadrian            __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null",
374250003Sadrian            is_proxysta_key);
375250003Sadrian         */
376250003Sadrian
377250003Sadrian        ar9300_set_key_cache_entry_mac(ah, entry, mac);
378250003Sadrian    }
379250003Sadrian
380250008Sadrian    ahp->ah_keytype[entry] = keyType[k->kv_type];
381250008Sadrian    HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: entry=%d, k->kv_type=%d,"
382250008Sadrian      "keyType=%d\n", __func__, entry, k->kv_type, keyType[k->kv_type]);
383250008Sadrian
384250008Sadrian
385250003Sadrian    if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) {
386250003Sadrian        return AH_TRUE;
387250003Sadrian    }
388250003Sadrian
389250003Sadrian    if (ar9300_get_capability(ah, HAL_CAP_BB_RIFS_HANG, 0, AH_NULL)
390250003Sadrian        == HAL_OK) {
391250003Sadrian        if (key_type == AR_KEYTABLE_TYPE_TKIP    ||
392250003Sadrian            key_type == AR_KEYTABLE_TYPE_40      ||
393250003Sadrian            key_type == AR_KEYTABLE_TYPE_104     ||
394250003Sadrian            key_type == AR_KEYTABLE_TYPE_128) {
395250003Sadrian            /* SW WAR for Bug 31602 */
396250003Sadrian            ahp->ah_rifs_sec_cnt++;
397250003Sadrian            HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
398250003Sadrian                "%s: Count = %d, disabling RIFS\n",
399250003Sadrian                __func__, ahp->ah_rifs_sec_cnt);
400250003Sadrian            ar9300_set_rifs_delay(ah, AH_FALSE);
401250003Sadrian        }
402250003Sadrian    }
403250003Sadrian    HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s[%d] mac %s proxy %d\n",
404250003Sadrian        __func__, __LINE__, mac ? ath_hal_ether_sprintf(mac) : "null",
405250003Sadrian        is_proxysta_key);
406250003Sadrian
407250003Sadrian    return AH_TRUE;
408250003Sadrian}
409250003Sadrian
410250003Sadrian/*
411250003Sadrian * Enable the Keysearch for every subframe of an aggregate
412250003Sadrian */
413250003Sadrianvoid
414250003Sadrianar9300_enable_keysearch_always(struct ath_hal *ah, int enable)
415250003Sadrian{
416250003Sadrian    u_int32_t val;
417250003Sadrian
418250003Sadrian    if (!ah) {
419250003Sadrian        return;
420250003Sadrian    }
421250003Sadrian    val = OS_REG_READ(ah, AR_PCU_MISC);
422250003Sadrian    if (enable) {
423250003Sadrian        val |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
424250003Sadrian    } else {
425250003Sadrian        val &= ~AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
426250003Sadrian    }
427250003Sadrian    OS_REG_WRITE(ah, AR_PCU_MISC, val);
428250003Sadrian}
429250003Sadrianvoid ar9300_dump_keycache(struct ath_hal *ah, int n, u_int32_t *entry)
430250003Sadrian{
431250003Sadrian#define AH_KEY_REG_SIZE	8
432250003Sadrian    int i;
433250003Sadrian
434250003Sadrian    for (i = 0; i < AH_KEY_REG_SIZE; i++) {
435250003Sadrian        entry[i] = OS_REG_READ(ah, AR_KEYTABLE_KEY0(n) + i * 4);
436250003Sadrian    }
437250003Sadrian#undef AH_KEY_REG_SIZE
438250003Sadrian}
439278741Sadrian
440278741Sadrian#if ATH_SUPPORT_KEYPLUMB_WAR
441278741Sadrian/*
442278741Sadrian * Check the contents of the specified key cache entry
443278741Sadrian * and any associated MIC entry.
444278741Sadrian */
445278741Sadrian    HAL_BOOL
446278741Sadrianar9300_check_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
447278741Sadrian        const HAL_KEYVAL *k, int xorKey)
448278741Sadrian{
449278741Sadrian    const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
450278741Sadrian    u_int32_t key0, key1, key2, key3, key4;
451278741Sadrian    u_int32_t keyType;
452278741Sadrian    u_int32_t xorMask = xorKey ?
453278741Sadrian        (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
454278741Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
455278741Sadrian
456278741Sadrian
457278741Sadrian    if (entry >= pCap->hal_key_cache_size) {
458278741Sadrian        HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
459278741Sadrian                "%s: entry %u out of range\n", __func__, entry);
460278741Sadrian        return AH_FALSE;
461278741Sadrian    }
462278741Sadrian    switch (k->kv_type) {
463278741Sadrian        case HAL_CIPHER_AES_OCB:
464278741Sadrian            keyType = AR_KEYTABLE_TYPE_AES;
465278741Sadrian            break;
466278741Sadrian        case HAL_CIPHER_AES_CCM:
467278741Sadrian            if (!pCap->hal_cipher_aes_ccm_support) {
468278741Sadrian                HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: AES-CCM not supported by "
469278741Sadrian                        "mac rev 0x%x\n",
470278741Sadrian                        __func__, AH_PRIVATE(ah)->ah_macRev);
471278741Sadrian                return AH_FALSE;
472278741Sadrian            }
473278741Sadrian            keyType = AR_KEYTABLE_TYPE_CCM;
474278741Sadrian            break;
475278741Sadrian        case HAL_CIPHER_TKIP:
476278741Sadrian            keyType = AR_KEYTABLE_TYPE_TKIP;
477278741Sadrian            if (IS_MIC_ENABLED(ah) && entry + 64 >= pCap->hal_key_cache_size) {
478278741Sadrian                HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
479278741Sadrian                        "%s: entry %u inappropriate for TKIP\n",
480278741Sadrian                        __func__, entry);
481278741Sadrian                return AH_FALSE;
482278741Sadrian            }
483278741Sadrian            break;
484278741Sadrian        case HAL_CIPHER_WEP:
485278741Sadrian            if (k->kv_len < 40 / NBBY) {
486278741Sadrian                HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: WEP key length %u too small\n",
487278741Sadrian                        __func__, k->kv_len);
488278741Sadrian                return AH_FALSE;
489278741Sadrian            }
490278741Sadrian            if (k->kv_len <= 40 / NBBY) {
491278741Sadrian                keyType = AR_KEYTABLE_TYPE_40;
492278741Sadrian            } else if (k->kv_len <= 104 / NBBY) {
493278741Sadrian                keyType = AR_KEYTABLE_TYPE_104;
494278741Sadrian            } else {
495278741Sadrian                keyType = AR_KEYTABLE_TYPE_128;
496278741Sadrian            }
497278741Sadrian            break;
498278741Sadrian        case HAL_CIPHER_CLR:
499278741Sadrian            keyType = AR_KEYTABLE_TYPE_CLR;
500278741Sadrian            return AH_TRUE;
501278741Sadrian        default:
502278741Sadrian            HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: cipher %u not supported\n",
503278741Sadrian                    __func__, k->kv_type);
504278741Sadrian            return AH_TRUE;
505278741Sadrian    }
506278741Sadrian
507278741Sadrian    key0 =  LE_READ_4(k->kv_val +  0) ^ xorMask;
508278741Sadrian    key1 = (LE_READ_2(k->kv_val +  4) ^ xorMask) & 0xffff;
509278741Sadrian    key2 =  LE_READ_4(k->kv_val +  6) ^ xorMask;
510278741Sadrian    key3 = (LE_READ_2(k->kv_val + 10) ^ xorMask) & 0xffff;
511278741Sadrian    key4 =  LE_READ_4(k->kv_val + 12) ^ xorMask;
512278741Sadrian    if (k->kv_len <= 104 / NBBY) {
513278741Sadrian        key4 &= 0xff;
514278741Sadrian    }
515278741Sadrian
516278741Sadrian    /*
517278741Sadrian     * Note: key cache hardware requires that each double-word
518278741Sadrian     * pair be written in even/odd order (since the destination is
519278741Sadrian     * a 64-bit register).  Don't reorder these writes w/o
520278741Sadrian     * considering this!
521278741Sadrian     */
522278741Sadrian    if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
523278741Sadrian        u_int16_t micentry = entry + 64;  /* MIC goes at slot+64 */
524278741Sadrian
525278741Sadrian
526278741Sadrian        /*
527278741Sadrian         * Invalidate the encrypt/decrypt key until the MIC
528278741Sadrian         * key is installed so pending rx frames will fail
529278741Sadrian         * with decrypt errors rather than a MIC error.
530278741Sadrian         */
531278741Sadrian        if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) &&
532278741Sadrian                (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) &&
533278741Sadrian                (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) &&
534278741Sadrian                (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) &&
535278741Sadrian                (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) &&
536278741Sadrian                ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE)))
537278741Sadrian        {
538278741Sadrian
539278741Sadrian            /*
540278741Sadrian             * since the AR_MISC_MODE register was written with the contents of
541278741Sadrian             * ah_miscMode (if any) in ar9300Attach, just check ah_miscMode and
542278741Sadrian             * save a pci read per key set.
543278741Sadrian             */
544278741Sadrian            if (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
545278741Sadrian                u_int32_t mic0,mic1,mic2,mic3,mic4;
546278741Sadrian                /*
547278741Sadrian                 * both RX and TX mic values can be combined into
548278741Sadrian                 * one cache slot entry.
549278741Sadrian                 * 8*N + 800         31:0    RX Michael key 0
550278741Sadrian                 * 8*N + 804         15:0    TX Michael key 0 [31:16]
551278741Sadrian                 * 8*N + 808         31:0    RX Michael key 1
552278741Sadrian                 * 8*N + 80C         15:0    TX Michael key 0 [15:0]
553278741Sadrian                 * 8*N + 810         31:0    TX Michael key 1
554278741Sadrian                 * 8*N + 814         15:0    reserved
555278741Sadrian                 * 8*N + 818         31:0    reserved
556278741Sadrian                 * 8*N + 81C         14:0    reserved
557278741Sadrian                 *                   15      key valid == 0
558278741Sadrian                 */
559278741Sadrian                /* RX mic */
560278741Sadrian                mic0 = LE_READ_4(k->kv_mic + 0);
561278741Sadrian                mic2 = LE_READ_4(k->kv_mic + 4);
562278741Sadrian                /* TX mic */
563278741Sadrian                mic1 = LE_READ_2(k->kv_txmic + 2) & 0xffff;
564278741Sadrian                mic3 = LE_READ_2(k->kv_txmic + 0) & 0xffff;
565278741Sadrian                mic4 = LE_READ_4(k->kv_txmic + 4);
566278741Sadrian                if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(micentry)) == mic0) &&
567278741Sadrian                        (OS_REG_READ(ah, AR_KEYTABLE_KEY1(micentry)) == mic1) &&
568278741Sadrian                        (OS_REG_READ(ah, AR_KEYTABLE_KEY2(micentry)) == mic2) &&
569278741Sadrian                        (OS_REG_READ(ah, AR_KEYTABLE_KEY3(micentry)) == mic3) &&
570278741Sadrian                        (OS_REG_READ(ah, AR_KEYTABLE_KEY4(micentry)) == mic4) &&
571278741Sadrian                        ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(micentry)) & AR_KEY_TYPE) == (AR_KEYTABLE_TYPE_CLR & AR_KEY_TYPE))) {
572278741Sadrian                    return AH_TRUE;
573278741Sadrian                }
574278741Sadrian
575278741Sadrian            } else {
576278741Sadrian                return AH_TRUE;
577278741Sadrian            }
578278741Sadrian        }
579278741Sadrian    } else {
580278741Sadrian        if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) &&
581278741Sadrian                (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) &&
582278741Sadrian                (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) &&
583278741Sadrian                (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) &&
584278741Sadrian                (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) &&
585278741Sadrian                ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE))) {
586278741Sadrian            return AH_TRUE;
587278741Sadrian        }
588278741Sadrian    }
589278741Sadrian    return AH_FALSE;
590278741Sadrian}
591278741Sadrian#endif
592