Dave, Here are some stragglers for 2.6.25. Most of them are fixes for the new stuff anyway -- I don't think there is anything convroversial. Please let me know if there are problems! Thanks, John --- Individual patches are available here: http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/upstream --- The following changes since commit 85040bcb4643cba578839e953f25e2d1965d83d0: YOSHIFUJI Hideaki (1): [IPV6] ADDRLABEL: Fix double free on label deletion. are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream Adrian Bassett (1): rtl8180_dev.c: add support for 1799:700f Bruno Randolf (1): ath5k: debug level improvements Cyrill Gorcunov (1): wireless: iwlwifi3945/4965 - fix incorrect counting of memory Eric Sandeen (1): iwlwifi: correct math in elapsed_jiffies Gregory Greenman (1): iwlwifi: Fix uCode error on association Holger Schurig (1): libertas: fix interrupt while removing driver Ihar Hrachyshka (1): libertas: fix memory alignment problems on the blackfin Iñaky Pérez-González (1): rfkill: add the WiMAX radio type Johannes Berg (1): mac80211: fix alignment warning John W. Linville (1): rt61pci: fix-up merge damage Joonwoo Park (1): iwlwifi: do not schedule tasklet when rcv unused irq Maarten Lankhorst (1): iwlwifi: Fix an invalid bitmask test in iwl3945 and iwl4965 Marcin Juszkiewicz (1): Add another Prism2 card to hostap Michael Buesch (4): b43: Fix rfkill allocation leakage in error paths b43legacy: Fix rfkill allocation leakage in error paths b43: Fix suspend/resume b43: Drop packets that we are not able to encrypt Michal Piotrowski (1): hostap_80211.h: remove duplicate prototype Reinette Chatre (3): iwl4965: fix return code indicating one interface is supported iwlwifi: initialize geo/channel information during probe iwlwifi: cleanup usage of inline functions Ron Rindjunsky (1): mac80211: fixing null qos data frames check for reordering buffer Stefano Brivio (1): b43legacy: fix MAC control and microcode init drivers/net/wireless/ath5k/base.c | 10 +- drivers/net/wireless/ath5k/debug.c | 124 +++++++++++++++++++++---- drivers/net/wireless/ath5k/debug.h | 18 ++-- drivers/net/wireless/b43/dma.c | 30 +++++- drivers/net/wireless/b43/main.c | 19 +++- drivers/net/wireless/b43/xmit.c | 23 +++-- drivers/net/wireless/b43/xmit.h | 10 +- drivers/net/wireless/b43legacy/b43legacy.h | 31 +++---- drivers/net/wireless/b43legacy/main.c | 133 ++++++++++++++++++--------- drivers/net/wireless/b43legacy/phy.c | 14 ++-- drivers/net/wireless/b43legacy/pio.c | 6 +- drivers/net/wireless/b43legacy/radio.c | 16 ++-- drivers/net/wireless/hostap/hostap_80211.h | 5 - drivers/net/wireless/hostap/hostap_cs.c | 3 + drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 14 --- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 - drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 7 -- drivers/net/wireless/iwlwifi/iwl-4965.h | 1 - drivers/net/wireless/iwlwifi/iwl-helpers.h | 4 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 86 +++++++++++++---- drivers/net/wireless/iwlwifi/iwl4965-base.c | 84 ++++++++++++----- drivers/net/wireless/libertas/assoc.c | 6 +- drivers/net/wireless/libertas/dev.h | 2 +- drivers/net/wireless/libertas/if_cs.c | 6 +- drivers/net/wireless/rt2x00/rt61pci.c | 3 +- drivers/net/wireless/rtl8180_dev.c | 1 + include/linux/input.h | 2 + include/linux/rfkill.h | 2 + net/mac80211/rx.c | 48 +++++++--- net/rfkill/rfkill-input.c | 9 ++ net/rfkill/rfkill.c | 3 + 33 files changed, 490 insertions(+), 236 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 72bcf32..d6599d2 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1980,7 +1980,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) struct ath5k_buf *bf = sc->bbuf; struct ath5k_hw *ah = sc->ah; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "in beacon_send\n"); + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA || sc->opmode == IEEE80211_IF_TYPE_MNTR)) { @@ -1996,10 +1996,10 @@ ath5k_beacon_send(struct ath5k_softc *sc) */ if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) { sc->bmisscount++; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "missed %u consecutive beacons\n", sc->bmisscount); if (sc->bmisscount > 3) { /* NB: 3 is a guess */ - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "stuck beacon time (%u missed)\n", sc->bmisscount); tasklet_schedule(&sc->restq); @@ -2007,7 +2007,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) return; } if (unlikely(sc->bmisscount != 0)) { - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "resume beacon xmit after %u misses\n", sc->bmisscount); sc->bmisscount = 0; @@ -2027,7 +2027,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr); ath5k_hw_tx_start(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "TXDP[%u] = %llx (%p)\n", + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", sc->bhalq, (unsigned long long)bf->daddr, bf->desc); sc->bsent++; diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 4ba649e..bb581ef 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Bruno Randolf <bruno@xxxxxxxxxxxxx> + * Copyright (c) 2007-2008 Bruno Randolf <bruno@xxxxxxxxxxxxx> * * This file is free software: you may copy, redistribute and/or modify it * under the terms of the GNU General Public License as published by the @@ -200,7 +200,7 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf, { struct ath5k_softc *sc = file->private_data; char buf[100]; - snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); + snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); return simple_read_from_buffer(user_buf, count, ppos, buf, 19); } @@ -209,7 +209,12 @@ static ssize_t write_file_tsf(struct file *file, size_t count, loff_t *ppos) { struct ath5k_softc *sc = file->private_data; - if (strncmp(userbuf, "reset", 5) == 0) { + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + if (strncmp(buf, "reset", 5) == 0) { ath5k_hw_reset_tsf(sc->ah); printk(KERN_INFO "debugfs reset TSF\n"); } @@ -231,8 +236,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf, { struct ath5k_softc *sc = file->private_data; struct ath5k_hw *ah = sc->ah; - char buf[1000]; - int len = 0; + char buf[500]; + unsigned int len = 0; unsigned int v; u64 tsf; @@ -277,11 +282,15 @@ static ssize_t write_file_beacon(struct file *file, { struct ath5k_softc *sc = file->private_data; struct ath5k_hw *ah = sc->ah; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; - if (strncmp(userbuf, "disable", 7) == 0) { + if (strncmp(buf, "disable", 7) == 0) { AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); printk(KERN_INFO "debugfs disable beacons\n"); - } else if (strncmp(userbuf, "enable", 6) == 0) { + } else if (strncmp(buf, "enable", 6) == 0) { AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); printk(KERN_INFO "debugfs enable beacons\n"); } @@ -314,6 +323,82 @@ static const struct file_operations fops_reset = { }; +/* debugfs: debug level */ + +static struct { + enum ath5k_debug_level level; + const char *name; + const char *desc; +} dbg_info[] = { + { ATH5K_DEBUG_RESET, "reset", "reset and initialization" }, + { ATH5K_DEBUG_INTR, "intr", "interrupt handling" }, + { ATH5K_DEBUG_MODE, "mode", "mode init/setup" }, + { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" }, + { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, + { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, + { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, + { ATH5K_DEBUG_LED, "led", "LED mamagement" }, + { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, + { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, + { ATH5K_DEBUG_DUMPMODES, "dumpmodes", "dump modes" }, + { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, + { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, +}; + +static ssize_t read_file_debug(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[700]; + unsigned int len = 0; + unsigned int i; + + len += snprintf(buf+len, sizeof(buf)-len, + "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level); + + for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { + len += snprintf(buf+len, sizeof(buf)-len, + "%10s %c 0x%08x - %s\n", dbg_info[i].name, + sc->debug.level & dbg_info[i].level ? '+' : ' ', + dbg_info[i].level, dbg_info[i].desc); + } + len += snprintf(buf+len, sizeof(buf)-len, + "%10s %c 0x%08x - %s\n", dbg_info[i].name, + sc->debug.level == dbg_info[i].level ? '+' : ' ', + dbg_info[i].level, dbg_info[i].desc); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_debug(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + unsigned int i; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { + if (strncmp(buf, dbg_info[i].name, + strlen(dbg_info[i].name)) == 0) { + sc->debug.level ^= dbg_info[i].level; /* toggle bit */ + break; + } + } + return count; +} + +static const struct file_operations fops_debug = { + .read = read_file_debug, + .write = write_file_debug, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + /* init */ void @@ -326,26 +411,24 @@ void ath5k_debug_init_device(struct ath5k_softc *sc) { sc->debug.level = ath5k_debug; + sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath5k_global_debugfs); - sc->debug.debugfs_debug = debugfs_create_u32("debug", - 0666, sc->debug.debugfs_phydir, &sc->debug.level); + ath5k_global_debugfs); + + sc->debug.debugfs_debug = debugfs_create_file("debug", 0666, + sc->debug.debugfs_phydir, sc, &fops_debug); sc->debug.debugfs_registers = debugfs_create_file("registers", 0444, - sc->debug.debugfs_phydir, - sc, &fops_registers); + sc->debug.debugfs_phydir, sc, &fops_registers); sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666, - sc->debug.debugfs_phydir, - sc, &fops_tsf); + sc->debug.debugfs_phydir, sc, &fops_tsf); sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666, - sc->debug.debugfs_phydir, - sc, &fops_beacon); + sc->debug.debugfs_phydir, sc, &fops_beacon); sc->debug.debugfs_reset = debugfs_create_file("reset", 0222, - sc->debug.debugfs_phydir, - sc, &fops_reset); + sc->debug.debugfs_phydir, sc, &fops_reset); } void @@ -415,8 +498,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) struct ath5k_buf *bf; int status; - if (likely(!(sc->debug.level & - (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL)))) + if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) return; printk(KERN_DEBUG "rx queue %x, link %p\n", @@ -426,7 +508,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) list_for_each_entry(bf, &sc->rxbuf, list) { ds = bf->desc; status = ah->ah_proc_rx_desc(ah, ds); - if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL)) + if (!status) ath5k_debug_printrxbuf(bf, status == 0); } spin_unlock_bh(&sc->rxbuflock); diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index 2b491cb..c4fd8c4 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h @@ -91,7 +91,6 @@ struct ath5k_dbg_info { * @ATH5K_DEBUG_MODE: mode init/setup * @ATH5K_DEBUG_XMIT: basic xmit operation * @ATH5K_DEBUG_BEACON: beacon handling - * @ATH5K_DEBUG_BEACON_PROC: beacon ISR proc * @ATH5K_DEBUG_CALIBRATE: periodic calibration * @ATH5K_DEBUG_TXPOWER: transmit power setting * @ATH5K_DEBUG_LED: led management @@ -99,7 +98,6 @@ struct ath5k_dbg_info { * @ATH5K_DEBUG_DUMP_TX: print transmit skb content * @ATH5K_DEBUG_DUMPMODES: dump modes * @ATH5K_DEBUG_TRACE: trace function calls - * @ATH5K_DEBUG_FATAL: fatal errors * @ATH5K_DEBUG_ANY: show at any debug level * * The debug level is used to control the amount and type of debugging output @@ -115,15 +113,13 @@ enum ath5k_debug_level { ATH5K_DEBUG_MODE = 0x00000004, ATH5K_DEBUG_XMIT = 0x00000008, ATH5K_DEBUG_BEACON = 0x00000010, - ATH5K_DEBUG_BEACON_PROC = 0x00000020, - ATH5K_DEBUG_CALIBRATE = 0x00000100, - ATH5K_DEBUG_TXPOWER = 0x00000200, - ATH5K_DEBUG_LED = 0x00000400, - ATH5K_DEBUG_DUMP_RX = 0x00001000, - ATH5K_DEBUG_DUMP_TX = 0x00002000, - ATH5K_DEBUG_DUMPMODES = 0x00004000, - ATH5K_DEBUG_TRACE = 0x00010000, - ATH5K_DEBUG_FATAL = 0x80000000, + ATH5K_DEBUG_CALIBRATE = 0x00000020, + ATH5K_DEBUG_TXPOWER = 0x00000040, + ATH5K_DEBUG_LED = 0x00000080, + ATH5K_DEBUG_DUMP_RX = 0x00000100, + ATH5K_DEBUG_DUMP_TX = 0x00000200, + ATH5K_DEBUG_DUMPMODES = 0x00000400, + ATH5K_DEBUG_TRACE = 0x00001000, ATH5K_DEBUG_ANY = 0xffffffff }; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3e73d2a..8a708b7 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 88d2c15..64c154d 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 3fc53e8..7caa26e 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 ca2a2ab..4176503 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 { diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 93419ad..c80edd2 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -23,7 +23,7 @@ #include "phy.h" -#define B43legacy_IRQWAIT_MAX_RETRIES 100 +#define B43legacy_IRQWAIT_MAX_RETRIES 20 #define B43legacy_RX_MAX_SSI 60 /* best guess at max ssi */ @@ -40,9 +40,8 @@ #define B43legacy_MMIO_DMA4_IRQ_MASK 0x44 #define B43legacy_MMIO_DMA5_REASON 0x48 #define B43legacy_MMIO_DMA5_IRQ_MASK 0x4C -#define B43legacy_MMIO_MACCTL 0x120 -#define B43legacy_MMIO_STATUS_BITFIELD 0x120 -#define B43legacy_MMIO_STATUS2_BITFIELD 0x124 +#define B43legacy_MMIO_MACCTL 0x120 /* MAC control */ +#define B43legacy_MMIO_MACCMD 0x124 /* MAC command */ #define B43legacy_MMIO_GEN_IRQ_REASON 0x128 #define B43legacy_MMIO_GEN_IRQ_MASK 0x12C #define B43legacy_MMIO_RAM_CONTROL 0x130 @@ -177,31 +176,25 @@ #define B43legacy_RADIOCTL_ID 0x01 /* MAC Control bitfield */ +#define B43legacy_MACCTL_ENABLED 0x00000001 /* MAC Enabled */ +#define B43legacy_MACCTL_PSM_RUN 0x00000002 /* Run Microcode */ +#define B43legacy_MACCTL_PSM_JMP0 0x00000004 /* Microcode jump to 0 */ +#define B43legacy_MACCTL_SHM_ENABLED 0x00000100 /* SHM Enabled */ #define B43legacy_MACCTL_IHR_ENABLED 0x00000400 /* IHR Region Enabled */ +#define B43legacy_MACCTL_BE 0x00010000 /* Big Endian mode */ #define B43legacy_MACCTL_INFRA 0x00020000 /* Infrastructure mode */ #define B43legacy_MACCTL_AP 0x00040000 /* AccessPoint mode */ +#define B43legacy_MACCTL_RADIOLOCK 0x00080000 /* Radio lock */ #define B43legacy_MACCTL_BEACPROMISC 0x00100000 /* Beacon Promiscuous */ #define B43legacy_MACCTL_KEEP_BADPLCP 0x00200000 /* Keep bad PLCP frames */ #define B43legacy_MACCTL_KEEP_CTL 0x00400000 /* Keep control frames */ #define B43legacy_MACCTL_KEEP_BAD 0x00800000 /* Keep bad frames (FCS) */ #define B43legacy_MACCTL_PROMISC 0x01000000 /* Promiscuous mode */ +#define B43legacy_MACCTL_HWPS 0x02000000 /* Hardware Power Saving */ +#define B43legacy_MACCTL_AWAKE 0x04000000 /* Device is awake */ +#define B43legacy_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */ #define B43legacy_MACCTL_GMODE 0x80000000 /* G Mode */ -/* StatusBitField */ -#define B43legacy_SBF_MAC_ENABLED 0x00000001 -#define B43legacy_SBF_CORE_READY 0x00000004 -#define B43legacy_SBF_400 0x00000400 /*FIXME: fix name*/ -#define B43legacy_SBF_XFER_REG_BYTESWAP 0x00010000 -#define B43legacy_SBF_MODE_NOTADHOC 0x00020000 -#define B43legacy_SBF_MODE_AP 0x00040000 -#define B43legacy_SBF_RADIOREG_LOCK 0x00080000 -#define B43legacy_SBF_MODE_MONITOR 0x00400000 -#define B43legacy_SBF_MODE_PROMISC 0x01000000 -#define B43legacy_SBF_PS1 0x02000000 -#define B43legacy_SBF_PS2 0x04000000 -#define B43legacy_SBF_NO_SSID_BCAST 0x08000000 -#define B43legacy_SBF_TIME_UPDATE 0x10000000 - /* 802.11 core specific TM State Low flags */ #define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */ #define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 4ed4243..aa20d5d 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -225,8 +225,8 @@ static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset, B43legacy_WARN_ON(offset % 4 != 0); - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - if (status & B43legacy_SBF_XFER_REG_BYTESWAP) + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + if (status & B43legacy_MACCTL_BE) val = swab32(val); b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset); @@ -434,9 +434,9 @@ static void b43legacy_time_lock(struct b43legacy_wldev *dev) { u32 status; - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - status |= B43legacy_SBF_TIME_UPDATE; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + status |= B43legacy_MACCTL_TBTTHOLD; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); mmiowb(); } @@ -444,9 +444,9 @@ static void b43legacy_time_unlock(struct b43legacy_wldev *dev) { u32 status; - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - status &= ~B43legacy_SBF_TIME_UPDATE; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + status &= ~B43legacy_MACCTL_TBTTHOLD; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); } static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf) @@ -647,7 +647,7 @@ void b43legacy_dummy_transmission(struct b43legacy_wldev *dev) b43legacy_ram_write(dev, i * 4, buffer[i]); /* dummy read follows */ - b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); + b43legacy_read32(dev, B43legacy_MMIO_MACCTL); b43legacy_write16(dev, 0x0568, 0x0000); b43legacy_write16(dev, 0x07C0, 0x0000); @@ -794,9 +794,9 @@ static void b43legacy_jssi_write(struct b43legacy_wldev *dev, u32 jssi) static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev) { b43legacy_jssi_write(dev, 0x7F7F7F7F); - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, b43legacy_read32(dev, - B43legacy_MMIO_STATUS2_BITFIELD) + B43legacy_MMIO_MACCMD) | (1 << 4)); B43legacy_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel); @@ -895,8 +895,8 @@ static void handle_irq_atim_end(struct b43legacy_wldev *dev) { if (!dev->reg124_set_0x4) /*FIXME rename this variable*/ return; - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, - b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD) + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, + b43legacy_read32(dev, B43legacy_MMIO_MACCMD) | 0x4); } @@ -1106,9 +1106,9 @@ static void b43legacy_update_templates(struct b43legacy_wldev *dev) b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, B43legacy_CCK_RATE_11MB); - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); status |= 0x03; - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, status); + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status); } static void b43legacy_refresh_templates(struct b43legacy_wldev *dev, @@ -1166,7 +1166,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) return; dev->irq_savedstate &= ~B43legacy_IRQ_BEACON; - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) { /* ACK beacon IRQ. */ @@ -1182,14 +1182,14 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) b43legacy_write_beacon_template(dev, 0x68, 0x18, B43legacy_CCK_RATE_1MB); status |= 0x1; - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status); } if (!(status & 0x2)) { b43legacy_write_beacon_template(dev, 0x468, 0x1A, B43legacy_CCK_RATE_1MB); status |= 0x2; - b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status); } } @@ -1548,9 +1548,20 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) u16 fwpatch; u16 fwdate; u16 fwtime; - u32 tmp; + u32 tmp, macctl; int err = 0; + /* Jump the microcode PSM to offset 0 */ + macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + B43legacy_WARN_ON(macctl & B43legacy_MACCTL_PSM_RUN); + macctl |= B43legacy_MACCTL_PSM_JMP0; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); + /* Zero out all microcode PSM registers and shared memory. */ + for (i = 0; i < 64; i++) + b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, i, 0); + for (i = 0; i < 4096; i += 2) + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, i, 0); + /* Upload Microcode. */ data = (__be32 *) (dev->fw.ucode->data + hdr_len); len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32); @@ -1581,7 +1592,12 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_ALL); - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0x00020402); + + /* Start the microcode PSM */ + macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + macctl &= ~B43legacy_MACCTL_PSM_JMP0; + macctl |= B43legacy_MACCTL_PSM_RUN; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); /* Wait for the microcode to load and respond */ i = 0; @@ -1594,9 +1610,13 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) b43legacyerr(dev->wl, "Microcode not responding\n"); b43legacy_print_fw_helptext(dev->wl); err = -ENODEV; - goto out; + goto error; + } + msleep_interruptible(50); + if (signal_pending(current)) { + err = -EINTR; + goto error; } - udelay(10); } /* dummy read follows */ b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); @@ -1617,9 +1637,8 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) " is supported. You must change your firmware" " files.\n"); b43legacy_print_fw_helptext(dev->wl); - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0); err = -EOPNOTSUPP; - goto out; + goto error; } b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u " "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, @@ -1629,7 +1648,14 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) dev->fw.rev = fwrev; dev->fw.patch = fwpatch; -out: + return 0; + +error: + macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + macctl &= ~B43legacy_MACCTL_PSM_RUN; + macctl |= B43legacy_MACCTL_PSM_JMP0; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); + return err; } @@ -1736,9 +1762,9 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev) u32 mask; u32 set; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, b43legacy_read32(dev, - B43legacy_MMIO_STATUS_BITFIELD) + B43legacy_MMIO_MACCTL) & 0xFFFF3FFF); b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK, @@ -1798,14 +1824,14 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev) B43legacy_WARN_ON(dev->mac_suspended < 0); B43legacy_WARN_ON(irqs_disabled()); if (dev->mac_suspended == 0) { - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, b43legacy_read32(dev, - B43legacy_MMIO_STATUS_BITFIELD) - | B43legacy_SBF_MAC_ENABLED); + B43legacy_MMIO_MACCTL) + | B43legacy_MACCTL_ENABLED); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_MAC_SUSPENDED); /* the next two are dummy reads */ - b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); + b43legacy_read32(dev, B43legacy_MMIO_MACCTL); b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); b43legacy_power_saving_ctl_bits(dev, -1, -1); @@ -1836,10 +1862,10 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev) dev->irq_savedstate = tmp; b43legacy_power_saving_ctl_bits(dev, -1, 1); - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, b43legacy_read32(dev, - B43legacy_MMIO_STATUS_BITFIELD) - & ~B43legacy_SBF_MAC_ENABLED); + B43legacy_MMIO_MACCTL) + & ~B43legacy_MACCTL_ENABLED); b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); for (i = 40; i; i--) { tmp = b43legacy_read32(dev, @@ -2007,12 +2033,15 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev) struct b43legacy_phy *phy = &dev->phy; int err; int tmp; - u32 value32; + u32 value32, macctl; u16 value16; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, - B43legacy_SBF_CORE_READY - | B43legacy_SBF_400); + /* Initialize the MAC control */ + macctl = B43legacy_MACCTL_IHR_ENABLED | B43legacy_MACCTL_SHM_ENABLED; + if (dev->phy.gmode) + macctl |= B43legacy_MACCTL_GMODE; + macctl |= B43legacy_MACCTL_INFRA; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); err = b43legacy_request_firmware(dev); if (err) @@ -2052,12 +2081,12 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev) if (dev->dev->id.revision < 5) b43legacy_write32(dev, 0x010C, 0x01000000); - value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - value32 &= ~B43legacy_SBF_MODE_NOTADHOC; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); - value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - value32 |= B43legacy_SBF_MODE_NOTADHOC; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); + value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + value32 &= ~B43legacy_MACCTL_INFRA; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32); + value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + value32 |= B43legacy_MACCTL_INFRA; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32); if (b43legacy_using_pio(dev)) { b43legacy_write32(dev, 0x0210, 0x00000100); @@ -2951,12 +2980,19 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) { struct b43legacy_wl *wl = dev->wl; struct b43legacy_phy *phy = &dev->phy; + u32 macctl; B43legacy_WARN_ON(b43legacy_status(dev) > B43legacy_STAT_INITIALIZED); if (b43legacy_status(dev) != B43legacy_STAT_INITIALIZED) return; b43legacy_set_status(dev, B43legacy_STAT_UNINIT); + /* Stop the microcode PSM. */ + macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + macctl &= ~B43legacy_MACCTL_PSM_RUN; + macctl |= B43legacy_MACCTL_PSM_JMP0; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); + mutex_unlock(&wl->mutex); /* Must unlock as it would otherwise deadlock. No races here. * Cancel possibly pending workqueues. */ @@ -3221,6 +3257,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) struct b43legacy_wldev *dev = wl->current_dev; int did_init = 0; int err = 0; + bool do_rfkill_exit = 0; /* First register RFkill. * LEDs that are registered later depend on it. */ @@ -3230,8 +3267,10 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { err = b43legacy_wireless_core_init(dev); - if (err) + if (err) { + do_rfkill_exit = 1; goto out_mutex_unlock; + } did_init = 1; } @@ -3240,6 +3279,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) if (err) { if (did_init) b43legacy_wireless_core_exit(dev); + do_rfkill_exit = 1; goto out_mutex_unlock; } } @@ -3247,6 +3287,9 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) out_mutex_unlock: mutex_unlock(&wl->mutex); + if (do_rfkill_exit) + b43legacy_rfkill_exit(dev); + return err; } diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index c16febb..8e5c09b 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c @@ -140,7 +140,7 @@ void b43legacy_phy_calibrate(struct b43legacy_wldev *dev) { struct b43legacy_phy *phy = &dev->phy; - b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); /* Dummy read. */ + b43legacy_read32(dev, B43legacy_MMIO_MACCTL); /* Dummy read. */ if (phy->calibrated) return; if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) { @@ -2231,16 +2231,16 @@ bit26 = 1; * or the latest PS-Poll packet sent was successful, * set bit26 */ } - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); if (bit25) - status |= B43legacy_SBF_PS1; + status |= B43legacy_MACCTL_HWPS; else - status &= ~B43legacy_SBF_PS1; + status &= ~B43legacy_MACCTL_HWPS; if (bit26) - status |= B43legacy_SBF_PS2; + status |= B43legacy_MACCTL_AWAKE; else - status &= ~B43legacy_SBF_PS2; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status &= ~B43legacy_MACCTL_AWAKE; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); if (bit26 && dev->dev->id.revision >= 5) { for (i = 0; i < 100; i++) { if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index de843ac..e4f4c5c 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -334,9 +334,9 @@ struct b43legacy_pioqueue *b43legacy_setup_pioqueue(struct b43legacy_wldev *dev, tasklet_init(&queue->txtask, tx_tasklet, (unsigned long)queue); - value = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - value &= ~B43legacy_SBF_XFER_REG_BYTESWAP; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value); + value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + value &= ~B43legacy_MACCTL_BE; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value); qsize = b43legacy_read16(dev, queue->mmio_base + B43legacy_PIO_TXQBUFSIZE); diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c index 318a270..955832e 100644 --- a/drivers/net/wireless/b43legacy/radio.c +++ b/drivers/net/wireless/b43legacy/radio.c @@ -91,10 +91,10 @@ void b43legacy_radio_lock(struct b43legacy_wldev *dev) { u32 status; - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - B43legacy_WARN_ON(status & B43legacy_SBF_RADIOREG_LOCK); - status |= B43legacy_SBF_RADIOREG_LOCK; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK); + status |= B43legacy_MACCTL_RADIOLOCK; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); mmiowb(); udelay(10); } @@ -104,10 +104,10 @@ void b43legacy_radio_unlock(struct b43legacy_wldev *dev) u32 status; b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */ - status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD); - B43legacy_WARN_ON(!(status & B43legacy_SBF_RADIOREG_LOCK)); - status &= ~B43legacy_SBF_RADIOREG_LOCK; - b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status); + status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); + B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK)); + status &= ~B43legacy_MACCTL_RADIOLOCK; + b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); mmiowb(); } diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h index d6b9362..3694b1e 100644 --- a/drivers/net/wireless/hostap/hostap_80211.h +++ b/drivers/net/wireless/hostap/hostap_80211.h @@ -71,11 +71,6 @@ struct hostap_80211_rx_status { u16 rate; /* in 100 kbps */ }; - -void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats); - - /* prism2_rx_80211 'type' argument */ enum { PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC, diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 0759380..437a9bc 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -891,6 +891,9 @@ static struct pcmcia_device_id hostap_cs_ids[] = { PCMCIA_DEVICE_PROD_ID123( "The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", 0xa5f472c2, 0x9c05598d, 0xc9049a39), + PCMCIA_DEVICE_PROD_ID123( + "Wireless LAN" , "11Mbps PC Card", "Version 01.02", + 0x4b8870ff, 0x70e946d1, 0x4b74baa0), PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 6e01873..571815d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -373,7 +373,7 @@ struct iwl3945_eeprom { #define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ #define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ #define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ -#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */ +#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 76c4ed1..4fdeb53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2369,18 +2369,4 @@ struct pci_device_id iwl3945_hw_card_ids[] = { {0} }; -/* - * Clear the OWNER_MSK, to establish driver (instead of uCode running on - * embedded controller) as EEPROM reader; each read is a series of pulses - * to/from the EEPROM chip, not a single event, so even reads could conflict - * if they weren't arbitrated by some ownership mechanism. Here, the driver - * simply claims ownership, which should be safe when this function is called - * (i.e. before loading uCode!). - */ -inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) -{ - _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); - return 0; -} - MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 20b925f..1da14f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -671,7 +671,6 @@ extern int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel); /* * Forward declare iwl-3945.c functions for iwl-base.c */ -extern int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv); extern __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv); extern int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv); extern void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv); @@ -791,7 +790,6 @@ struct iwl3945_priv { u16 active_rate_basic; u8 call_post_assoc_from_beacon; - u8 assoc_station_added; /* Rate scaling data */ s8 data_retry_limit; u8 retry_rate; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index ff71c09..ffe1e9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -465,7 +465,7 @@ struct iwl4965_eeprom { #define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ #define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ #define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ -#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */ +#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 04db34b..569347f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4961,11 +4961,4 @@ int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv) return rc; } -inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv) -{ - iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); -} - - MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 78bc148..9cb82be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -750,7 +750,6 @@ struct iwl4965_priv; * Forward declare iwl-4965.c functions for iwl-base.c */ extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv); -extern void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv); extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq, diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index cd2eb18..cb009f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -246,10 +246,10 @@ static inline int iwl_check_bits(unsigned long field, unsigned long mask) static inline unsigned long elapsed_jiffies(unsigned long start, unsigned long end) { - if (end > start) + if (end >= start) return end - start; - return end + (MAX_JIFFY_OFFSET - start); + return end + (MAX_JIFFY_OFFSET - start) + 1; } static inline u8 iwl_get_dma_hi_address(dma_addr_t addr) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 748ac12..33239f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1557,6 +1557,20 @@ static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac) memcpy(mac, priv->eeprom.mac_address, 6); } +/* + * Clear the OWNER_MSK, to establish driver (instead of uCode running on + * embedded controller) as EEPROM reader; each read is a series of pulses + * to/from the EEPROM chip, not a single event, so even reads could conflict + * if they weren't arbitrated by some ownership mechanism. Here, the driver + * simply claims ownership, which should be safe when this function is called + * (i.e. before loading uCode!). + */ +static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) +{ + _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); + return 0; +} + /** * iwl3945_eeprom_init - read EEPROM contents * @@ -2792,7 +2806,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, #endif /* drop all data frame if we are not associated */ - if (!iwl3945_is_associated(priv) && !priv->assoc_id && + if ((!iwl3945_is_associated(priv) || !priv->assoc_id) && ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); goto drop_unlock; @@ -4745,8 +4759,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) #ifdef CONFIG_IWL3945_DEBUG if (iwl3945_debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_MAC_CLK_ACTV) - IWL_DEBUG_ISR("Microcode started or stopped.\n"); + if (inta & CSR_INT_BIT_SCD) + IWL_DEBUG_ISR("Scheduler finished to transmit " + "the frame/frames.\n"); /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) @@ -4754,7 +4769,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) } #endif /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE); + inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); /* HW RF KILL switch toggled (4965 only) */ if (inta & CSR_INT_BIT_RF_KILL) { @@ -4890,8 +4905,11 @@ static irqreturn_t iwl3945_isr(int irq, void *data) IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); + inta &= ~CSR_INT_BIT_SCD; + /* iwl3945_irq_tasklet() will service interrupts and re-enable them */ - tasklet_schedule(&priv->irq_tasklet); + if (likely(inta || inta_fh)) + tasklet_schedule(&priv->irq_tasklet); unplugged: spin_unlock(&priv->lock); @@ -5146,6 +5164,15 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) return 0; } +/* + * iwl3945_free_channel_map - undo allocations in iwl3945_init_channel_map + */ +static void iwl3945_free_channel_map(struct iwl3945_priv *priv) +{ + kfree(priv->channel_info); + priv->channel_count = 0; +} + /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after * sending probe req. This should be set long enough to hear probe responses * from more than one AP. */ @@ -5471,6 +5498,17 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) return 0; } +/* + * iwl3945_free_geos - undo allocations in iwl3945_init_geos + */ +static void iwl3945_free_geos(struct iwl3945_priv *priv) +{ + kfree(priv->modes); + kfree(priv->ieee_channels); + kfree(priv->ieee_rates); + clear_bit(STATUS_GEO_CONFIGURED, &priv->status); +} + /****************************************************************************** * * uCode download functions @@ -6130,15 +6168,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) /* Clear out the uCode error bit if it is set */ clear_bit(STATUS_FW_ERROR, &priv->status); - rc = iwl3945_init_channel_map(priv); - if (rc) { - IWL_ERROR("initializing regulatory failed: %d\n", rc); - return; - } - - iwl3945_init_geos(priv); - iwl3945_reset_channel_flag(priv); - if (iwl3945_is_rfkill(priv)) return; @@ -6599,7 +6628,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) * that based on the direct_mask added to each channel entry */ scan->tx_cmd.len = cpu_to_le16( iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(scan), 0)); + IWL_MAX_SCAN_SIZE - sizeof(*scan), 0)); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; @@ -7120,7 +7149,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) { int rc = 0; - if (priv->status & STATUS_EXIT_PENDING) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* The following should be done only at AP bring up */ @@ -8614,11 +8643,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); + err = iwl3945_init_channel_map(priv); + if (err) { + IWL_ERROR("initializing regulatory failed: %d\n", err); + goto out_remove_sysfs; + } + + err = iwl3945_init_geos(priv); + if (err) { + IWL_ERROR("initializing geos failed: %d\n", err); + goto out_free_channel_map; + } + iwl3945_reset_channel_flag(priv); + iwl3945_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); if (err) { IWL_ERROR("Failed to register network device (error %d)\n", err); - goto out_remove_sysfs; + goto out_free_geos; } priv->hw->conf.beacon_int = 100; @@ -8628,6 +8670,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e return 0; + out_free_geos: + iwl3945_free_geos(priv); + out_free_channel_map: + iwl3945_free_channel_map(priv); out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); @@ -8702,10 +8748,8 @@ static void iwl3945_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - kfree(priv->channel_info); - - kfree(priv->ieee_channels); - kfree(priv->ieee_rates); + iwl3945_free_channel_map(priv); + iwl3945_free_geos(priv); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index c86da5c..bf3a60c 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1639,6 +1639,12 @@ static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac) memcpy(mac, priv->eeprom.mac_address, 6); } +static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv) +{ + iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); +} + /** * iwl4965_eeprom_init - read EEPROM contents * @@ -2927,8 +2933,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, #endif /* drop all data frame if we are not associated */ - if (!iwl4965_is_associated(priv) && !priv->assoc_id && - ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { + if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && + (!iwl4965_is_associated(priv) || + !priv->assoc_id || + !priv->assoc_station_added)) { IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n"); goto drop_unlock; } @@ -5131,8 +5139,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) #ifdef CONFIG_IWL4965_DEBUG if (iwl4965_debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_MAC_CLK_ACTV) - IWL_DEBUG_ISR("Microcode started or stopped.\n"); + if (inta & CSR_INT_BIT_SCD) + IWL_DEBUG_ISR("Scheduler finished to transmit " + "the frame/frames.\n"); /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) @@ -5140,7 +5149,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) } #endif /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE); + inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { @@ -5269,8 +5278,11 @@ static irqreturn_t iwl4965_isr(int irq, void *data) IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); + inta &= ~CSR_INT_BIT_SCD; + /* iwl4965_irq_tasklet() will service interrupts and re-enable them */ - tasklet_schedule(&priv->irq_tasklet); + if (likely(inta || inta_fh)) + tasklet_schedule(&priv->irq_tasklet); unplugged: spin_unlock(&priv->lock); @@ -5576,6 +5588,15 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) return 0; } +/* + * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map + */ +static void iwl4965_free_channel_map(struct iwl4965_priv *priv) +{ + kfree(priv->channel_info); + priv->channel_count = 0; +} + /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after * sending probe req. This should be set long enough to hear probe responses * from more than one AP. */ @@ -5909,6 +5930,17 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) return 0; } +/* + * iwl4965_free_geos - undo allocations in iwl4965_init_geos + */ +static void iwl4965_free_geos(struct iwl4965_priv *priv) +{ + kfree(priv->modes); + kfree(priv->ieee_channels); + kfree(priv->ieee_rates); + clear_bit(STATUS_GEO_CONFIGURED, &priv->status); +} + /****************************************************************************** * * uCode download functions @@ -6560,15 +6592,6 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv) /* Clear out the uCode error bit if it is set */ clear_bit(STATUS_FW_ERROR, &priv->status); - rc = iwl4965_init_channel_map(priv); - if (rc) { - IWL_ERROR("initializing regulatory failed: %d\n", rc); - return; - } - - iwl4965_init_geos(priv); - iwl4965_reset_channel_flag(priv); - if (iwl4965_is_rfkill(priv)) return; @@ -7023,7 +7046,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) * that based on the direct_mask added to each channel entry */ scan->tx_cmd.len = cpu_to_le16( iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(scan), 0)); + IWL_MAX_SCAN_SIZE - sizeof(*scan), 0)); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; @@ -7448,7 +7471,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw, if (priv->vif) { IWL_DEBUG_MAC80211("leave - vif != NULL\n"); - return 0; + return -EOPNOTSUPP; } spin_lock_irqsave(&priv->lock, flags); @@ -7580,7 +7603,7 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv) { int rc = 0; - if (priv->status & STATUS_EXIT_PENDING) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* The following should be done only at AP bring up */ @@ -9198,11 +9221,24 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); + err = iwl4965_init_channel_map(priv); + if (err) { + IWL_ERROR("initializing regulatory failed: %d\n", err); + goto out_remove_sysfs; + } + + err = iwl4965_init_geos(priv); + if (err) { + IWL_ERROR("initializing geos failed: %d\n", err); + goto out_free_channel_map; + } + iwl4965_reset_channel_flag(priv); + iwl4965_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); if (err) { IWL_ERROR("Failed to register network device (error %d)\n", err); - goto out_remove_sysfs; + goto out_free_geos; } priv->hw->conf.beacon_int = 100; @@ -9212,6 +9248,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e return 0; + out_free_geos: + iwl4965_free_geos(priv); + out_free_channel_map: + iwl4965_free_channel_map(priv); out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); @@ -9286,10 +9326,8 @@ static void iwl4965_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - kfree(priv->channel_info); - - kfree(priv->ieee_channels); - kfree(priv->ieee_rates); + iwl4965_free_channel_map(priv); + iwl4965_free_geos(priv); if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index c622e9b..87e145f 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -12,8 +12,10 @@ #include "cmd.h" -static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static int assoc_helper_essid(struct lbs_private *priv, diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 58d7ef6..5a69f2b 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -349,7 +349,7 @@ struct assoc_request { u8 channel; u8 band; u8 mode; - u8 bssid[ETH_ALEN]; + u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); /** WEP keys */ struct enc_key wep_keys[4]; diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 4b5ab9a..5a9cadb 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -249,14 +249,14 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) lbs_deb_enter(LBS_DEB_CS); int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); - if(int_cause == 0x0) { + if (int_cause == 0x0) { /* Not for us */ return IRQ_NONE; } else if (int_cause == 0xffff) { /* Read in junk, the card has probably been removed */ card->priv->surpriseremoved = 1; - + return IRQ_HANDLED; } else { if (int_cause & IF_CS_H_IC_TX_OVER) lbs_host_to_card_done(card->priv); @@ -717,8 +717,8 @@ static void if_cs_release(struct pcmcia_device *p_dev) lbs_deb_enter(LBS_DEB_CS); - pcmcia_disable_device(p_dev); free_irq(p_dev->irq.AssignedIRQ, card); + pcmcia_disable_device(p_dev); if (card->iobase) ioport_unmap(card->iobase); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index ab52f22..b31f0c2 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1736,7 +1736,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) WARNING(rt2x00dev, "TX status report missed for entry %p\n", entry_done); - rt2x00lib_txdone(entry_done, TX_FAIL_OTHER, 0); + rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER, + 0); entry_done = rt2x00_get_data_entry_done(ring); } diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index 07f37b0..27ebd68 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -36,6 +36,7 @@ MODULE_LICENSE("GPL"); static struct pci_device_id rtl8180_table[] __devinitdata = { /* rtl8185 */ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, + { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) }, /* rtl8180 */ diff --git a/include/linux/input.h b/include/linux/input.h index 2075d6d..056a17a 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -371,6 +371,8 @@ struct input_absinfo { #define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */ #define KEY_DISPLAY_OFF 245 /* display device to off state */ +#define KEY_WIMAX 246 + #define BTN_MISC 0x100 #define BTN_0 0x100 #define BTN_1 0x101 diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 0ce5e0b..e3ab21d 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -33,11 +33,13 @@ * RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device. * RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. * RFKILL_TYPE_UWB: switch is on a ultra wideband device. + * RFKILL_TYPE_WIMAX: switch is on a WiMAX device. */ enum rfkill_type { RFKILL_TYPE_WLAN , RFKILL_TYPE_BLUETOOTH, RFKILL_TYPE_UWB, + RFKILL_TYPE_WIMAX, RFKILL_TYPE_MAX, }; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 89e1e30..d44c872 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -340,9 +340,42 @@ static u32 ieee80211_rx_load_stats(struct ieee80211_local *local, return load; } +static ieee80211_txrx_result +ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx) +{ + int hdrlen; + + /* + * Drivers are required to align the payload data in a way that + * guarantees that the contained IP header is aligned to a four- + * byte boundary. In the case of regular frames, this simply means + * aligning the payload to a four-byte boundary (because either + * the IP header is directly contained, or IV/RFC1042 headers that + * have a length divisible by four are in front of it. + * + * With A-MSDU frames, however, the payload data address must + * yield two modulo four because there are 14-byte 802.3 headers + * within the A-MSDU frames that push the IP header further back + * to a multiple of four again. Thankfully, the specs were sane + * enough this time around to require padding each A-MSDU subframe + * to a length that is a multiple of four. + * + * Padding like atheros hardware adds which is inbetween the 802.11 + * header and the payload is not supported, the driver is required + * to move the 802.11 header further back in that case. + */ + hdrlen = ieee80211_get_hdrlen(rx->fc); + if (rx->flags & IEEE80211_TXRXD_RX_AMSDU) + hdrlen += ETH_HLEN; + WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3); + + return TXRX_CONTINUE; +} + ieee80211_rx_handler ieee80211_rx_pre_handlers[] = { ieee80211_rx_h_parse_qos, + ieee80211_rx_h_verify_ip_alignment, NULL }; @@ -1679,7 +1712,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct ieee80211_sub_if_data *prev = NULL; struct sk_buff *skb_new; u8 *bssid; - int hdrlen; hdr = (struct ieee80211_hdr *) skb->data; memset(&rx, 0, sizeof(rx)); @@ -1691,18 +1723,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, rx.fc = le16_to_cpu(hdr->frame_control); type = rx.fc & IEEE80211_FCTL_FTYPE; - /* - * Drivers are required to align the payload data to a four-byte - * boundary, so the last two bits of the address where it starts - * may not be set. The header is required to be directly before - * the payload data, padding like atheros hardware adds which is - * inbetween the 802.11 header and the payload is not supported, - * the driver is required to move the 802.11 header further back - * in that case. - */ - hdrlen = ieee80211_get_hdrlen(rx.fc); - WARN_ON_ONCE(((unsigned long)(skb->data + hdrlen)) & 3); - if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) local->dot11ReceivedFragmentCount++; @@ -1952,7 +1972,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, goto end_reorder; /* null data frames are excluded */ - if (unlikely(fc & IEEE80211_STYPE_QOS_NULLFUNC)) + if (unlikely(fc & IEEE80211_STYPE_NULLFUNC)) goto end_reorder; /* new un-ordered ampdu frame - process it */ diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index d1e9d68..e4b051d 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c @@ -84,6 +84,7 @@ static void rfkill_schedule_toggle(struct rfkill_task *task) static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN); static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH); static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); +static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); static void rfkill_event(struct input_handle *handle, unsigned int type, unsigned int code, int down) @@ -99,6 +100,9 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, case KEY_UWB: rfkill_schedule_toggle(&rfkill_uwb); break; + case KEY_WIMAX: + rfkill_schedule_toggle(&rfkill_wimax); + break; default: break; } @@ -159,6 +163,11 @@ static const struct input_device_id rfkill_ids[] = { .evbit = { BIT_MASK(EV_KEY) }, .keybit = { [BIT_WORD(KEY_UWB)] = BIT_MASK(KEY_UWB) }, }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) }, + }, { } }; diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index d06d338..6562f86 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -126,6 +126,9 @@ static ssize_t rfkill_type_show(struct device *dev, case RFKILL_TYPE_UWB: type = "ultrawideband"; break; + case RFKILL_TYPE_WIMAX: + type = "wimax"; + break; default: BUG(); } -- John W. Linville linville@xxxxxxxxxxxxx - To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html