Please test if this fixes hwcrypto.
Note that we will require v4 firmware with this patch.
I will remove v3 firmware support, because it's _really_
a huge pain to support both firmware versions.
If someone wants to have v3 support, please fork my tree.
Or alternatively simply install v4 firmware, which is a lot
easier. ;)

Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h     
2006-11-14 16:03:00.000000000 +0100
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h  2006-11-14 
18:34:14.000000000 +0100
@@ -620,7 +620,6 @@ struct bcm43xx_stats {
 
 struct bcm43xx_key {
        u8 enabled;
-       u8 used;
        u8 algorithm;
        u8 address[6];
 };
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c        
2006-11-14 16:03:00.000000000 +0100
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c     
2006-11-15 18:58:51.000000000 +0100
@@ -874,11 +874,12 @@ static void keymac_write(struct bcm43xx_
 {
        u32 addrtmp[2];
 
+       assert(index >= 4 + 4);
+       memcpy(bcm->key[index].address, addr, 6);
        /* We have two default TX keys and two default RX keys.
         * Physical mac 0 is mapped to physical key 8.
         * So we must adjust the index here.
         */
-       assert(index >= 4 + 4);
        index -= 8;
 
        addrtmp[0] = addr[0];
@@ -912,97 +913,88 @@ static void keymac_write(struct bcm43xx_
        }
 }
 
-static int key_write_common(struct bcm43xx_private *bcm,
-                           u8 index, u8 algorithm,
-                           struct ieee80211_key_conf *keyconf,
-                           const u8 *mac_addr)
+static void do_key_write(struct bcm43xx_private *bcm,
+                        u8 index, u8 algorithm,
+                        const u8 *key, size_t key_len,
+                        const u8 *mac_addr)
 {
        u8 buf[BCM43xx_SEC_KEYSIZE];
 
-       /* The "index" passed to this function is the
-        * absolute key table index.
-        */
-
-       if ((index >= bcm->max_nr_keys) ||
-           (keyconf && (keyconf->keylen > BCM43xx_SEC_KEYSIZE)))
-               return -EINVAL;
+       assert(index < bcm->max_nr_keys);
+       assert(key_len <= BCM43xx_SEC_KEYSIZE);
 
        memset(buf, 0, sizeof(buf));
-       if (mac_addr)
+       if (index >= 8)
                keymac_write(bcm, index, buf); /* First zero out mac. */
-       if (keyconf)
-               memcpy(buf, keyconf->key, keyconf->keylen);
+       memcpy(buf, key, key_len);
        key_write(bcm, index, algorithm, buf);
-       if (mac_addr)
+       if (index >= 8)
                keymac_write(bcm, index, mac_addr);
-       bcm->key[index].algorithm = algorithm;
-       bcm->key[index].used = 1;
-       bcm->key[index].enabled = 1;
-       if (mac_addr)
-               memcpy(bcm->key[index].address, mac_addr, 6);
-       else
-               memset(bcm->key[index].address, 0, 6);
 
-       return 0;
+       bcm->key[index].algorithm = algorithm;
 }
 
-static int bcm43xx_default_key_write(struct bcm43xx_private *bcm,
-                                    u8 index, u8 algorithm,
-                                    struct ieee80211_key_conf *key)
+static int bcm43xx_key_write(struct bcm43xx_private *bcm,
+                            int index, u8 algorithm,
+                            const u8 *key, size_t key_len,
+                            const u8 *mac_addr,
+                            struct ieee80211_key_conf *keyconf)
 {
-       int err;
+       int i;
 
-       if (index > 3)
+       if (key_len > BCM43xx_SEC_KEYSIZE)
                return -EINVAL;
+       if (index < 0) {
+               /* Per station key with associated MAC address.
+                * Look if it already exists, if yes update, otherwise
+                * allocate a new key.
+                */
+               for (i = 8; i < bcm->max_nr_keys; i++) {
+                       if (compare_ether_addr(bcm->key[i].address, mac_addr) 
== 0) {
+                               /* found existing */
+                               index = i;
+                               break;
+                       }
+               }
+               if (index < 0) {
+                       for (i = 8; i < bcm->max_nr_keys; i++) {
+                               if (!bcm->key[i].enabled) {
+                                       /* found empty */
+                                       index = i;
+                                       break;
+                               }
+                       }
+               }
+               if (index < 0) {
+                       dprintk(KERN_ERR PFX "Out of hw key memory\n");
+                       return -ENOBUFS;
+               }
+       } else
+               assert(index <= 3);
 
-       /* Write default TX key */
-       err = key_write_common(bcm, index, algorithm,
-                              key, NULL);
-       if (err)
-               return err;
-       /* Write default RX key */
-       err = key_write_common(bcm, index + 4, algorithm,
-                              key, NULL);
-       key->hw_key_idx = index;
-
-       return err;
-}
-
-static int bcm43xx_key_write(struct bcm43xx_private *bcm,
-                            u8 algorithm,
-                            struct ieee80211_key_conf *key,
-                            const u8 *mac_addr)
-{
-       int err;
-       u8 index;
-
-       for (index = 4 + 4; index < bcm->max_nr_keys; index++) {
-               if (!bcm->key[index].used)
-                       break;
+       do_key_write(bcm, index, algorithm, key, key_len, mac_addr);
+       if (index <= 3) {
+               /* Default RX key */
+               assert(mac_addr == NULL);
+               do_key_write(bcm, index + 4, algorithm, key, key_len, NULL);
        }
-       if (index >= bcm->max_nr_keys)
-               return -ENOBUFS;
+       keyconf->hw_key_idx = index;
 
-       err = key_write_common(bcm, index, algorithm,
-                              key, mac_addr);
-       key->hw_key_idx = index;
-
-       return err;
+       return 0;
 }
 
 static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
 {
-       static const u8 zero[6] = { 0 };
+       static const u8 zero[BCM43xx_SEC_KEYSIZE] = { 0 };
        unsigned int i;
 
+       BUILD_BUG_ON(BCM43xx_SEC_KEYSIZE < ETH_ALEN);
        for (i = 0; i < bcm->max_nr_keys; i++) {
-               key_write_common(bcm, i, 0, NULL,
-                                (i >= 4 + 4) ? zero : NULL);
-               bcm->key[i].used = 0;
+               do_key_write(bcm, i, BCM43xx_SEC_ALGO_NONE,
+                            zero, BCM43xx_SEC_KEYSIZE,
+                            zero);
                bcm->key[i].enabled = 0;
-               bcm->key[i].algorithm = 0;
        }
-       dprintk(KERN_INFO PFX "Keys cleared\n");
 }
 
 /* http://bcm-specs.sipsolutions.net/80211CoreReset */
@@ -1928,9 +1920,15 @@ static int bcm43xx_upload_microcode(stru
        fwtime = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
                                    BCM43xx_SHM_SH_UCODETIME);
 
-       phy->fw = BCM43xx_FW_3;
-       if (fwrev > 0x128)
-               phy->fw = BCM43xx_FW_4;
+       phy->fw = BCM43xx_FW_4;
+       if (fwrev <= 0x128) {
+               printk(KERN_ERR PFX "YOUR FIRMWARE IS TOO OLD. Firmware from "
+                      "binary drivers older than version 4.x is unsupported. "
+                      "You must upgrade your firmware files.\n");
+               bcm43xx_write32(bcm->wlcore, BCM43xx_MMIO_STATUS_BITFIELD, 0);
+               err = -EOPNOTSUPP;
+               goto out;
+       }
        printk(KERN_DEBUG PFX "firmware revision %X, patchlevel %X, "
                              "date 20%.2i-%.2i-%.2i %.2i:%.2i:%.2i\n",
               fwrev, fwpatch,
@@ -3630,7 +3628,6 @@ static int bcm43xx_net_set_key(struct ne
        u8 algorithm;
        u8 index;
        int err = -EINVAL;
-       int i;
 
        switch (key->alg) {
        case ALG_NONE:
@@ -3665,33 +3662,33 @@ static int bcm43xx_net_set_key(struct ne
                err = -ENODEV;
                goto out_unlock;
        }
-       if (bcm43xx_current_phy(bcm)->fw == BCM43xx_FW_3) {
-               /* No support for HW-crypto with v3 firmware. */
-               key->force_sw_encrypt = 1;
-               err = 0;
-               goto out_unlock;
-       }
 
        switch (cmd) {
        case SET_KEY:
+               key->force_sw_encrypt = 0;
 
                if (algorithm == BCM43xx_SEC_ALGO_TKIP) {
                        /* FIXME: No TKIP hardware encryption for now. */
-                       err = 0;
                        key->force_sw_encrypt = 1;
-                       goto out_unlock;
+                       algorithm = BCM43xx_SEC_ALGO_NONE;
                }
 
                if (is_broadcast_ether_addr(addr)) {
                        /* addr is FF:FF:FF:FF:FF:FF for default keys */
-                       err = bcm43xx_default_key_write(bcm, index,
-                                                       algorithm, key);
+                       err = bcm43xx_key_write(bcm, index, algorithm,
+                                               key->key, key->keylen,
+                                               NULL, key);
                } else {
-                       err = bcm43xx_key_write(bcm, algorithm, key,
-                                               addr);
+                       err = bcm43xx_key_write(bcm, -1, algorithm,
+                                               key->key, key->keylen,
+                                               addr, key);
                }
-               if (err)
+               if (err) {
+                       key->force_sw_encrypt = 1;
                        goto out_unlock;
+               }
+               bcm->key[key->hw_key_idx].enabled = 1;
+
                if (algorithm == BCM43xx_SEC_ALGO_WEP40 ||
                    algorithm == BCM43xx_SEC_ALGO_WEP104) {
                        bcm43xx_hf_write(bcm,
@@ -3702,21 +3699,23 @@ static int bcm43xx_net_set_key(struct ne
                                         bcm43xx_hf_read(bcm) &
                                         ~BCM43xx_HF_USEDEFKEYS);
                }
-               key->force_sw_encrypt = 0;
                break;
-       case DISABLE_KEY:
+       case DISABLE_KEY: {
+               static const u8 zero[BCM43xx_SEC_KEYSIZE] = { 0 };
+
+               algorithm = BCM43xx_SEC_ALGO_NONE;
                if (is_broadcast_ether_addr(addr)) {
-                       err = key_write_common(bcm, index, 0, NULL, NULL);
+                       err = bcm43xx_key_write(bcm, index, algorithm,
+                                               zero, BCM43xx_SEC_KEYSIZE,
+                                               NULL, key);
                } else {
-                       static const u8 zero[6] = { 0 };
-
-                       for (i = 8; i < bcm->max_nr_keys; i++) {
-                               if (compare_ether_addr(bcm->key[i].address, 
addr) != 0)
-                                       continue;
-                               err = key_write_common(bcm, i, 0, NULL, zero);
-                       }
+                       err = bcm43xx_key_write(bcm, -1, algorithm,
+                                               zero, BCM43xx_SEC_KEYSIZE,
+                                               addr, key);
                }
+               bcm->key[key->hw_key_idx].enabled = 0;
                break;
+       }
        case REMOVE_ALL_KEYS:
                bcm43xx_clear_keys(bcm);
                err = 0;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c        
2006-11-14 16:03:00.000000000 +0100
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c     
2006-11-15 18:16:18.000000000 +0100
@@ -405,7 +405,6 @@ static void generate_txhdr_fw4(struct bc
 
                assert(key_idx < bcm->max_nr_keys);
                key = &(bcm->key[key_idx]);
-               assert(key->used);
 
                if (key->enabled) {
                        /* Hardware appends ICV. */
@@ -648,34 +647,45 @@ void bcm43xx_rx(struct bcm43xx_private *
 
        if ((macstat & BCM43xx_RX_MAC_DEC) &&
            !(macstat & BCM43xx_RX_MAC_DECERR)) {
+               unsigned int keyidx;
                int wlhdr_len;
                int iv_len;
                int icv_len;
 
-               /* Remove PROTECTED flag to mark it as decrypted. */
-               assert(fctl & IEEE80211_FCTL_PROTECTED);
-               fctl &= ~IEEE80211_FCTL_PROTECTED;
-               wlhdr->frame_control = cpu_to_le16(fctl);
-
-               wlhdr_len = ieee80211_get_hdrlen(fctl);
-               if (skb->data[wlhdr_len + 3] & (1 << 5)) {
-                       /* The Ext-IV Bit is set in the "KeyID"
-                        * octet of the IV.
-                        */
-                       iv_len = 8;
-                       icv_len = 8;
-               } else {
-                       iv_len = 4;
-                       icv_len = 4;
-               }
+               keyidx = ((macstat & BCM43xx_RX_MAC_KEYIDX)
+                         >> BCM43xx_RX_MAC_KEYIDX_SHIFT);
+               /* We must adjust the key index here. We want the "physical"
+                * key index, but the ucode passed it slightly different.
+                */
+               keyidx += 4;
+               assert((keyidx >= 4) && (keyidx < bcm->max_nr_keys));
+
+               if (bcm->key[keyidx].algorithm != BCM43xx_SEC_ALGO_NONE) {
+                       /* Remove PROTECTED flag to mark it as decrypted. */
+                       assert(fctl & IEEE80211_FCTL_PROTECTED);
+                       fctl &= ~IEEE80211_FCTL_PROTECTED;
+                       wlhdr->frame_control = cpu_to_le16(fctl);
+
+                       wlhdr_len = ieee80211_get_hdrlen(fctl);
+                       if (skb->data[wlhdr_len + 3] & (1 << 5)) {
+                               /* The Ext-IV Bit is set in the "KeyID"
+                                * octet of the IV.
+                                */
+                               iv_len = 8;
+                               icv_len = 8;
+                       } else {
+                               iv_len = 4;
+                               icv_len = 4;
+                       }
 
-               /* Remove the IV */
-               memmove(skb->data + iv_len, skb->data, wlhdr_len);
-               skb_pull(skb, iv_len);
-               /* Remove the ICV */
-               skb_trim(skb, skb->len - icv_len);
+                       /* Remove the IV */
+                       memmove(skb->data + iv_len, skb->data, wlhdr_len);
+                       skb_pull(skb, iv_len);
+                       /* Remove the ICV */
+                       skb_trim(skb, skb->len - icv_len);
 
-               status.flag |= RX_FLAG_DECRYPTED;
+                       status.flag |= RX_FLAG_DECRYPTED;
+               }
        }
 
        status.signal = bcm43xx_rssi_postprocess(bcm, jssi,


-- 
Greetings Michael.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to