aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2009-08-06 04:36:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:45 -0400
commit66d2d089c394c7e31020947d682523f77a93244b (patch)
treed4bef490c1449252606ca09be804c191f0822ce5
parent5ba63533bbf653631faab60f6988506160ec6ba4 (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.h7
-rw-r--r--drivers/net/wireless/b43/main.c96
-rw-r--r--drivers/net/wireless/b43/xmit.c4
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. */
497enum { 501enum {
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,
796static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr) 796static 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
844static void do_key_write(struct b43_wldev *dev, 829static 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
915static int b43_key_clear(struct b43_wldev *dev, int index) 903static 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
930static void b43_clear_keys(struct b43_wldev *dev) 918static 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
938static void b43_dump_keymemory(struct b43_wldev *dev) 930static 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
2877static void b43_security_init(struct b43_wldev *dev) 2876static 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);