diff options
author | Michael Buesch <mb@bu3sch.de> | 2009-08-06 04:36:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:13:45 -0400 |
commit | 66d2d089c394c7e31020947d682523f77a93244b (patch) | |
tree | d4bef490c1449252606ca09be804c191f0822ce5 | |
parent | 5ba63533bbf653631faab60f6988506160ec6ba4 (diff) |
b43: Fix hardware key index handling
This fixes the hardware encryption keys index and array size handling.
Thanks to Gregor Kowski for reporting this issue.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 96 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 4 |
3 files changed, 53 insertions, 54 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 102094a23598..a1b3b731935b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -493,6 +493,10 @@ enum { | |||
493 | 493 | ||
494 | /* Max size of a security key */ | 494 | /* Max size of a security key */ |
495 | #define B43_SEC_KEYSIZE 16 | 495 | #define B43_SEC_KEYSIZE 16 |
496 | /* Max number of group keys */ | ||
497 | #define B43_NR_GROUP_KEYS 4 | ||
498 | /* Max number of pairwise keys */ | ||
499 | #define B43_NR_PAIRWISE_KEYS 50 | ||
496 | /* Security algorithms. */ | 500 | /* Security algorithms. */ |
497 | enum { | 501 | enum { |
498 | B43_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ | 502 | B43_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ |
@@ -819,8 +823,7 @@ struct b43_wldev { | |||
819 | 823 | ||
820 | /* encryption/decryption */ | 824 | /* encryption/decryption */ |
821 | u16 ktp; /* Key table pointer */ | 825 | u16 ktp; /* Key table pointer */ |
822 | u8 max_nr_keys; | 826 | struct b43_key key[B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS]; |
823 | struct b43_key key[58]; | ||
824 | 827 | ||
825 | /* Firmware data */ | 828 | /* Firmware data */ |
826 | struct b43_firmware fw; | 829 | struct b43_firmware fw; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 997dd55b63f7..950beefbeaeb 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -796,18 +796,19 @@ static void key_write(struct b43_wldev *dev, | |||
796 | static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr) | 796 | static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr) |
797 | { | 797 | { |
798 | u32 addrtmp[2] = { 0, 0, }; | 798 | u32 addrtmp[2] = { 0, 0, }; |
799 | u8 per_sta_keys_start = 8; | 799 | u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2; |
800 | 800 | ||
801 | if (b43_new_kidx_api(dev)) | 801 | if (b43_new_kidx_api(dev)) |
802 | per_sta_keys_start = 4; | 802 | pairwise_keys_start = B43_NR_GROUP_KEYS; |
803 | 803 | ||
804 | B43_WARN_ON(index < per_sta_keys_start); | 804 | B43_WARN_ON(index < pairwise_keys_start); |
805 | /* We have two default TX keys and possibly two default RX keys. | 805 | /* We have four default TX keys and possibly four default RX keys. |
806 | * Physical mac 0 is mapped to physical key 4 or 8, depending | 806 | * Physical mac 0 is mapped to physical key 4 or 8, depending |
807 | * on the firmware version. | 807 | * on the firmware version. |
808 | * So we must adjust the index here. | 808 | * So we must adjust the index here. |
809 | */ | 809 | */ |
810 | index -= per_sta_keys_start; | 810 | index -= pairwise_keys_start; |
811 | B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS); | ||
811 | 812 | ||
812 | if (addr) { | 813 | if (addr) { |
813 | addrtmp[0] = addr[0]; | 814 | addrtmp[0] = addr[0]; |
@@ -818,27 +819,11 @@ static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr) | |||
818 | addrtmp[1] |= ((u32) (addr[5]) << 8); | 819 | addrtmp[1] |= ((u32) (addr[5]) << 8); |
819 | } | 820 | } |
820 | 821 | ||
821 | if (dev->dev->id.revision >= 5) { | 822 | /* Receive match transmitter address (RCMTA) mechanism */ |
822 | /* Receive match transmitter address mechanism */ | 823 | b43_shm_write32(dev, B43_SHM_RCMTA, |
823 | b43_shm_write32(dev, B43_SHM_RCMTA, | 824 | (index * 2) + 0, addrtmp[0]); |
824 | (index * 2) + 0, addrtmp[0]); | 825 | b43_shm_write16(dev, B43_SHM_RCMTA, |
825 | b43_shm_write16(dev, B43_SHM_RCMTA, | 826 | (index * 2) + 1, addrtmp[1]); |
826 | (index * 2) + 1, addrtmp[1]); | ||
827 | } else { | ||
828 | /* RXE (Receive Engine) and | ||
829 | * PSM (Programmable State Machine) mechanism | ||
830 | */ | ||
831 | if (index < 8) { | ||
832 | /* TODO write to RCM 16, 19, 22 and 25 */ | ||
833 | } else { | ||
834 | b43_shm_write32(dev, B43_SHM_SHARED, | ||
835 | B43_SHM_SH_PSM + (index * 6) + 0, | ||
836 | addrtmp[0]); | ||
837 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
838 | B43_SHM_SH_PSM + (index * 6) + 4, | ||
839 | addrtmp[1]); | ||
840 | } | ||
841 | } | ||
842 | } | 827 | } |
843 | 828 | ||
844 | static void do_key_write(struct b43_wldev *dev, | 829 | static void do_key_write(struct b43_wldev *dev, |
@@ -846,20 +831,20 @@ static void do_key_write(struct b43_wldev *dev, | |||
846 | const u8 *key, size_t key_len, const u8 *mac_addr) | 831 | const u8 *key, size_t key_len, const u8 *mac_addr) |
847 | { | 832 | { |
848 | u8 buf[B43_SEC_KEYSIZE] = { 0, }; | 833 | u8 buf[B43_SEC_KEYSIZE] = { 0, }; |
849 | u8 per_sta_keys_start = 8; | 834 | u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2; |
850 | 835 | ||
851 | if (b43_new_kidx_api(dev)) | 836 | if (b43_new_kidx_api(dev)) |
852 | per_sta_keys_start = 4; | 837 | pairwise_keys_start = B43_NR_GROUP_KEYS; |
853 | 838 | ||
854 | B43_WARN_ON(index >= dev->max_nr_keys); | 839 | B43_WARN_ON(index >= ARRAY_SIZE(dev->key)); |
855 | B43_WARN_ON(key_len > B43_SEC_KEYSIZE); | 840 | B43_WARN_ON(key_len > B43_SEC_KEYSIZE); |
856 | 841 | ||
857 | if (index >= per_sta_keys_start) | 842 | if (index >= pairwise_keys_start) |
858 | keymac_write(dev, index, NULL); /* First zero out mac. */ | 843 | keymac_write(dev, index, NULL); /* First zero out mac. */ |
859 | if (key) | 844 | if (key) |
860 | memcpy(buf, key, key_len); | 845 | memcpy(buf, key, key_len); |
861 | key_write(dev, index, algorithm, buf); | 846 | key_write(dev, index, algorithm, buf); |
862 | if (index >= per_sta_keys_start) | 847 | if (index >= pairwise_keys_start) |
863 | keymac_write(dev, index, mac_addr); | 848 | keymac_write(dev, index, mac_addr); |
864 | 849 | ||
865 | dev->key[index].algorithm = algorithm; | 850 | dev->key[index].algorithm = algorithm; |
@@ -872,21 +857,24 @@ static int b43_key_write(struct b43_wldev *dev, | |||
872 | struct ieee80211_key_conf *keyconf) | 857 | struct ieee80211_key_conf *keyconf) |
873 | { | 858 | { |
874 | int i; | 859 | int i; |
875 | int sta_keys_start; | 860 | int pairwise_keys_start; |
876 | 861 | ||
877 | if (key_len > B43_SEC_KEYSIZE) | 862 | if (key_len > B43_SEC_KEYSIZE) |
878 | return -EINVAL; | 863 | return -EINVAL; |
879 | for (i = 0; i < dev->max_nr_keys; i++) { | 864 | for (i = 0; i < ARRAY_SIZE(dev->key); i++) { |
880 | /* Check that we don't already have this key. */ | 865 | /* Check that we don't already have this key. */ |
881 | B43_WARN_ON(dev->key[i].keyconf == keyconf); | 866 | B43_WARN_ON(dev->key[i].keyconf == keyconf); |
882 | } | 867 | } |
883 | if (index < 0) { | 868 | if (index < 0) { |
884 | /* Pairwise key. Get an empty slot for the key. */ | 869 | /* Pairwise key. Get an empty slot for the key. */ |
885 | if (b43_new_kidx_api(dev)) | 870 | if (b43_new_kidx_api(dev)) |
886 | sta_keys_start = 4; | 871 | pairwise_keys_start = B43_NR_GROUP_KEYS; |
887 | else | 872 | else |
888 | sta_keys_start = 8; | 873 | pairwise_keys_start = B43_NR_GROUP_KEYS * 2; |
889 | for (i = sta_keys_start; i < dev->max_nr_keys; i++) { | 874 | for (i = pairwise_keys_start; |
875 | i < pairwise_keys_start + B43_NR_PAIRWISE_KEYS; | ||
876 | i++) { | ||
877 | B43_WARN_ON(i >= ARRAY_SIZE(dev->key)); | ||
890 | if (!dev->key[i].keyconf) { | 878 | if (!dev->key[i].keyconf) { |
891 | /* found empty */ | 879 | /* found empty */ |
892 | index = i; | 880 | index = i; |
@@ -914,7 +902,7 @@ static int b43_key_write(struct b43_wldev *dev, | |||
914 | 902 | ||
915 | static int b43_key_clear(struct b43_wldev *dev, int index) | 903 | static int b43_key_clear(struct b43_wldev *dev, int index) |
916 | { | 904 | { |
917 | if (B43_WARN_ON((index < 0) || (index >= dev->max_nr_keys))) | 905 | if (B43_WARN_ON((index < 0) || (index >= ARRAY_SIZE(dev->key)))) |
918 | return -EINVAL; | 906 | return -EINVAL; |
919 | do_key_write(dev, index, B43_SEC_ALGO_NONE, | 907 | do_key_write(dev, index, B43_SEC_ALGO_NONE, |
920 | NULL, B43_SEC_KEYSIZE, NULL); | 908 | NULL, B43_SEC_KEYSIZE, NULL); |
@@ -929,15 +917,19 @@ static int b43_key_clear(struct b43_wldev *dev, int index) | |||
929 | 917 | ||
930 | static void b43_clear_keys(struct b43_wldev *dev) | 918 | static void b43_clear_keys(struct b43_wldev *dev) |
931 | { | 919 | { |
932 | int i; | 920 | int i, count; |
933 | 921 | ||
934 | for (i = 0; i < dev->max_nr_keys; i++) | 922 | if (b43_new_kidx_api(dev)) |
923 | count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS; | ||
924 | else | ||
925 | count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS; | ||
926 | for (i = 0; i < count; i++) | ||
935 | b43_key_clear(dev, i); | 927 | b43_key_clear(dev, i); |
936 | } | 928 | } |
937 | 929 | ||
938 | static void b43_dump_keymemory(struct b43_wldev *dev) | 930 | static void b43_dump_keymemory(struct b43_wldev *dev) |
939 | { | 931 | { |
940 | unsigned int i, index, offset; | 932 | unsigned int i, index, count, offset, pairwise_keys_start; |
941 | u8 mac[ETH_ALEN]; | 933 | u8 mac[ETH_ALEN]; |
942 | u16 algo; | 934 | u16 algo; |
943 | u32 rcmta0; | 935 | u32 rcmta0; |
@@ -951,7 +943,14 @@ static void b43_dump_keymemory(struct b43_wldev *dev) | |||
951 | hf = b43_hf_read(dev); | 943 | hf = b43_hf_read(dev); |
952 | b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n", | 944 | b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n", |
953 | !!(hf & B43_HF_USEDEFKEYS)); | 945 | !!(hf & B43_HF_USEDEFKEYS)); |
954 | for (index = 0; index < dev->max_nr_keys; index++) { | 946 | if (b43_new_kidx_api(dev)) { |
947 | pairwise_keys_start = B43_NR_GROUP_KEYS; | ||
948 | count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS; | ||
949 | } else { | ||
950 | pairwise_keys_start = B43_NR_GROUP_KEYS * 2; | ||
951 | count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS; | ||
952 | } | ||
953 | for (index = 0; index < count; index++) { | ||
955 | key = &(dev->key[index]); | 954 | key = &(dev->key[index]); |
956 | printk(KERN_DEBUG "Key slot %02u: %s", | 955 | printk(KERN_DEBUG "Key slot %02u: %s", |
957 | index, (key->keyconf == NULL) ? " " : "*"); | 956 | index, (key->keyconf == NULL) ? " " : "*"); |
@@ -965,11 +964,11 @@ static void b43_dump_keymemory(struct b43_wldev *dev) | |||
965 | B43_SHM_SH_KEYIDXBLOCK + (index * 2)); | 964 | B43_SHM_SH_KEYIDXBLOCK + (index * 2)); |
966 | printk(" Algo: %04X/%02X", algo, key->algorithm); | 965 | printk(" Algo: %04X/%02X", algo, key->algorithm); |
967 | 966 | ||
968 | if (index >= 4) { | 967 | if (index >= pairwise_keys_start) { |
969 | rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, | 968 | rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, |
970 | ((index - 4) * 2) + 0); | 969 | ((index - pairwise_keys_start) * 2) + 0); |
971 | rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, | 970 | rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, |
972 | ((index - 4) * 2) + 1); | 971 | ((index - pairwise_keys_start) * 2) + 1); |
973 | *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); | 972 | *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); |
974 | *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); | 973 | *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); |
975 | printk(" MAC: %pM", mac); | 974 | printk(" MAC: %pM", mac); |
@@ -2876,17 +2875,14 @@ error: | |||
2876 | 2875 | ||
2877 | static void b43_security_init(struct b43_wldev *dev) | 2876 | static void b43_security_init(struct b43_wldev *dev) |
2878 | { | 2877 | { |
2879 | dev->max_nr_keys = (dev->dev->id.revision >= 5) ? 58 : 20; | ||
2880 | B43_WARN_ON(dev->max_nr_keys > ARRAY_SIZE(dev->key)); | ||
2881 | dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP); | 2878 | dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP); |
2882 | /* KTP is a word address, but we address SHM bytewise. | 2879 | /* KTP is a word address, but we address SHM bytewise. |
2883 | * So multiply by two. | 2880 | * So multiply by two. |
2884 | */ | 2881 | */ |
2885 | dev->ktp *= 2; | 2882 | dev->ktp *= 2; |
2886 | if (dev->dev->id.revision >= 5) { | 2883 | /* Number of RCMTA address slots */ |
2887 | /* Number of RCMTA address slots */ | 2884 | b43_write16(dev, B43_MMIO_RCMTA_COUNT, B43_NR_PAIRWISE_KEYS); |
2888 | b43_write16(dev, B43_MMIO_RCMTA_COUNT, dev->max_nr_keys - 8); | 2885 | /* Clear the key memory. */ |
2889 | } | ||
2890 | b43_clear_keys(dev); | 2886 | b43_clear_keys(dev); |
2891 | } | 2887 | } |
2892 | 2888 | ||
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5b85e7d73592..5280ebc8c6e9 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -237,7 +237,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
237 | int wlhdr_len; | 237 | int wlhdr_len; |
238 | size_t iv_len; | 238 | size_t iv_len; |
239 | 239 | ||
240 | B43_WARN_ON(key_idx >= dev->max_nr_keys); | 240 | B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key)); |
241 | key = &(dev->key[key_idx]); | 241 | key = &(dev->key[key_idx]); |
242 | 242 | ||
243 | if (unlikely(!key->keyconf)) { | 243 | if (unlikely(!key->keyconf)) { |
@@ -578,7 +578,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
578 | * key index, but the ucode passed it slightly different. | 578 | * key index, but the ucode passed it slightly different. |
579 | */ | 579 | */ |
580 | keyidx = b43_kidx_to_raw(dev, keyidx); | 580 | keyidx = b43_kidx_to_raw(dev, keyidx); |
581 | B43_WARN_ON(keyidx >= dev->max_nr_keys); | 581 | B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key)); |
582 | 582 | ||
583 | if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { | 583 | if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { |
584 | wlhdr_len = ieee80211_hdrlen(fctl); | 584 | wlhdr_len = ieee80211_hdrlen(fctl); |