diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-08-04 10:38:02 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-22 16:29:58 -0400 |
commit | 61e754f44b57060464b1fcf261a8428ecfa23bed (patch) | |
tree | 0fab4e6777f4ad317dac446d0afb24efb9257636 | |
parent | 2bb057d07a0bc17475a7bf897fc41667ab08b73f (diff) |
rt2x00: Implement HW encryption (rt61pci)
rt61pci supports hardware encryption.
rt61pci 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>
-rw-r--r-- | drivers/net/wireless/rt2x00/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 256 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.h | 21 |
3 files changed, 270 insertions, 8 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 2f60e175f039..f333f6100d09 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -107,6 +107,7 @@ config RT61PCI | |||
107 | depends on PCI | 107 | depends on PCI |
108 | select RT2X00_LIB_PCI | 108 | select RT2X00_LIB_PCI |
109 | select RT2X00_LIB_FIRMWARE | 109 | select RT2X00_LIB_FIRMWARE |
110 | select RT2X00_LIB_CRYPTO | ||
110 | select CRC_ITU_T | 111 | select CRC_ITU_T |
111 | select EEPROM_93CX6 | 112 | select EEPROM_93CX6 |
112 | ---help--- | 113 | ---help--- |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 087e90b328cd..86e7a50374b9 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -346,6 +346,204 @@ static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev, | |||
346 | /* | 346 | /* |
347 | * Configuration handlers. | 347 | * Configuration handlers. |
348 | */ | 348 | */ |
349 | static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, | ||
350 | struct rt2x00lib_crypto *crypto, | ||
351 | struct ieee80211_key_conf *key) | ||
352 | { | ||
353 | struct hw_key_entry key_entry; | ||
354 | struct rt2x00_field32 field; | ||
355 | u32 mask; | ||
356 | u32 reg; | ||
357 | |||
358 | if (crypto->cmd == SET_KEY) { | ||
359 | /* | ||
360 | * rt2x00lib can't determine the correct free | ||
361 | * key_idx for shared keys. We have 1 register | ||
362 | * with key valid bits. The goal is simple, read | ||
363 | * the register, if that is full we have no slots | ||
364 | * left. | ||
365 | * Note that each BSS is allowed to have up to 4 | ||
366 | * shared keys, so put a mask over the allowed | ||
367 | * entries. | ||
368 | */ | ||
369 | mask = (0xf << crypto->bssidx); | ||
370 | |||
371 | rt2x00pci_register_read(rt2x00dev, SEC_CSR0, ®); | ||
372 | reg &= mask; | ||
373 | |||
374 | if (reg && reg == mask) | ||
375 | return -ENOSPC; | ||
376 | |||
377 | key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; | ||
378 | |||
379 | /* | ||
380 | * Upload key to hardware | ||
381 | */ | ||
382 | memcpy(key_entry.key, crypto->key, | ||
383 | sizeof(key_entry.key)); | ||
384 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
385 | sizeof(key_entry.tx_mic)); | ||
386 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
387 | sizeof(key_entry.rx_mic)); | ||
388 | |||
389 | reg = SHARED_KEY_ENTRY(key->hw_key_idx); | ||
390 | rt2x00pci_register_multiwrite(rt2x00dev, reg, | ||
391 | &key_entry, sizeof(key_entry)); | ||
392 | |||
393 | /* | ||
394 | * The cipher types are stored over 2 registers. | ||
395 | * bssidx 0 and 1 keys are stored in SEC_CSR1 and | ||
396 | * bssidx 1 and 2 keys are stored in SEC_CSR5. | ||
397 | * Using the correct defines correctly will cause overhead, | ||
398 | * so just calculate the correct offset. | ||
399 | */ | ||
400 | if (key->hw_key_idx < 8) { | ||
401 | field.bit_offset = (3 * key->hw_key_idx); | ||
402 | field.bit_mask = 0x7 << field.bit_offset; | ||
403 | |||
404 | rt2x00pci_register_read(rt2x00dev, SEC_CSR1, ®); | ||
405 | rt2x00_set_field32(®, field, crypto->cipher); | ||
406 | rt2x00pci_register_write(rt2x00dev, SEC_CSR1, reg); | ||
407 | } else { | ||
408 | field.bit_offset = (3 * (key->hw_key_idx - 8)); | ||
409 | field.bit_mask = 0x7 << field.bit_offset; | ||
410 | |||
411 | rt2x00pci_register_read(rt2x00dev, SEC_CSR5, ®); | ||
412 | rt2x00_set_field32(®, field, crypto->cipher); | ||
413 | rt2x00pci_register_write(rt2x00dev, SEC_CSR5, reg); | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * The driver does not support the IV/EIV generation | ||
418 | * in hardware. However it doesn't support the IV/EIV | ||
419 | * inside the ieee80211 frame either, but requires it | ||
420 | * to be provided seperately for the descriptor. | ||
421 | * rt2x00lib will cut the IV/EIV data out of all frames | ||
422 | * given to us by mac80211, but we must tell mac80211 | ||
423 | * to generate the IV/EIV data. | ||
424 | */ | ||
425 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * SEC_CSR0 contains only single-bit fields to indicate | ||
430 | * a particular key is valid. Because using the FIELD32() | ||
431 | * defines directly will cause a lot of overhead we use | ||
432 | * a calculation to determine the correct bit directly. | ||
433 | */ | ||
434 | mask = 1 << key->hw_key_idx; | ||
435 | |||
436 | rt2x00pci_register_read(rt2x00dev, SEC_CSR0, ®); | ||
437 | if (crypto->cmd == SET_KEY) | ||
438 | reg |= mask; | ||
439 | else if (crypto->cmd == DISABLE_KEY) | ||
440 | reg &= ~mask; | ||
441 | rt2x00pci_register_write(rt2x00dev, SEC_CSR0, reg); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | ||
447 | struct rt2x00lib_crypto *crypto, | ||
448 | struct ieee80211_key_conf *key) | ||
449 | { | ||
450 | struct hw_pairwise_ta_entry addr_entry; | ||
451 | struct hw_key_entry key_entry; | ||
452 | u32 mask; | ||
453 | u32 reg; | ||
454 | |||
455 | if (crypto->cmd == SET_KEY) { | ||
456 | /* | ||
457 | * rt2x00lib can't determine the correct free | ||
458 | * key_idx for pairwise keys. We have 2 registers | ||
459 | * with key valid bits. The goal is simple, read | ||
460 | * the first register, if that is full move to | ||
461 | * the next register. | ||
462 | * When both registers are full, we drop the key, | ||
463 | * otherwise we use the first invalid entry. | ||
464 | */ | ||
465 | rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®); | ||
466 | if (reg && reg == ~0) { | ||
467 | key->hw_key_idx = 32; | ||
468 | rt2x00pci_register_read(rt2x00dev, SEC_CSR3, ®); | ||
469 | if (reg && reg == ~0) | ||
470 | return -ENOSPC; | ||
471 | } | ||
472 | |||
473 | key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; | ||
474 | |||
475 | /* | ||
476 | * Upload key to hardware | ||
477 | */ | ||
478 | memcpy(key_entry.key, crypto->key, | ||
479 | sizeof(key_entry.key)); | ||
480 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
481 | sizeof(key_entry.tx_mic)); | ||
482 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
483 | sizeof(key_entry.rx_mic)); | ||
484 | |||
485 | memset(&addr_entry, 0, sizeof(addr_entry)); | ||
486 | memcpy(&addr_entry, crypto->address, ETH_ALEN); | ||
487 | addr_entry.cipher = crypto->cipher; | ||
488 | |||
489 | reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); | ||
490 | rt2x00pci_register_multiwrite(rt2x00dev, reg, | ||
491 | &key_entry, sizeof(key_entry)); | ||
492 | |||
493 | reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); | ||
494 | rt2x00pci_register_multiwrite(rt2x00dev, reg, | ||
495 | &addr_entry, sizeof(addr_entry)); | ||
496 | |||
497 | /* | ||
498 | * Enable pairwise lookup table for given BSS idx, | ||
499 | * without this received frames will not be decrypted | ||
500 | * by the hardware. | ||
501 | */ | ||
502 | rt2x00pci_register_read(rt2x00dev, SEC_CSR4, ®); | ||
503 | reg |= (1 << crypto->bssidx); | ||
504 | rt2x00pci_register_write(rt2x00dev, SEC_CSR4, reg); | ||
505 | |||
506 | /* | ||
507 | * The driver does not support the IV/EIV generation | ||
508 | * in hardware. However it doesn't support the IV/EIV | ||
509 | * inside the ieee80211 frame either, but requires it | ||
510 | * to be provided seperately for the descriptor. | ||
511 | * rt2x00lib will cut the IV/EIV data out of all frames | ||
512 | * given to us by mac80211, but we must tell mac80211 | ||
513 | * to generate the IV/EIV data. | ||
514 | */ | ||
515 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
516 | } | ||
517 | |||
518 | /* | ||
519 | * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate | ||
520 | * a particular key is valid. Because using the FIELD32() | ||
521 | * defines directly will cause a lot of overhead we use | ||
522 | * a calculation to determine the correct bit directly. | ||
523 | */ | ||
524 | if (key->hw_key_idx < 32) { | ||
525 | mask = 1 << key->hw_key_idx; | ||
526 | |||
527 | rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®); | ||
528 | if (crypto->cmd == SET_KEY) | ||
529 | reg |= mask; | ||
530 | else if (crypto->cmd == DISABLE_KEY) | ||
531 | reg &= ~mask; | ||
532 | rt2x00pci_register_write(rt2x00dev, SEC_CSR2, reg); | ||
533 | } else { | ||
534 | mask = 1 << (key->hw_key_idx - 32); | ||
535 | |||
536 | rt2x00pci_register_read(rt2x00dev, SEC_CSR3, ®); | ||
537 | if (crypto->cmd == SET_KEY) | ||
538 | reg |= mask; | ||
539 | else if (crypto->cmd == DISABLE_KEY) | ||
540 | reg &= ~mask; | ||
541 | rt2x00pci_register_write(rt2x00dev, SEC_CSR3, reg); | ||
542 | } | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
349 | static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, | 547 | static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, |
350 | const unsigned int filter_flags) | 548 | const unsigned int filter_flags) |
351 | { | 549 | { |
@@ -1533,8 +1731,8 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1533 | * TX descriptor initialization | 1731 | * TX descriptor initialization |
1534 | */ | 1732 | */ |
1535 | static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 1733 | static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
1536 | struct sk_buff *skb, | 1734 | struct sk_buff *skb, |
1537 | struct txentry_desc *txdesc) | 1735 | struct txentry_desc *txdesc) |
1538 | { | 1736 | { |
1539 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 1737 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
1540 | __le32 *txd = skbdesc->desc; | 1738 | __le32 *txd = skbdesc->desc; |
@@ -1548,7 +1746,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1548 | rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); | 1746 | rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); |
1549 | rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); | 1747 | rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); |
1550 | rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); | 1748 | rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); |
1551 | rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); | 1749 | rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); |
1552 | rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, | 1750 | rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, |
1553 | test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); | 1751 | test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); |
1554 | rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1); | 1752 | rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1); |
@@ -1561,6 +1759,11 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1561 | rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); | 1759 | rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); |
1562 | rt2x00_desc_write(txd, 2, word); | 1760 | rt2x00_desc_write(txd, 2, word); |
1563 | 1761 | ||
1762 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { | ||
1763 | _rt2x00_desc_write(txd, 3, skbdesc->iv); | ||
1764 | _rt2x00_desc_write(txd, 4, skbdesc->eiv); | ||
1765 | } | ||
1766 | |||
1564 | rt2x00_desc_read(txd, 5, &word); | 1767 | rt2x00_desc_read(txd, 5, &word); |
1565 | rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid); | 1768 | rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid); |
1566 | rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, | 1769 | rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, |
@@ -1595,11 +1798,15 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1595 | rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); | 1798 | rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); |
1596 | rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, | 1799 | rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, |
1597 | test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); | 1800 | test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); |
1598 | rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); | 1801 | rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, |
1802 | test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags)); | ||
1803 | rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, | ||
1804 | test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); | ||
1805 | rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); | ||
1599 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); | 1806 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); |
1600 | rt2x00_set_field32(&word, TXD_W0_BURST, | 1807 | rt2x00_set_field32(&word, TXD_W0_BURST, |
1601 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | 1808 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); |
1602 | rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); | 1809 | rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); |
1603 | rt2x00_desc_write(txd, 0, word); | 1810 | rt2x00_desc_write(txd, 0, word); |
1604 | } | 1811 | } |
1605 | 1812 | ||
@@ -1718,6 +1925,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1718 | static void rt61pci_fill_rxdone(struct queue_entry *entry, | 1925 | static void rt61pci_fill_rxdone(struct queue_entry *entry, |
1719 | struct rxdone_entry_desc *rxdesc) | 1926 | struct rxdone_entry_desc *rxdesc) |
1720 | { | 1927 | { |
1928 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1721 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1929 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
1722 | u32 word0; | 1930 | u32 word0; |
1723 | u32 word1; | 1931 | u32 word1; |
@@ -1728,6 +1936,38 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, | |||
1728 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) | 1936 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) |
1729 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | 1937 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; |
1730 | 1938 | ||
1939 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { | ||
1940 | rxdesc->cipher = | ||
1941 | rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); | ||
1942 | rxdesc->cipher_status = | ||
1943 | rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); | ||
1944 | } | ||
1945 | |||
1946 | if (rxdesc->cipher != CIPHER_NONE) { | ||
1947 | _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv); | ||
1948 | _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->eiv); | ||
1949 | _rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv); | ||
1950 | |||
1951 | /* | ||
1952 | * Hardware has stripped IV/EIV data from 802.11 frame during | ||
1953 | * decryption. It has provided the data seperately but rt2x00lib | ||
1954 | * should decide if it should be reinserted. | ||
1955 | */ | ||
1956 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | ||
1957 | |||
1958 | /* | ||
1959 | * FIXME: Legacy driver indicates that the frame does | ||
1960 | * contain the Michael Mic. Unfortunately, in rt2x00 | ||
1961 | * the MIC seems to be missing completely... | ||
1962 | */ | ||
1963 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
1964 | |||
1965 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | ||
1966 | rxdesc->flags |= RX_FLAG_DECRYPTED; | ||
1967 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | ||
1968 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | ||
1969 | } | ||
1970 | |||
1731 | /* | 1971 | /* |
1732 | * Obtain the status about this packet. | 1972 | * Obtain the status about this packet. |
1733 | * When frame was received with an OFDM bitrate, | 1973 | * When frame was received with an OFDM bitrate, |
@@ -1735,7 +1975,7 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, | |||
1735 | * a CCK bitrate the signal is the rate in 100kbit/s. | 1975 | * a CCK bitrate the signal is the rate in 100kbit/s. |
1736 | */ | 1976 | */ |
1737 | rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); | 1977 | rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); |
1738 | rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1); | 1978 | rxdesc->rssi = rt61pci_agc_to_rssi(rt2x00dev, word1); |
1739 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); | 1979 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); |
1740 | 1980 | ||
1741 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) | 1981 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) |
@@ -2355,6 +2595,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2355 | */ | 2595 | */ |
2356 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 2596 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
2357 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | 2597 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); |
2598 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | ||
2358 | 2599 | ||
2359 | /* | 2600 | /* |
2360 | * Set the rssi offset. | 2601 | * Set the rssi offset. |
@@ -2404,6 +2645,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2404 | .config = rt2x00mac_config, | 2645 | .config = rt2x00mac_config, |
2405 | .config_interface = rt2x00mac_config_interface, | 2646 | .config_interface = rt2x00mac_config_interface, |
2406 | .configure_filter = rt2x00mac_configure_filter, | 2647 | .configure_filter = rt2x00mac_configure_filter, |
2648 | .set_key = rt2x00mac_set_key, | ||
2407 | .get_stats = rt2x00mac_get_stats, | 2649 | .get_stats = rt2x00mac_get_stats, |
2408 | .set_retry_limit = rt61pci_set_retry_limit, | 2650 | .set_retry_limit = rt61pci_set_retry_limit, |
2409 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2651 | .bss_info_changed = rt2x00mac_bss_info_changed, |
@@ -2432,6 +2674,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | |||
2432 | .write_beacon = rt61pci_write_beacon, | 2674 | .write_beacon = rt61pci_write_beacon, |
2433 | .kick_tx_queue = rt61pci_kick_tx_queue, | 2675 | .kick_tx_queue = rt61pci_kick_tx_queue, |
2434 | .fill_rxdone = rt61pci_fill_rxdone, | 2676 | .fill_rxdone = rt61pci_fill_rxdone, |
2677 | .config_shared_key = rt61pci_config_shared_key, | ||
2678 | .config_pairwise_key = rt61pci_config_pairwise_key, | ||
2435 | .config_filter = rt61pci_config_filter, | 2679 | .config_filter = rt61pci_config_filter, |
2436 | .config_intf = rt61pci_config_intf, | 2680 | .config_intf = rt61pci_config_intf, |
2437 | .config_erp = rt61pci_config_erp, | 2681 | .config_erp = rt61pci_config_erp, |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 1004d5b899e6..6d591cef3e5d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h | |||
@@ -134,6 +134,16 @@ | |||
134 | #define PAIRWISE_KEY_TABLE_BASE 0x1200 | 134 | #define PAIRWISE_KEY_TABLE_BASE 0x1200 |
135 | #define PAIRWISE_TA_TABLE_BASE 0x1a00 | 135 | #define PAIRWISE_TA_TABLE_BASE 0x1a00 |
136 | 136 | ||
137 | #define SHARED_KEY_ENTRY(__idx) \ | ||
138 | ( SHARED_KEY_TABLE_BASE + \ | ||
139 | ((__idx) * sizeof(struct hw_key_entry)) ) | ||
140 | #define PAIRWISE_KEY_ENTRY(__idx) \ | ||
141 | ( PAIRWISE_KEY_TABLE_BASE + \ | ||
142 | ((__idx) * sizeof(struct hw_key_entry)) ) | ||
143 | #define PAIRWISE_TA_ENTRY(__idx) \ | ||
144 | ( PAIRWISE_TA_TABLE_BASE + \ | ||
145 | ((__idx) * sizeof(struct hw_pairwise_ta_entry)) ) | ||
146 | |||
137 | struct hw_key_entry { | 147 | struct hw_key_entry { |
138 | u8 key[16]; | 148 | u8 key[16]; |
139 | u8 tx_mic[8]; | 149 | u8 tx_mic[8]; |
@@ -142,7 +152,8 @@ struct hw_key_entry { | |||
142 | 152 | ||
143 | struct hw_pairwise_ta_entry { | 153 | struct hw_pairwise_ta_entry { |
144 | u8 address[6]; | 154 | u8 address[6]; |
145 | u8 reserved[2]; | 155 | u8 cipher; |
156 | u8 reserved; | ||
146 | } __attribute__ ((packed)); | 157 | } __attribute__ ((packed)); |
147 | 158 | ||
148 | /* | 159 | /* |
@@ -662,6 +673,10 @@ struct hw_pairwise_ta_entry { | |||
662 | * SEC_CSR4: Pairwise key table lookup control. | 673 | * SEC_CSR4: Pairwise key table lookup control. |
663 | */ | 674 | */ |
664 | #define SEC_CSR4 0x30b0 | 675 | #define SEC_CSR4 0x30b0 |
676 | #define SEC_CSR4_ENABLE_BSS0 FIELD32(0x00000001) | ||
677 | #define SEC_CSR4_ENABLE_BSS1 FIELD32(0x00000002) | ||
678 | #define SEC_CSR4_ENABLE_BSS2 FIELD32(0x00000004) | ||
679 | #define SEC_CSR4_ENABLE_BSS3 FIELD32(0x00000008) | ||
665 | 680 | ||
666 | /* | 681 | /* |
667 | * SEC_CSR5: shared key table security mode register. | 682 | * SEC_CSR5: shared key table security mode register. |
@@ -1428,8 +1443,10 @@ struct hw_pairwise_ta_entry { | |||
1428 | 1443 | ||
1429 | /* | 1444 | /* |
1430 | * Word4 | 1445 | * Word4 |
1446 | * ICV: Received ICV of originally encrypted. | ||
1447 | * NOTE: This is a guess, the official definition is "reserved" | ||
1431 | */ | 1448 | */ |
1432 | #define RXD_W4_RESERVED FIELD32(0xffffffff) | 1449 | #define RXD_W4_ICV FIELD32(0xffffffff) |
1433 | 1450 | ||
1434 | /* | 1451 | /* |
1435 | * the above 20-byte is called RXINFO and will be DMAed to MAC RX block | 1452 | * the above 20-byte is called RXINFO and will be DMAed to MAC RX block |