diff options
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.h | 10 |
4 files changed, 63 insertions, 19 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3e73d2a523a..8a708b77925 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1114,7 +1114,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, { const struct b43_dma_ops *ops = ring->ops; u8 *header; - int slot; + int slot, old_top_slot, old_used_slots; int err; struct b43_dmadesc_generic *desc; struct b43_dmadesc_meta *meta; @@ -1126,6 +1126,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring, #define SLOTS_PER_PACKET 2 B43_WARN_ON(skb_shinfo(skb)->nr_frags); + old_top_slot = ring->current_slot; + old_used_slots = ring->used_slots; + /* Get a slot for the header. */ slot = request_slot(ring); desc = ops->idx2desc(ring, slot, &meta_hdr); @@ -1133,13 +1136,21 @@ static int dma_tx_fragment(struct b43_dmaring *ring, header = &(ring->txhdr_cache[slot * hdrsize]); cookie = generate_cookie(ring, slot); - b43_generate_txhdr(ring->dev, header, - skb->data, skb->len, ctl, cookie); + err = b43_generate_txhdr(ring->dev, header, + skb->data, skb->len, ctl, cookie); + if (unlikely(err)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; + return err; + } meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, hdrsize, 1); - if (dma_mapping_error(meta_hdr->dmaaddr)) + if (dma_mapping_error(meta_hdr->dmaaddr)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; return -EIO; + } ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, hdrsize, 1, 0, 0); @@ -1157,6 +1168,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, if (dma_mapping_error(meta->dmaaddr)) { bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; err = -ENOMEM; goto out_unmap_hdr; } @@ -1167,6 +1180,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (dma_mapping_error(meta->dmaaddr)) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; err = -EIO; goto out_free_bounce; } @@ -1252,6 +1267,13 @@ int b43_dma_tx(struct b43_wldev *dev, B43_WARN_ON(ring->stopped); err = dma_tx_fragment(ring, skb, ctl); + if (unlikely(err == -ENOKEY)) { + /* Drop this packet, as we don't have the encryption key + * anymore and must not transmit it unencrypted. */ + dev_kfree_skb_any(skb); + err = 0; + goto out_unlock; + } if (unlikely(err)) { b43err(dev->wl, "DMA tx mapping failure\n"); goto out_unlock; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 88d2c15d3fb..64c154d080d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3532,8 +3532,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev) b43_bluetooth_coext_enable(dev); ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ - memset(wl->bssid, 0, ETH_ALEN); - memset(wl->mac_addr, 0, ETH_ALEN); b43_upload_card_macaddress(dev); b43_security_init(dev); b43_rng_init(wl); @@ -3630,6 +3628,15 @@ static int b43_op_start(struct ieee80211_hw *hw) struct b43_wldev *dev = wl->current_dev; int did_init = 0; int err = 0; + bool do_rfkill_exit = 0; + + /* Kill all old instance specific information to make sure + * the card won't use it in the short timeframe between start + * and mac80211 reconfiguring it. */ + memset(wl->bssid, 0, ETH_ALEN); + memset(wl->mac_addr, 0, ETH_ALEN); + wl->filter_flags = 0; + wl->radiotap_enabled = 0; /* First register RFkill. * LEDs that are registered later depend on it. */ @@ -3639,8 +3646,10 @@ static int b43_op_start(struct ieee80211_hw *hw) if (b43_status(dev) < B43_STAT_INITIALIZED) { err = b43_wireless_core_init(dev); - if (err) + if (err) { + do_rfkill_exit = 1; goto out_mutex_unlock; + } did_init = 1; } @@ -3649,6 +3658,7 @@ static int b43_op_start(struct ieee80211_hw *hw) if (err) { if (did_init) b43_wireless_core_exit(dev); + do_rfkill_exit = 1; goto out_mutex_unlock; } } @@ -3656,6 +3666,9 @@ static int b43_op_start(struct ieee80211_hw *hw) out_mutex_unlock: mutex_unlock(&wl->mutex); + if (do_rfkill_exit) + b43_rfkill_exit(dev); + return err; } diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 3fc53e8b441..7caa26eb410 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -178,12 +178,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate) } /* Generate a TX data header. */ -void b43_generate_txhdr(struct b43_wldev *dev, - u8 *_txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const struct ieee80211_tx_control *txctl, - u16 cookie) +int b43_generate_txhdr(struct b43_wldev *dev, + u8 *_txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const struct ieee80211_tx_control *txctl, + u16 cookie) { struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; const struct b43_phy *phy = &dev->phy; @@ -237,7 +237,15 @@ void b43_generate_txhdr(struct b43_wldev *dev, B43_WARN_ON(key_idx >= dev->max_nr_keys); key = &(dev->key[key_idx]); - B43_WARN_ON(!key->keyconf); + + if (unlikely(!key->keyconf)) { + /* This key is invalid. This might only happen + * in a short timeframe after machine resume before + * we were able to reconfigure keys. + * Drop this packet completely. Do not transmit it + * unencrypted to avoid leaking information. */ + return -ENOKEY; + } /* Hardware appends ICV. */ plcp_fragment_len += txctl->icv_len; @@ -408,6 +416,7 @@ void b43_generate_txhdr(struct b43_wldev *dev, txhdr->phy_ctl = cpu_to_le16(phy_ctl); txhdr->extra_ft = extra_ft; + return 0; } static s8 b43_rssi_postprocess(struct b43_wldev *dev, diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index ca2a2ab8654..41765039552 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -174,11 +174,11 @@ size_t b43_txhdr_size(struct b43_wldev *dev) } -void b43_generate_txhdr(struct b43_wldev *dev, - u8 * txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const struct ieee80211_tx_control *txctl, u16 cookie); +int b43_generate_txhdr(struct b43_wldev *dev, + u8 * txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const struct ieee80211_tx_control *txctl, u16 cookie); /* Transmit Status */ struct b43_txstatus { |