diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-08-04 10:38:24 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-22 16:29:58 -0400 |
commit | 906c110fcc24bdd5bf0fa22d89ac75d99c747e53 (patch) | |
tree | f7288c835b1490ffee657119bef8317f69cc22aa /drivers/net/wireless | |
parent | 61e754f44b57060464b1fcf261a8428ecfa23bed (diff) |
rt2x00: Implement HW encryption (rt73usb)
rt73usb supports hardware encryption.
rt73usb supports up to 4 shared keys and up to 64 pairwise keys.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/rt2x00/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 271 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.h | 21 |
3 files changed, 285 insertions, 8 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index f333f6100d09..11f590d63aff 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -156,6 +156,7 @@ config RT73USB | |||
156 | depends on USB | 156 | depends on USB |
157 | select RT2X00_LIB_USB | 157 | select RT2X00_LIB_USB |
158 | select RT2X00_LIB_FIRMWARE | 158 | select RT2X00_LIB_FIRMWARE |
159 | select RT2X00_LIB_CRYPTO | ||
159 | select CRC_ITU_T | 160 | select CRC_ITU_T |
160 | ---help--- | 161 | ---help--- |
161 | This adds support for rt2501 wireless chipset family. | 162 | This adds support for rt2501 wireless chipset family. |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 9761eaaa08be..ddba747fed98 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -357,6 +357,219 @@ static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev, | |||
357 | /* | 357 | /* |
358 | * Configuration handlers. | 358 | * Configuration handlers. |
359 | */ | 359 | */ |
360 | static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, | ||
361 | struct rt2x00lib_crypto *crypto, | ||
362 | struct ieee80211_key_conf *key) | ||
363 | { | ||
364 | struct hw_key_entry key_entry; | ||
365 | struct rt2x00_field32 field; | ||
366 | int timeout; | ||
367 | u32 mask; | ||
368 | u32 reg; | ||
369 | |||
370 | if (crypto->cmd == SET_KEY) { | ||
371 | /* | ||
372 | * rt2x00lib can't determine the correct free | ||
373 | * key_idx for shared keys. We have 1 register | ||
374 | * with key valid bits. The goal is simple, read | ||
375 | * the register, if that is full we have no slots | ||
376 | * left. | ||
377 | * Note that each BSS is allowed to have up to 4 | ||
378 | * shared keys, so put a mask over the allowed | ||
379 | * entries. | ||
380 | */ | ||
381 | mask = (0xf << crypto->bssidx); | ||
382 | |||
383 | rt73usb_register_read(rt2x00dev, SEC_CSR0, ®); | ||
384 | reg &= mask; | ||
385 | |||
386 | if (reg && reg == mask) | ||
387 | return -ENOSPC; | ||
388 | |||
389 | key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; | ||
390 | |||
391 | /* | ||
392 | * Upload key to hardware | ||
393 | */ | ||
394 | memcpy(key_entry.key, crypto->key, | ||
395 | sizeof(key_entry.key)); | ||
396 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
397 | sizeof(key_entry.tx_mic)); | ||
398 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
399 | sizeof(key_entry.rx_mic)); | ||
400 | |||
401 | reg = SHARED_KEY_ENTRY(key->hw_key_idx); | ||
402 | timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); | ||
403 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | ||
404 | USB_VENDOR_REQUEST_OUT, reg, | ||
405 | &key_entry, | ||
406 | sizeof(key_entry), | ||
407 | timeout); | ||
408 | |||
409 | /* | ||
410 | * The cipher types are stored over 2 registers. | ||
411 | * bssidx 0 and 1 keys are stored in SEC_CSR1 and | ||
412 | * bssidx 1 and 2 keys are stored in SEC_CSR5. | ||
413 | * Using the correct defines correctly will cause overhead, | ||
414 | * so just calculate the correct offset. | ||
415 | */ | ||
416 | if (key->hw_key_idx < 8) { | ||
417 | field.bit_offset = (3 * key->hw_key_idx); | ||
418 | field.bit_mask = 0x7 << field.bit_offset; | ||
419 | |||
420 | rt73usb_register_read(rt2x00dev, SEC_CSR1, ®); | ||
421 | rt2x00_set_field32(®, field, crypto->cipher); | ||
422 | rt73usb_register_write(rt2x00dev, SEC_CSR1, reg); | ||
423 | } else { | ||
424 | field.bit_offset = (3 * (key->hw_key_idx - 8)); | ||
425 | field.bit_mask = 0x7 << field.bit_offset; | ||
426 | |||
427 | rt73usb_register_read(rt2x00dev, SEC_CSR5, ®); | ||
428 | rt2x00_set_field32(®, field, crypto->cipher); | ||
429 | rt73usb_register_write(rt2x00dev, SEC_CSR5, reg); | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | * The driver does not support the IV/EIV generation | ||
434 | * in hardware. However it doesn't support the IV/EIV | ||
435 | * inside the ieee80211 frame either, but requires it | ||
436 | * to be provided seperately for the descriptor. | ||
437 | * rt2x00lib will cut the IV/EIV data out of all frames | ||
438 | * given to us by mac80211, but we must tell mac80211 | ||
439 | * to generate the IV/EIV data. | ||
440 | */ | ||
441 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | * SEC_CSR0 contains only single-bit fields to indicate | ||
446 | * a particular key is valid. Because using the FIELD32() | ||
447 | * defines directly will cause a lot of overhead we use | ||
448 | * a calculation to determine the correct bit directly. | ||
449 | */ | ||
450 | mask = 1 << key->hw_key_idx; | ||
451 | |||
452 | rt73usb_register_read(rt2x00dev, SEC_CSR0, ®); | ||
453 | if (crypto->cmd == SET_KEY) | ||
454 | reg |= mask; | ||
455 | else if (crypto->cmd == DISABLE_KEY) | ||
456 | reg &= ~mask; | ||
457 | rt73usb_register_write(rt2x00dev, SEC_CSR0, reg); | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | ||
463 | struct rt2x00lib_crypto *crypto, | ||
464 | struct ieee80211_key_conf *key) | ||
465 | { | ||
466 | struct hw_pairwise_ta_entry addr_entry; | ||
467 | struct hw_key_entry key_entry; | ||
468 | int timeout; | ||
469 | u32 mask; | ||
470 | u32 reg; | ||
471 | |||
472 | if (crypto->cmd == SET_KEY) { | ||
473 | /* | ||
474 | * rt2x00lib can't determine the correct free | ||
475 | * key_idx for pairwise keys. We have 2 registers | ||
476 | * with key valid bits. The goal is simple, read | ||
477 | * the first register, if that is full move to | ||
478 | * the next register. | ||
479 | * When both registers are full, we drop the key, | ||
480 | * otherwise we use the first invalid entry. | ||
481 | */ | ||
482 | rt73usb_register_read(rt2x00dev, SEC_CSR2, ®); | ||
483 | if (reg && reg == ~0) { | ||
484 | key->hw_key_idx = 32; | ||
485 | rt73usb_register_read(rt2x00dev, SEC_CSR3, ®); | ||
486 | if (reg && reg == ~0) | ||
487 | return -ENOSPC; | ||
488 | } | ||
489 | |||
490 | key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; | ||
491 | |||
492 | /* | ||
493 | * Upload key to hardware | ||
494 | */ | ||
495 | memcpy(key_entry.key, crypto->key, | ||
496 | sizeof(key_entry.key)); | ||
497 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
498 | sizeof(key_entry.tx_mic)); | ||
499 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
500 | sizeof(key_entry.rx_mic)); | ||
501 | |||
502 | reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); | ||
503 | timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); | ||
504 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | ||
505 | USB_VENDOR_REQUEST_OUT, reg, | ||
506 | &key_entry, | ||
507 | sizeof(key_entry), | ||
508 | timeout); | ||
509 | |||
510 | /* | ||
511 | * Send the address and cipher type to the hardware register. | ||
512 | * This data fits within the CSR cache size, so we can use | ||
513 | * rt73usb_register_multiwrite() directly. | ||
514 | */ | ||
515 | memset(&addr_entry, 0, sizeof(addr_entry)); | ||
516 | memcpy(&addr_entry, crypto->address, ETH_ALEN); | ||
517 | addr_entry.cipher = crypto->cipher; | ||
518 | |||
519 | reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); | ||
520 | rt73usb_register_multiwrite(rt2x00dev, reg, | ||
521 | &addr_entry, sizeof(addr_entry)); | ||
522 | |||
523 | /* | ||
524 | * Enable pairwise lookup table for given BSS idx, | ||
525 | * without this received frames will not be decrypted | ||
526 | * by the hardware. | ||
527 | */ | ||
528 | rt73usb_register_read(rt2x00dev, SEC_CSR4, ®); | ||
529 | reg |= (1 << crypto->bssidx); | ||
530 | rt73usb_register_write(rt2x00dev, SEC_CSR4, reg); | ||
531 | |||
532 | /* | ||
533 | * The driver does not support the IV/EIV generation | ||
534 | * in hardware. However it doesn't support the IV/EIV | ||
535 | * inside the ieee80211 frame either, but requires it | ||
536 | * to be provided seperately for the descriptor. | ||
537 | * rt2x00lib will cut the IV/EIV data out of all frames | ||
538 | * given to us by mac80211, but we must tell mac80211 | ||
539 | * to generate the IV/EIV data. | ||
540 | */ | ||
541 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate | ||
546 | * a particular key is valid. Because using the FIELD32() | ||
547 | * defines directly will cause a lot of overhead we use | ||
548 | * a calculation to determine the correct bit directly. | ||
549 | */ | ||
550 | if (key->hw_key_idx < 32) { | ||
551 | mask = 1 << key->hw_key_idx; | ||
552 | |||
553 | rt73usb_register_read(rt2x00dev, SEC_CSR2, ®); | ||
554 | if (crypto->cmd == SET_KEY) | ||
555 | reg |= mask; | ||
556 | else if (crypto->cmd == DISABLE_KEY) | ||
557 | reg &= ~mask; | ||
558 | rt73usb_register_write(rt2x00dev, SEC_CSR2, reg); | ||
559 | } else { | ||
560 | mask = 1 << (key->hw_key_idx - 32); | ||
561 | |||
562 | rt73usb_register_read(rt2x00dev, SEC_CSR3, ®); | ||
563 | if (crypto->cmd == SET_KEY) | ||
564 | reg |= mask; | ||
565 | else if (crypto->cmd == DISABLE_KEY) | ||
566 | reg &= ~mask; | ||
567 | rt73usb_register_write(rt2x00dev, SEC_CSR3, reg); | ||
568 | } | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
360 | static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, | 573 | static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, |
361 | const unsigned int filter_flags) | 574 | const unsigned int filter_flags) |
362 | { | 575 | { |
@@ -1265,8 +1478,8 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1265 | * TX descriptor initialization | 1478 | * TX descriptor initialization |
1266 | */ | 1479 | */ |
1267 | static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 1480 | static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
1268 | struct sk_buff *skb, | 1481 | struct sk_buff *skb, |
1269 | struct txentry_desc *txdesc) | 1482 | struct txentry_desc *txdesc) |
1270 | { | 1483 | { |
1271 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 1484 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
1272 | __le32 *txd = skbdesc->desc; | 1485 | __le32 *txd = skbdesc->desc; |
@@ -1280,7 +1493,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1280 | rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); | 1493 | rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); |
1281 | rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); | 1494 | rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); |
1282 | rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); | 1495 | rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); |
1283 | rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); | 1496 | rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); |
1284 | rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, | 1497 | rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, |
1285 | test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); | 1498 | test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); |
1286 | rt2x00_desc_write(txd, 1, word); | 1499 | rt2x00_desc_write(txd, 1, word); |
@@ -1292,6 +1505,11 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1292 | rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); | 1505 | rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); |
1293 | rt2x00_desc_write(txd, 2, word); | 1506 | rt2x00_desc_write(txd, 2, word); |
1294 | 1507 | ||
1508 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { | ||
1509 | _rt2x00_desc_write(txd, 3, skbdesc->iv); | ||
1510 | _rt2x00_desc_write(txd, 4, skbdesc->eiv); | ||
1511 | } | ||
1512 | |||
1295 | rt2x00_desc_read(txd, 5, &word); | 1513 | rt2x00_desc_read(txd, 5, &word); |
1296 | rt2x00_set_field32(&word, TXD_W5_TX_POWER, | 1514 | rt2x00_set_field32(&word, TXD_W5_TX_POWER, |
1297 | TXPOWER_TO_DEV(rt2x00dev->tx_power)); | 1515 | TXPOWER_TO_DEV(rt2x00dev->tx_power)); |
@@ -1313,12 +1531,16 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1313 | rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); | 1531 | rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); |
1314 | rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, | 1532 | rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, |
1315 | test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); | 1533 | test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); |
1316 | rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); | 1534 | rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, |
1535 | test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags)); | ||
1536 | rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, | ||
1537 | test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); | ||
1538 | rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); | ||
1317 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, | 1539 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, |
1318 | skb->len - skbdesc->desc_len); | 1540 | skb->len - skbdesc->desc_len); |
1319 | rt2x00_set_field32(&word, TXD_W0_BURST2, | 1541 | rt2x00_set_field32(&word, TXD_W0_BURST2, |
1320 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | 1542 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); |
1321 | rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); | 1543 | rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); |
1322 | rt2x00_desc_write(txd, 0, word); | 1544 | rt2x00_desc_write(txd, 0, word); |
1323 | } | 1545 | } |
1324 | 1546 | ||
@@ -1468,6 +1690,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1468 | static void rt73usb_fill_rxdone(struct queue_entry *entry, | 1690 | static void rt73usb_fill_rxdone(struct queue_entry *entry, |
1469 | struct rxdone_entry_desc *rxdesc) | 1691 | struct rxdone_entry_desc *rxdesc) |
1470 | { | 1692 | { |
1693 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1471 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1694 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1472 | __le32 *rxd = (__le32 *)entry->skb->data; | 1695 | __le32 *rxd = (__le32 *)entry->skb->data; |
1473 | u32 word0; | 1696 | u32 word0; |
@@ -1489,6 +1712,38 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1489 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) | 1712 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) |
1490 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | 1713 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; |
1491 | 1714 | ||
1715 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { | ||
1716 | rxdesc->cipher = | ||
1717 | rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); | ||
1718 | rxdesc->cipher_status = | ||
1719 | rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); | ||
1720 | } | ||
1721 | |||
1722 | if (rxdesc->cipher != CIPHER_NONE) { | ||
1723 | _rt2x00_desc_read(rxd, 2, &rxdesc->iv); | ||
1724 | _rt2x00_desc_read(rxd, 3, &rxdesc->eiv); | ||
1725 | _rt2x00_desc_read(rxd, 4, &rxdesc->icv); | ||
1726 | |||
1727 | /* | ||
1728 | * Hardware has stripped IV/EIV data from 802.11 frame during | ||
1729 | * decryption. It has provided the data seperately but rt2x00lib | ||
1730 | * should decide if it should be reinserted. | ||
1731 | */ | ||
1732 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | ||
1733 | |||
1734 | /* | ||
1735 | * FIXME: Legacy driver indicates that the frame does | ||
1736 | * contain the Michael Mic. Unfortunately, in rt2x00 | ||
1737 | * the MIC seems to be missing completely... | ||
1738 | */ | ||
1739 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
1740 | |||
1741 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | ||
1742 | rxdesc->flags |= RX_FLAG_DECRYPTED; | ||
1743 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | ||
1744 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | ||
1745 | } | ||
1746 | |||
1492 | /* | 1747 | /* |
1493 | * Obtain the status about this packet. | 1748 | * Obtain the status about this packet. |
1494 | * When frame was received with an OFDM bitrate, | 1749 | * When frame was received with an OFDM bitrate, |
@@ -1496,7 +1751,7 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1496 | * a CCK bitrate the signal is the rate in 100kbit/s. | 1751 | * a CCK bitrate the signal is the rate in 100kbit/s. |
1497 | */ | 1752 | */ |
1498 | rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); | 1753 | rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); |
1499 | rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1); | 1754 | rxdesc->rssi = rt73usb_agc_to_rssi(rt2x00dev, word1); |
1500 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); | 1755 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); |
1501 | 1756 | ||
1502 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) | 1757 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) |
@@ -1938,6 +2193,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1938 | */ | 2193 | */ |
1939 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 2194 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
1940 | __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); | 2195 | __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); |
2196 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | ||
1941 | 2197 | ||
1942 | /* | 2198 | /* |
1943 | * Set the rssi offset. | 2199 | * Set the rssi offset. |
@@ -1997,6 +2253,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { | |||
1997 | .config = rt2x00mac_config, | 2253 | .config = rt2x00mac_config, |
1998 | .config_interface = rt2x00mac_config_interface, | 2254 | .config_interface = rt2x00mac_config_interface, |
1999 | .configure_filter = rt2x00mac_configure_filter, | 2255 | .configure_filter = rt2x00mac_configure_filter, |
2256 | .set_key = rt2x00mac_set_key, | ||
2000 | .get_stats = rt2x00mac_get_stats, | 2257 | .get_stats = rt2x00mac_get_stats, |
2001 | .set_retry_limit = rt73usb_set_retry_limit, | 2258 | .set_retry_limit = rt73usb_set_retry_limit, |
2002 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2259 | .bss_info_changed = rt2x00mac_bss_info_changed, |
@@ -2024,6 +2281,8 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { | |||
2024 | .get_tx_data_len = rt73usb_get_tx_data_len, | 2281 | .get_tx_data_len = rt73usb_get_tx_data_len, |
2025 | .kick_tx_queue = rt73usb_kick_tx_queue, | 2282 | .kick_tx_queue = rt73usb_kick_tx_queue, |
2026 | .fill_rxdone = rt73usb_fill_rxdone, | 2283 | .fill_rxdone = rt73usb_fill_rxdone, |
2284 | .config_shared_key = rt73usb_config_shared_key, | ||
2285 | .config_pairwise_key = rt73usb_config_pairwise_key, | ||
2027 | .config_filter = rt73usb_config_filter, | 2286 | .config_filter = rt73usb_config_filter, |
2028 | .config_intf = rt73usb_config_intf, | 2287 | .config_intf = rt73usb_config_intf, |
2029 | .config_erp = rt73usb_config_erp, | 2288 | .config_erp = rt73usb_config_erp, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 148493501011..91e04d319d76 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h | |||
@@ -92,6 +92,16 @@ | |||
92 | #define PAIRWISE_KEY_TABLE_BASE 0x1200 | 92 | #define PAIRWISE_KEY_TABLE_BASE 0x1200 |
93 | #define PAIRWISE_TA_TABLE_BASE 0x1a00 | 93 | #define PAIRWISE_TA_TABLE_BASE 0x1a00 |
94 | 94 | ||
95 | #define SHARED_KEY_ENTRY(__idx) \ | ||
96 | ( SHARED_KEY_TABLE_BASE + \ | ||
97 | ((__idx) * sizeof(struct hw_key_entry)) ) | ||
98 | #define PAIRWISE_KEY_ENTRY(__idx) \ | ||
99 | ( PAIRWISE_KEY_TABLE_BASE + \ | ||
100 | ((__idx) * sizeof(struct hw_key_entry)) ) | ||
101 | #define PAIRWISE_TA_ENTRY(__idx) \ | ||
102 | ( PAIRWISE_TA_TABLE_BASE + \ | ||
103 | ((__idx) * sizeof(struct hw_pairwise_ta_entry)) ) | ||
104 | |||
95 | struct hw_key_entry { | 105 | struct hw_key_entry { |
96 | u8 key[16]; | 106 | u8 key[16]; |
97 | u8 tx_mic[8]; | 107 | u8 tx_mic[8]; |
@@ -100,7 +110,8 @@ struct hw_key_entry { | |||
100 | 110 | ||
101 | struct hw_pairwise_ta_entry { | 111 | struct hw_pairwise_ta_entry { |
102 | u8 address[6]; | 112 | u8 address[6]; |
103 | u8 reserved[2]; | 113 | u8 cipher; |
114 | u8 reserved; | ||
104 | } __attribute__ ((packed)); | 115 | } __attribute__ ((packed)); |
105 | 116 | ||
106 | /* | 117 | /* |
@@ -563,6 +574,10 @@ struct hw_pairwise_ta_entry { | |||
563 | * SEC_CSR4: Pairwise key table lookup control. | 574 | * SEC_CSR4: Pairwise key table lookup control. |
564 | */ | 575 | */ |
565 | #define SEC_CSR4 0x30b0 | 576 | #define SEC_CSR4 0x30b0 |
577 | #define SEC_CSR4_ENABLE_BSS0 FIELD32(0x00000001) | ||
578 | #define SEC_CSR4_ENABLE_BSS1 FIELD32(0x00000002) | ||
579 | #define SEC_CSR4_ENABLE_BSS2 FIELD32(0x00000004) | ||
580 | #define SEC_CSR4_ENABLE_BSS3 FIELD32(0x00000008) | ||
566 | 581 | ||
567 | /* | 582 | /* |
568 | * SEC_CSR5: shared key table security mode register. | 583 | * SEC_CSR5: shared key table security mode register. |
@@ -1010,8 +1025,10 @@ struct hw_pairwise_ta_entry { | |||
1010 | 1025 | ||
1011 | /* | 1026 | /* |
1012 | * Word4 | 1027 | * Word4 |
1028 | * ICV: Received ICV of originally encrypted. | ||
1029 | * NOTE: This is a guess, the official definition is "reserved" | ||
1013 | */ | 1030 | */ |
1014 | #define RXD_W4_RESERVED FIELD32(0xffffffff) | 1031 | #define RXD_W4_ICV FIELD32(0xffffffff) |
1015 | 1032 | ||
1016 | /* | 1033 | /* |
1017 | * the above 20-byte is called RXINFO and will be DMAed to MAC RX block | 1034 | * the above 20-byte is called RXINFO and will be DMAed to MAC RX block |