Commit | Line | Data |
---|---|---|
572ff6f6 MD |
1 | /*- |
2 | * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer, | |
10 | * without modification. | |
11 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |
12 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | |
13 | * redistribution must be conditioned upon including a substantially | |
14 | * similar Disclaimer requirement for further binary redistribution. | |
15 | * | |
16 | * NO WARRANTY | |
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
df052c2a | 19 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTABILITY |
572ff6f6 MD |
20 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
21 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | |
22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | |
25 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
27 | * THE POSSIBILITY OF SUCH DAMAGES. | |
28 | */ | |
29 | ||
30 | #include <sys/cdefs.h> | |
848b370c | 31 | __FBSDID("$FreeBSD$"); |
572ff6f6 MD |
32 | |
33 | /* | |
34 | * Driver for the Atheros Wireless LAN controller. | |
35 | * | |
36 | * This software is derived from work of Atsushi Onoe; his contribution | |
37 | * is greatly appreciated. | |
38 | */ | |
39 | ||
40 | #include "opt_inet.h" | |
41 | #include "opt_ath.h" | |
42 | #include "opt_wlan.h" | |
43 | ||
44 | #include <sys/param.h> | |
45 | #include <sys/systm.h> | |
46 | #include <sys/sysctl.h> | |
47 | #include <sys/mbuf.h> | |
48 | #include <sys/malloc.h> | |
49 | #include <sys/lock.h> | |
572ff6f6 MD |
50 | #include <sys/kernel.h> |
51 | #include <sys/socket.h> | |
52 | #include <sys/sockio.h> | |
53 | #include <sys/errno.h> | |
54 | #include <sys/callout.h> | |
55 | #include <sys/bus.h> | |
56 | #include <sys/endian.h> | |
57 | #include <sys/kthread.h> | |
58 | #include <sys/taskqueue.h> | |
2b3f93ea | 59 | #include <sys/caps.h> |
572ff6f6 | 60 | |
dc249793 MD |
61 | #if defined(__DragonFly__) |
62 | /* empty */ | |
63 | #else | |
b14ca477 | 64 | #include <machine/bus.h> |
dc249793 | 65 | #endif |
b14ca477 | 66 | |
572ff6f6 MD |
67 | #include <net/if.h> |
68 | #include <net/if_var.h> | |
69 | #include <net/if_dl.h> | |
70 | #include <net/if_media.h> | |
71 | #include <net/if_types.h> | |
72 | #include <net/if_arp.h> | |
73 | #include <net/ethernet.h> | |
74 | #include <net/if_llc.h> | |
75 | ||
dc249793 | 76 | #include <netproto/802_11/ieee80211_var.h> |
572ff6f6 MD |
77 | |
78 | #include <net/bpf.h> | |
79 | ||
dc249793 | 80 | #include <dev/netif/ath/ath/if_athvar.h> |
572ff6f6 | 81 | |
dc249793 MD |
82 | #include <dev/netif/ath/ath/if_ath_debug.h> |
83 | #include <dev/netif/ath/ath/if_ath_keycache.h> | |
84 | #include <dev/netif/ath/ath/if_ath_misc.h> | |
572ff6f6 MD |
85 | |
86 | #ifdef ATH_DEBUG | |
87 | static void | |
88 | ath_keyprint(struct ath_softc *sc, const char *tag, u_int ix, | |
89 | const HAL_KEYVAL *hk, const u_int8_t mac[IEEE80211_ADDR_LEN]) | |
90 | { | |
91 | static const char *ciphers[] = { | |
92 | "WEP", | |
93 | "AES-OCB", | |
94 | "AES-CCM", | |
95 | "CKIP", | |
96 | "TKIP", | |
97 | "CLR", | |
98 | }; | |
99 | int i, n; | |
100 | ||
dc249793 | 101 | kprintf("%s: [%02u] %-7s ", tag, ix, ciphers[hk->kv_type]); |
572ff6f6 | 102 | for (i = 0, n = hk->kv_len; i < n; i++) |
dc249793 MD |
103 | kprintf("%02x", hk->kv_val[i]); |
104 | kprintf(" mac %s", ether_sprintf(mac)); | |
572ff6f6 | 105 | if (hk->kv_type == HAL_CIPHER_TKIP) { |
dc249793 | 106 | kprintf(" %s ", sc->sc_splitmic ? "mic" : "rxmic"); |
572ff6f6 | 107 | for (i = 0; i < sizeof(hk->kv_mic); i++) |
dc249793 | 108 | kprintf("%02x", hk->kv_mic[i]); |
572ff6f6 | 109 | if (!sc->sc_splitmic) { |
dc249793 | 110 | kprintf(" txmic "); |
572ff6f6 | 111 | for (i = 0; i < sizeof(hk->kv_txmic); i++) |
dc249793 | 112 | kprintf("%02x", hk->kv_txmic[i]); |
572ff6f6 MD |
113 | } |
114 | } | |
dc249793 | 115 | kprintf("\n"); |
572ff6f6 MD |
116 | } |
117 | #endif | |
118 | ||
119 | /* | |
120 | * Set a TKIP key into the hardware. This handles the | |
121 | * potential distribution of key state to multiple key | |
122 | * cache slots for TKIP. | |
123 | */ | |
124 | static int | |
125 | ath_keyset_tkip(struct ath_softc *sc, const struct ieee80211_key *k, | |
126 | HAL_KEYVAL *hk, const u_int8_t mac[IEEE80211_ADDR_LEN]) | |
127 | { | |
128 | #define IEEE80211_KEY_XR (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV) | |
129 | static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; | |
130 | struct ath_hal *ah = sc->sc_ah; | |
131 | ||
132 | KASSERT(k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP, | |
133 | ("got a non-TKIP key, cipher %u", k->wk_cipher->ic_cipher)); | |
134 | if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) { | |
135 | if (sc->sc_splitmic) { | |
136 | /* | |
137 | * TX key goes at first index, RX key at the rx index. | |
138 | * The hal handles the MIC keys at index+64. | |
139 | */ | |
140 | memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_mic)); | |
141 | KEYPRINTF(sc, k->wk_keyix, hk, zerobssid); | |
142 | if (!ath_hal_keyset(ah, k->wk_keyix, hk, zerobssid)) | |
143 | return 0; | |
144 | ||
145 | memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); | |
146 | KEYPRINTF(sc, k->wk_keyix+32, hk, mac); | |
147 | /* XXX delete tx key on failure? */ | |
148 | return ath_hal_keyset(ah, k->wk_keyix+32, hk, mac); | |
149 | } else { | |
150 | /* | |
151 | * Room for both TX+RX MIC keys in one key cache | |
152 | * slot, just set key at the first index; the hal | |
153 | * will handle the rest. | |
154 | */ | |
155 | memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); | |
156 | memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic)); | |
157 | KEYPRINTF(sc, k->wk_keyix, hk, mac); | |
158 | return ath_hal_keyset(ah, k->wk_keyix, hk, mac); | |
159 | } | |
160 | } else if (k->wk_flags & IEEE80211_KEY_XMIT) { | |
161 | if (sc->sc_splitmic) { | |
162 | /* | |
163 | * NB: must pass MIC key in expected location when | |
164 | * the keycache only holds one MIC key per entry. | |
165 | */ | |
166 | memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_txmic)); | |
167 | } else | |
168 | memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic)); | |
169 | KEYPRINTF(sc, k->wk_keyix, hk, mac); | |
170 | return ath_hal_keyset(ah, k->wk_keyix, hk, mac); | |
171 | } else if (k->wk_flags & IEEE80211_KEY_RECV) { | |
172 | memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); | |
173 | KEYPRINTF(sc, k->wk_keyix, hk, mac); | |
174 | return ath_hal_keyset(ah, k->wk_keyix, hk, mac); | |
175 | } | |
176 | return 0; | |
177 | #undef IEEE80211_KEY_XR | |
178 | } | |
179 | ||
180 | /* | |
181 | * Set a net80211 key into the hardware. This handles the | |
182 | * potential distribution of key state to multiple key | |
183 | * cache slots for TKIP with hardware MIC support. | |
184 | */ | |
185 | int | |
186 | ath_keyset(struct ath_softc *sc, struct ieee80211vap *vap, | |
187 | const struct ieee80211_key *k, | |
188 | struct ieee80211_node *bss) | |
189 | { | |
572ff6f6 MD |
190 | static const u_int8_t ciphermap[] = { |
191 | HAL_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */ | |
192 | HAL_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */ | |
193 | HAL_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */ | |
194 | HAL_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */ | |
195 | (u_int8_t) -1, /* 4 is not allocated */ | |
196 | HAL_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */ | |
197 | HAL_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */ | |
198 | }; | |
199 | struct ath_hal *ah = sc->sc_ah; | |
200 | const struct ieee80211_cipher *cip = k->wk_cipher; | |
201 | u_int8_t gmac[IEEE80211_ADDR_LEN]; | |
202 | const u_int8_t *mac; | |
203 | HAL_KEYVAL hk; | |
d98a0bcf | 204 | int ret; |
572ff6f6 MD |
205 | |
206 | memset(&hk, 0, sizeof(hk)); | |
207 | /* | |
208 | * Software crypto uses a "clear key" so non-crypto | |
209 | * state kept in the key cache are maintained and | |
210 | * so that rx frames have an entry to match. | |
211 | */ | |
212 | if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { | |
b14ca477 | 213 | KASSERT(cip->ic_cipher < nitems(ciphermap), |
572ff6f6 MD |
214 | ("invalid cipher type %u", cip->ic_cipher)); |
215 | hk.kv_type = ciphermap[cip->ic_cipher]; | |
216 | hk.kv_len = k->wk_keylen; | |
217 | memcpy(hk.kv_val, k->wk_key, k->wk_keylen); | |
218 | } else | |
219 | hk.kv_type = HAL_CIPHER_CLR; | |
220 | ||
221 | /* | |
222 | * If we're installing a clear cipher key and | |
223 | * the hardware doesn't support that, just succeed. | |
224 | * Leave it up to the net80211 layer to figure it out. | |
225 | */ | |
226 | if (hk.kv_type == HAL_CIPHER_CLR && sc->sc_hasclrkey == 0) { | |
227 | return (1); | |
228 | } | |
229 | ||
230 | /* | |
231 | * XXX TODO: check this: | |
232 | * | |
233 | * Group keys on hardware that supports multicast frame | |
234 | * key search should only be done in adhoc/hostap mode, | |
235 | * not STA mode. | |
236 | * | |
237 | * XXX TODO: what about mesh, tdma? | |
238 | */ | |
239 | #if 0 | |
240 | if ((vap->iv_opmode == IEEE80211_M_HOSTAP || | |
241 | vap->iv_opmode == IEEE80211_M_IBSS) && | |
242 | #else | |
243 | if ( | |
244 | #endif | |
245 | (k->wk_flags & IEEE80211_KEY_GROUP) && | |
246 | sc->sc_mcastkey) { | |
247 | /* | |
248 | * Group keys on hardware that supports multicast frame | |
249 | * key search use a MAC that is the sender's address with | |
250 | * the multicast bit set instead of the app-specified address. | |
251 | */ | |
252 | IEEE80211_ADDR_COPY(gmac, bss->ni_macaddr); | |
253 | gmac[0] |= 0x01; | |
254 | mac = gmac; | |
255 | } else | |
256 | mac = k->wk_macaddr; | |
257 | ||
848b370c | 258 | ATH_LOCK(sc); |
d98a0bcf | 259 | ath_power_set_power_state(sc, HAL_PM_AWAKE); |
572ff6f6 MD |
260 | if (hk.kv_type == HAL_CIPHER_TKIP && |
261 | (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { | |
d98a0bcf | 262 | ret = ath_keyset_tkip(sc, k, &hk, mac); |
572ff6f6 MD |
263 | } else { |
264 | KEYPRINTF(sc, k->wk_keyix, &hk, mac); | |
d98a0bcf | 265 | ret = ath_hal_keyset(ah, k->wk_keyix, &hk, mac); |
572ff6f6 | 266 | } |
d98a0bcf | 267 | ath_power_restore_power_state(sc); |
848b370c | 268 | ATH_UNLOCK(sc); |
d98a0bcf MD |
269 | |
270 | return (ret); | |
572ff6f6 MD |
271 | } |
272 | ||
273 | /* | |
274 | * Allocate tx/rx key slots for TKIP. We allocate two slots for | |
275 | * each key, one for decrypt/encrypt and the other for the MIC. | |
276 | */ | |
277 | static u_int16_t | |
278 | key_alloc_2pair(struct ath_softc *sc, | |
279 | ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) | |
280 | { | |
572ff6f6 MD |
281 | u_int i, keyix; |
282 | ||
283 | KASSERT(sc->sc_splitmic, ("key cache !split")); | |
284 | /* XXX could optimize */ | |
b14ca477 | 285 | for (i = 0; i < nitems(sc->sc_keymap)/4; i++) { |
572ff6f6 MD |
286 | u_int8_t b = sc->sc_keymap[i]; |
287 | if (b != 0xff) { | |
288 | /* | |
289 | * One or more slots in this byte are free. | |
290 | */ | |
291 | keyix = i*NBBY; | |
292 | while (b & 1) { | |
293 | again: | |
294 | keyix++; | |
295 | b >>= 1; | |
296 | } | |
297 | /* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */ | |
298 | if (isset(sc->sc_keymap, keyix+32) || | |
299 | isset(sc->sc_keymap, keyix+64) || | |
300 | isset(sc->sc_keymap, keyix+32+64)) { | |
301 | /* full pair unavailable */ | |
302 | /* XXX statistic */ | |
303 | if (keyix == (i+1)*NBBY) { | |
304 | /* no slots were appropriate, advance */ | |
305 | continue; | |
306 | } | |
307 | goto again; | |
308 | } | |
309 | setbit(sc->sc_keymap, keyix); | |
310 | setbit(sc->sc_keymap, keyix+64); | |
311 | setbit(sc->sc_keymap, keyix+32); | |
312 | setbit(sc->sc_keymap, keyix+32+64); | |
313 | DPRINTF(sc, ATH_DEBUG_KEYCACHE, | |
314 | "%s: key pair %u,%u %u,%u\n", | |
315 | __func__, keyix, keyix+64, | |
316 | keyix+32, keyix+32+64); | |
317 | *txkeyix = keyix; | |
318 | *rxkeyix = keyix+32; | |
319 | return 1; | |
320 | } | |
321 | } | |
322 | DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__); | |
323 | return 0; | |
572ff6f6 MD |
324 | } |
325 | ||
326 | /* | |
327 | * Allocate tx/rx key slots for TKIP. We allocate two slots for | |
328 | * each key, one for decrypt/encrypt and the other for the MIC. | |
329 | */ | |
330 | static u_int16_t | |
331 | key_alloc_pair(struct ath_softc *sc, | |
332 | ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) | |
333 | { | |
572ff6f6 MD |
334 | u_int i, keyix; |
335 | ||
336 | KASSERT(!sc->sc_splitmic, ("key cache split")); | |
337 | /* XXX could optimize */ | |
b14ca477 | 338 | for (i = 0; i < nitems(sc->sc_keymap)/4; i++) { |
572ff6f6 MD |
339 | u_int8_t b = sc->sc_keymap[i]; |
340 | if (b != 0xff) { | |
341 | /* | |
342 | * One or more slots in this byte are free. | |
343 | */ | |
344 | keyix = i*NBBY; | |
345 | while (b & 1) { | |
346 | again: | |
347 | keyix++; | |
348 | b >>= 1; | |
349 | } | |
350 | if (isset(sc->sc_keymap, keyix+64)) { | |
351 | /* full pair unavailable */ | |
352 | /* XXX statistic */ | |
353 | if (keyix == (i+1)*NBBY) { | |
354 | /* no slots were appropriate, advance */ | |
355 | continue; | |
356 | } | |
357 | goto again; | |
358 | } | |
359 | setbit(sc->sc_keymap, keyix); | |
360 | setbit(sc->sc_keymap, keyix+64); | |
361 | DPRINTF(sc, ATH_DEBUG_KEYCACHE, | |
362 | "%s: key pair %u,%u\n", | |
363 | __func__, keyix, keyix+64); | |
364 | *txkeyix = *rxkeyix = keyix; | |
365 | return 1; | |
366 | } | |
367 | } | |
368 | DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__); | |
369 | return 0; | |
572ff6f6 MD |
370 | } |
371 | ||
372 | /* | |
373 | * Allocate a single key cache slot. | |
374 | */ | |
375 | static int | |
376 | key_alloc_single(struct ath_softc *sc, | |
377 | ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) | |
378 | { | |
572ff6f6 MD |
379 | u_int i, keyix; |
380 | ||
381 | if (sc->sc_hasclrkey == 0) { | |
382 | /* | |
383 | * Map to slot 0 for the AR5210. | |
384 | */ | |
385 | *txkeyix = *rxkeyix = 0; | |
386 | return (1); | |
387 | } | |
388 | ||
389 | /* XXX try i,i+32,i+64,i+32+64 to minimize key pair conflicts */ | |
b14ca477 | 390 | for (i = 0; i < nitems(sc->sc_keymap); i++) { |
572ff6f6 MD |
391 | u_int8_t b = sc->sc_keymap[i]; |
392 | if (b != 0xff) { | |
393 | /* | |
394 | * One or more slots are free. | |
395 | */ | |
396 | keyix = i*NBBY; | |
397 | while (b & 1) | |
398 | keyix++, b >>= 1; | |
399 | setbit(sc->sc_keymap, keyix); | |
400 | DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: key %u\n", | |
401 | __func__, keyix); | |
402 | *txkeyix = *rxkeyix = keyix; | |
403 | return 1; | |
404 | } | |
405 | } | |
406 | DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of space\n", __func__); | |
407 | return 0; | |
572ff6f6 MD |
408 | } |
409 | ||
410 | /* | |
411 | * Allocate one or more key cache slots for a uniacst key. The | |
412 | * key itself is needed only to identify the cipher. For hardware | |
413 | * TKIP with split cipher+MIC keys we allocate two key cache slot | |
414 | * pairs so that we can setup separate TX and RX MIC keys. Note | |
415 | * that the MIC key for a TKIP key at slot i is assumed by the | |
416 | * hardware to be at slot i+64. This limits TKIP keys to the first | |
417 | * 64 entries. | |
418 | */ | |
419 | int | |
420 | ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, | |
421 | ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) | |
422 | { | |
4f1aaf2f | 423 | struct ath_softc *sc = vap->iv_ic->ic_softc; |
572ff6f6 MD |
424 | |
425 | /* | |
426 | * Group key allocation must be handled specially for | |
427 | * parts that do not support multicast key cache search | |
428 | * functionality. For those parts the key id must match | |
429 | * the h/w key index so lookups find the right key. On | |
430 | * parts w/ the key search facility we install the sender's | |
431 | * mac address (with the high bit set) and let the hardware | |
432 | * find the key w/o using the key id. This is preferred as | |
433 | * it permits us to support multiple users for adhoc and/or | |
434 | * multi-station operation. | |
435 | */ | |
436 | if (k->wk_keyix != IEEE80211_KEYIX_NONE) { | |
437 | /* | |
438 | * Only global keys should have key index assigned. | |
439 | */ | |
440 | if (!(&vap->iv_nw_keys[0] <= k && | |
441 | k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) { | |
442 | /* should not happen */ | |
443 | DPRINTF(sc, ATH_DEBUG_KEYCACHE, | |
444 | "%s: bogus group key\n", __func__); | |
445 | return 0; | |
446 | } | |
447 | if (vap->iv_opmode != IEEE80211_M_HOSTAP || | |
448 | !(k->wk_flags & IEEE80211_KEY_GROUP) || | |
449 | !sc->sc_mcastkey) { | |
450 | /* | |
451 | * XXX we pre-allocate the global keys so | |
452 | * have no way to check if they've already | |
453 | * been allocated. | |
454 | */ | |
455 | *keyix = *rxkeyix = k - vap->iv_nw_keys; | |
456 | return 1; | |
457 | } | |
458 | /* | |
459 | * Group key and device supports multicast key search. | |
460 | */ | |
461 | k->wk_keyix = IEEE80211_KEYIX_NONE; | |
462 | } | |
463 | ||
464 | /* | |
465 | * We allocate two pair for TKIP when using the h/w to do | |
466 | * the MIC. For everything else, including software crypto, | |
467 | * we allocate a single entry. Note that s/w crypto requires | |
468 | * a pass-through slot on the 5211 and 5212. The 5210 does | |
469 | * not support pass-through cache entries and we map all | |
470 | * those requests to slot 0. | |
471 | */ | |
472 | if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { | |
473 | return key_alloc_single(sc, keyix, rxkeyix); | |
474 | } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP && | |
475 | (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { | |
476 | if (sc->sc_splitmic) | |
477 | return key_alloc_2pair(sc, keyix, rxkeyix); | |
478 | else | |
479 | return key_alloc_pair(sc, keyix, rxkeyix); | |
480 | } else { | |
481 | return key_alloc_single(sc, keyix, rxkeyix); | |
482 | } | |
483 | } | |
484 | ||
485 | /* | |
486 | * Delete an entry in the key cache allocated by ath_key_alloc. | |
487 | */ | |
488 | int | |
489 | ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) | |
490 | { | |
4f1aaf2f | 491 | struct ath_softc *sc = vap->iv_ic->ic_softc; |
572ff6f6 MD |
492 | struct ath_hal *ah = sc->sc_ah; |
493 | const struct ieee80211_cipher *cip = k->wk_cipher; | |
494 | u_int keyix = k->wk_keyix; | |
495 | ||
496 | DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: delete key %u\n", __func__, keyix); | |
497 | ||
848b370c | 498 | ATH_LOCK(sc); |
d98a0bcf | 499 | ath_power_set_power_state(sc, HAL_PM_AWAKE); |
572ff6f6 MD |
500 | ath_hal_keyreset(ah, keyix); |
501 | /* | |
502 | * Handle split tx/rx keying required for TKIP with h/w MIC. | |
503 | */ | |
504 | if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && | |
505 | (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic) | |
506 | ath_hal_keyreset(ah, keyix+32); /* RX key */ | |
507 | if (keyix >= IEEE80211_WEP_NKID) { | |
508 | /* | |
509 | * Don't touch keymap entries for global keys so | |
510 | * they are never considered for dynamic allocation. | |
511 | */ | |
512 | clrbit(sc->sc_keymap, keyix); | |
513 | if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && | |
514 | (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { | |
515 | clrbit(sc->sc_keymap, keyix+64); /* TX key MIC */ | |
516 | if (sc->sc_splitmic) { | |
517 | /* +32 for RX key, +32+64 for RX key MIC */ | |
518 | clrbit(sc->sc_keymap, keyix+32); | |
519 | clrbit(sc->sc_keymap, keyix+32+64); | |
520 | } | |
521 | } | |
522 | } | |
d98a0bcf | 523 | ath_power_restore_power_state(sc); |
848b370c | 524 | ATH_UNLOCK(sc); |
572ff6f6 MD |
525 | return 1; |
526 | } | |
527 | ||
528 | /* | |
529 | * Set the key cache contents for the specified key. Key cache | |
530 | * slot(s) must already have been allocated by ath_key_alloc. | |
531 | */ | |
532 | int | |
b14ca477 | 533 | ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) |
572ff6f6 | 534 | { |
4f1aaf2f | 535 | struct ath_softc *sc = vap->iv_ic->ic_softc; |
572ff6f6 MD |
536 | |
537 | return ath_keyset(sc, vap, k, vap->iv_bss); | |
538 | } |