]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/b43/xmit.c
b43: fix ieee80211_rx() context
[karo-tx-linux.git] / drivers / net / wireless / b43 / xmit.c
index 55f36a7254d98515b7d61b22152fe10c4a567255..f4e9695ec18611a2c33439184fa501fc9dc9a8c7 100644 (file)
@@ -27,7 +27,7 @@
 
 */
 
-#include "xmit.h"
+#include "b43.h"
 #include "phy_common.h"
 #include "dma.h"
 #include "pio.h"
@@ -180,11 +180,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate)
 /* Generate a TX data header. */
 int b43_generate_txhdr(struct b43_wldev *dev,
                       u8 *_txhdr,
-                      const unsigned char *fragment_data,
-                      unsigned int fragment_len,
+                      struct sk_buff *skb_frag,
                       struct ieee80211_tx_info *info,
                       u16 cookie)
 {
+       const unsigned char *fragment_data = skb_frag->data;
+       unsigned int fragment_len = skb_frag->len;
        struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
        const struct b43_phy *phy = &dev->phy;
        const struct ieee80211_hdr *wlhdr =
@@ -237,7 +238,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
                int wlhdr_len;
                size_t iv_len;
 
-               B43_WARN_ON(key_idx >= dev->max_nr_keys);
+               B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key));
                key = &(dev->key[key_idx]);
 
                if (unlikely(!key->keyconf)) {
@@ -258,9 +259,26 @@ int b43_generate_txhdr(struct b43_wldev *dev,
                mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
                           B43_TXH_MAC_KEYALG;
                wlhdr_len = ieee80211_hdrlen(fctl);
-               iv_len = min((size_t) info->control.hw_key->iv_len,
-                            ARRAY_SIZE(txhdr->iv));
-               memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
+               if (key->algorithm == B43_SEC_ALGO_TKIP) {
+                       u16 phase1key[5];
+                       int i;
+                       /* we give the phase1key and iv16 here, the key is stored in
+                        * shm. With that the hardware can do phase 2 and encryption.
+                        */
+                       ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
+                                       IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
+                       /* phase1key is in host endian. Copy to little-endian txhdr->iv. */
+                       for (i = 0; i < 5; i++) {
+                               txhdr->iv[i * 2 + 0] = phase1key[i];
+                               txhdr->iv[i * 2 + 1] = phase1key[i] >> 8;
+                       }
+                       /* iv16 */
+                       memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
+               } else {
+                       iv_len = min((size_t) info->control.hw_key->iv_len,
+                                    ARRAY_SIZE(txhdr->iv));
+                       memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
+               }
        }
        if (b43_is_old_txhdr_format(dev)) {
                b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
@@ -578,7 +596,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
                 * key index, but the ucode passed it slightly different.
                 */
                keyidx = b43_kidx_to_raw(dev, keyidx);
-               B43_WARN_ON(keyidx >= dev->max_nr_keys);
+               B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
 
                if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
                        wlhdr_len = ieee80211_hdrlen(fctl);
@@ -655,6 +673,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
                status.freq = chanid + 2400;
                break;
        case B43_PHYTYPE_N:
+       case B43_PHYTYPE_LP:
                /* chanid is the SHM channel cookie. Which is the plain
                 * channel number in b43. */
                if (chanstat & B43_RX_CHAN_5GHZ) {
@@ -670,8 +689,15 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
                goto drop;
        }
 
-       ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
+       memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
 
+       local_bh_disable();
+       ieee80211_rx(dev->wl->hw, skb);
+       local_bh_enable();
+
+#if B43_DEBUG
+       dev->rx_count++;
+#endif
        return;
 drop:
        b43dbg(dev->wl, "RX: Packet dropped\n");