--- linux-2.6.18.noarch/include/net/ieee80211.h.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/include/net/ieee80211.h 2008-08-12 17:06:50.000000000 -0400 @@ -680,7 +680,11 @@ struct ieee80211_probe_response { struct ieee80211_hdr_3addr header; +#ifndef __GENKSYMS__ __le32 time_stamp[2]; +#else + u32 time_stamp[2]; +#endif __le16 beacon_interval; __le16 capability; /* SSID, supported rates, FH params, DS params, @@ -721,8 +725,13 @@ u8 encrypted; u8 rts_included; u8 reserved; +#ifndef __GENKSYMS__ u16 frag_size; u16 payload_size; +#else + __le16 frag_size; + __le16 payload_size; +#endif struct sk_buff *fragments[0]; }; @@ -1043,10 +1052,6 @@ /* host performs multicast decryption */ int host_mc_decrypt; - /* host should strip IV and ICV from protected frames */ - /* meaningful only when hardware decryption is being used */ - int host_strip_iv_icv; - int host_open_frag; int host_build_iv; int ieee802_1x; /* is IEEE 802.1X used */ @@ -1086,8 +1091,6 @@ int perfect_rssi; int worst_rssi; - u16 prev_seq_ctl; /* used to drop duplicate frames */ - /* Callback functions */ void (*set_security) (struct net_device * dev, struct ieee80211_security * sec); --- linux-2.6.18.noarch/include/net/ieee80211softmac.h.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/include/net/ieee80211softmac.h 2008-08-12 17:06:50.000000000 -0400 @@ -63,11 +63,13 @@ /* * Information about association + * + * Do we need a lock for this? + * We only ever use this structure inlined + * into our global struct. I've used its lock, + * but maybe we need a local one here? */ struct ieee80211softmac_assoc_info { - - struct mutex mutex; - /* * This is the requested ESSID. It is written * only by the WX handlers. @@ -84,6 +86,9 @@ /* BSSID we're trying to associate to */ char bssid[ETH_ALEN]; + + /* Rates supported by the network */ + struct ieee80211softmac_ratesinfo supported_rates; /* some flags. * static_essid is valid if the essid is constant, @@ -97,13 +102,11 @@ * * bssfixed is used for SIOCSIWAP. */ - u8 static_essid; - u8 short_preamble_available; - u8 associating; - u8 associated; - u8 assoc_wait; - u8 bssvalid; - u8 bssfixed; + u8 static_essid:1, + associating:1, + assoc_wait:1, + bssvalid:1, + bssfixed:1; /* Scan retries remaining */ int scan_retry; @@ -112,19 +115,6 @@ struct work_struct timeout; }; -struct ieee80211softmac_bss_info { - /* Rates supported by the network */ - struct ieee80211softmac_ratesinfo supported_rates; - - /* This indicates whether frames can currently be transmitted with - * short preamble (only use this variable during TX at CCK rates) */ - u8 short_preamble:1; - - /* This indicates whether protection (e.g. self-CTS) should be used - * when transmitting with OFDM modulation */ - u8 use_protection:1; -}; - enum { IEEE80211SOFTMAC_AUTH_OPEN_REQUEST = 1, IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE = 2, @@ -167,10 +157,6 @@ #define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */ #define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST (1 << 3) /* mgt_mcast_rate */ -#define IEEE80211SOFTMAC_BSSINFOCHG_RATES (1 << 0) /* supported_rates */ -#define IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE (1 << 1) /* short_preamble */ -#define IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION (1 << 2) /* use_protection */ - struct ieee80211softmac_device { /* 802.11 structure for data stuff */ struct ieee80211_device *ieee; @@ -214,29 +200,22 @@ * The driver just needs to read them. */ struct ieee80211softmac_txrates txrates; - - /* If the driver needs to do stuff on TX rate changes, assign this - * callback. See IEEE80211SOFTMAC_TXRATECHG for change flags. */ + /* If the driver needs to do stuff on TX rate changes, assign this callback. */ void (*txrates_change)(struct net_device *dev, - u32 changes); - - /* If the driver needs to do stuff when BSS properties change, assign - * this callback. see IEEE80211SOFTMAC_BSSINFOCHG for change flags. */ - void (*bssinfo_change)(struct net_device *dev, - u32 changes); + u32 changes, /* see IEEE80211SOFTMAC_TXRATECHG flags */ + const struct ieee80211softmac_txrates *rates_before_change); /* private stuff follows */ /* this lock protects this structure */ spinlock_t lock; - - struct workqueue_struct *wq; - - u8 running; /* SoftMAC started? */ - u8 scanning; - + + /* couple of flags */ + u8 scanning:1, /* protects scanning from being done multiple times at once */ + associated:1, + running:1; + struct ieee80211softmac_scaninfo *scaninfo; struct ieee80211softmac_assoc_info associnfo; - struct ieee80211softmac_bss_info bssinfo; struct list_head auth_queue; struct list_head events; @@ -249,7 +228,7 @@ /* we need to keep a list of network structs we copied */ struct list_head network_list; - + /* This must be the last item so that it points to the data * allocated beyond this structure by alloc_ieee80211 */ u8 priv[0]; @@ -294,7 +273,7 @@ { struct ieee80211softmac_txrates *txrates = &mac->txrates; - if (!mac->associnfo.associated) + if (!mac->associated) return txrates->mgt_mcast_rate; /* We are associated, sending unicast frame */ @@ -308,24 +287,6 @@ return txrates->mcast_rate; } -/* Helper function which advises you when it is safe to transmit with short - * preamble. - * You should only call this function when transmitting at CCK rates. */ -static inline int ieee80211softmac_short_preamble_ok(struct ieee80211softmac_device *mac, - int is_multicast, - int is_mgt) -{ - return (is_multicast && is_mgt) ? 0 : mac->bssinfo.short_preamble; -} - -/* Helper function which advises you whether protection (e.g. self-CTS) is - * needed. 1 = protection needed, 0 = no protection needed - * Only use this function when transmitting with OFDM modulation. */ -static inline int ieee80211softmac_protection_needed(struct ieee80211softmac_device *mac) -{ - return mac->bssinfo.use_protection; -} - /* Start the SoftMAC. Call this after you initialized the device * and it is ready to run. */ --- linux-2.6.18.noarch/drivers/net/wireless/bcm43xx/bcm43xx_wx.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2008-08-12 17:06:50.000000000 -0400 @@ -695,7 +695,6 @@ bcm->ieee->host_encrypt = !!on; bcm->ieee->host_decrypt = !!on; bcm->ieee->host_build_iv = !on; - bcm->ieee->host_strip_iv_icv = !on; spin_unlock_irqrestore(&bcm->irq_lock, flags); mutex_unlock(&bcm->mutex); @@ -850,7 +849,7 @@ unsigned long flags; wstats = &bcm->stats.wstats; - if (!mac->associnfo.associated) { + if (!mac->associated) { wstats->miss.beacon = 0; // bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here? wstats->discard.retries = 0; --- linux-2.6.18.noarch/drivers/net/wireless/bcm43xx/bcm43xx_leds.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/drivers/net/wireless/bcm43xx/bcm43xx_leds.c 2008-08-12 17:06:50.000000000 -0400 @@ -249,7 +249,7 @@ //TODO break; case BCM43xx_LED_ASSOC: - if (bcm->softmac->associnfo.associated) + if (bcm->softmac->associated) turn_on = 1; break; #ifdef CONFIG_BCM43XX_DEBUG --- linux-2.6.18.noarch/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c 2008-08-12 17:06:50.000000000 -0400 @@ -544,6 +544,24 @@ } frame_ctl = le16_to_cpu(wlhdr->frame_ctl); + if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { + frame_ctl &= ~IEEE80211_FCTL_PROTECTED; + wlhdr->frame_ctl = cpu_to_le16(frame_ctl); + /* trim IV and ICV */ + /* FIXME: this must be done only for WEP encrypted packets */ + if (skb->len < 32) { + dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " + "set and length < 32)\n"); + return -EINVAL; + } else { + memmove(skb->data + 4, skb->data, 24); + skb_pull(skb, 4); + skb_trim(skb, skb->len - 4); + stats.len -= 8; + } + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); + } + switch (WLAN_FC_GET_TYPE(frame_ctl)) { case IEEE80211_FTYPE_MGMT: ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); --- linux-2.6.18.noarch/drivers/net/wireless/zd1211rw/zd_chip.h.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/drivers/net/wireless/zd1211rw/zd_chip.h 2008-08-12 17:06:50.000000000 -0400 @@ -459,15 +459,6 @@ #define CR_MANDATORY_RATE_TBL CTL_REG(0x0634) #define CR_RTS_CTS_RATE CTL_REG(0x0638) -/* These are all bit indexes in CR_RTS_CTS_RATE, so remember to shift. */ -#define RTSCTS_SH_RTS_RATE 0 -#define RTSCTS_SH_EXP_CTS_RATE 4 -#define RTSCTS_SH_RTS_MOD_TYPE 8 -#define RTSCTS_SH_RTS_PMB_TYPE 9 -#define RTSCTS_SH_CTS_RATE 16 -#define RTSCTS_SH_CTS_MOD_TYPE 24 -#define RTSCTS_SH_CTS_PMB_TYPE 25 - #define CR_WEP_PROTECT CTL_REG(0x063C) #define CR_RX_THRESHOLD CTL_REG(0x0640) @@ -841,9 +832,6 @@ int zd_chip_disable_hwint(struct zd_chip *chip); int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel); -int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, - u8 rts_rate, int preamble); - static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type) { return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type); @@ -859,17 +847,7 @@ return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates); } -int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates); - -static inline int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_chip_set_basic_rates_locked(chip, cr_rates); - mutex_unlock(&chip->mutex); - return r; -} +int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates); int zd_chip_lock_phy_regs(struct zd_chip *chip); int zd_chip_unlock_phy_regs(struct zd_chip *chip); --- linux-2.6.18.noarch/drivers/net/wireless/zd1211rw/zd_mac.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/drivers/net/wireless/zd1211rw/zd_mac.c 2008-08-12 17:06:50.000000000 -0400 @@ -33,8 +33,6 @@ static void ieee_init(struct ieee80211_device *ieee); static void softmac_init(struct ieee80211softmac_device *sm); -static void set_rts_cts_work(struct zd_mac *mac); -static void set_basic_rates_work(struct zd_mac *mac); static void housekeeping_init(struct zd_mac *mac); static void housekeeping_enable(struct zd_mac *mac); @@ -53,10 +51,6 @@ memset(mac, 0, sizeof(*mac)); spin_lock_init(&mac->lock); mac->netdev = netdev; - INIT_WORK(&mac->set_rts_cts_work, - (void (*)(void *))set_rts_cts_work, mac); - INIT_WORK(&mac->set_basic_rates_work, - (void (*)(void *))set_basic_rates_work, mac); skb_queue_head_init(&mac->rx_queue); tasklet_init(&mac->rx_tasklet, do_rx, (unsigned long)mac); @@ -272,13 +266,6 @@ housekeeping_disable(mac); ieee80211softmac_stop(netdev); - /* Ensure no work items are running or queued from this point */ - cancel_delayed_work(&mac->set_rts_cts_work); - cancel_delayed_work(&mac->set_basic_rates_work); - flush_workqueue(zd_workqueue); - mac->updating_rts_rate = 0; - mac->updating_basic_rates = 0; - zd_chip_disable_hwint(chip); zd_chip_switch_radio_off(chip); zd_chip_disable_int(chip); @@ -391,185 +378,6 @@ return regdomain; } -/* Fallback to lowest rate, if rate is unknown. */ -static u8 rate_to_zd_rate(u8 rate) -{ - switch (rate) { - case IEEE80211_CCK_RATE_2MB: - return ZD_CCK_RATE_2M; - case IEEE80211_CCK_RATE_5MB: - return ZD_CCK_RATE_5_5M; - case IEEE80211_CCK_RATE_11MB: - return ZD_CCK_RATE_11M; - case IEEE80211_OFDM_RATE_6MB: - return ZD_OFDM_RATE_6M; - case IEEE80211_OFDM_RATE_9MB: - return ZD_OFDM_RATE_9M; - case IEEE80211_OFDM_RATE_12MB: - return ZD_OFDM_RATE_12M; - case IEEE80211_OFDM_RATE_18MB: - return ZD_OFDM_RATE_18M; - case IEEE80211_OFDM_RATE_24MB: - return ZD_OFDM_RATE_24M; - case IEEE80211_OFDM_RATE_36MB: - return ZD_OFDM_RATE_36M; - case IEEE80211_OFDM_RATE_48MB: - return ZD_OFDM_RATE_48M; - case IEEE80211_OFDM_RATE_54MB: - return ZD_OFDM_RATE_54M; - } - return ZD_CCK_RATE_1M; -} - -static u16 rate_to_cr_rate(u8 rate) -{ - switch (rate) { - case IEEE80211_CCK_RATE_2MB: - return CR_RATE_1M; - case IEEE80211_CCK_RATE_5MB: - return CR_RATE_5_5M; - case IEEE80211_CCK_RATE_11MB: - return CR_RATE_11M; - case IEEE80211_OFDM_RATE_6MB: - return CR_RATE_6M; - case IEEE80211_OFDM_RATE_9MB: - return CR_RATE_9M; - case IEEE80211_OFDM_RATE_12MB: - return CR_RATE_12M; - case IEEE80211_OFDM_RATE_18MB: - return CR_RATE_18M; - case IEEE80211_OFDM_RATE_24MB: - return CR_RATE_24M; - case IEEE80211_OFDM_RATE_36MB: - return CR_RATE_36M; - case IEEE80211_OFDM_RATE_48MB: - return CR_RATE_48M; - case IEEE80211_OFDM_RATE_54MB: - return CR_RATE_54M; - } - return CR_RATE_1M; -} - -static void try_enable_tx(struct zd_mac *mac) -{ - unsigned long flags; - - spin_lock_irqsave(&mac->lock, flags); - if (mac->updating_rts_rate == 0 && mac->updating_basic_rates == 0) - netif_wake_queue(mac->netdev); - spin_unlock_irqrestore(&mac->lock, flags); -} - -static void set_rts_cts_work(struct zd_mac *mac) -{ - unsigned long flags; - u8 rts_rate; - unsigned int short_preamble; - - mutex_lock(&mac->chip.mutex); - - spin_lock_irqsave(&mac->lock, flags); - mac->updating_rts_rate = 0; - rts_rate = mac->rts_rate; - short_preamble = mac->short_preamble; - spin_unlock_irqrestore(&mac->lock, flags); - - zd_chip_set_rts_cts_rate_locked(&mac->chip, rts_rate, short_preamble); - mutex_unlock(&mac->chip.mutex); - - try_enable_tx(mac); -} - -static void set_basic_rates_work(struct zd_mac *mac) -{ - unsigned long flags; - u16 basic_rates; - - mutex_lock(&mac->chip.mutex); - - spin_lock_irqsave(&mac->lock, flags); - mac->updating_basic_rates = 0; - basic_rates = mac->basic_rates; - spin_unlock_irqrestore(&mac->lock, flags); - - zd_chip_set_basic_rates_locked(&mac->chip, basic_rates); - mutex_unlock(&mac->chip.mutex); - - try_enable_tx(mac); -} - -static void bssinfo_change(struct net_device *netdev, u32 changes) -{ - struct zd_mac *mac = zd_netdev_mac(netdev); - struct ieee80211softmac_device *softmac = ieee80211_priv(netdev); - struct ieee80211softmac_bss_info *bssinfo = &softmac->bssinfo; - int need_set_rts_cts = 0; - int need_set_rates = 0; - u16 basic_rates; - unsigned long flags; - - dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); - - if (changes & IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE) { - spin_lock_irqsave(&mac->lock, flags); - mac->short_preamble = bssinfo->short_preamble; - spin_unlock_irqrestore(&mac->lock, flags); - need_set_rts_cts = 1; - } - - if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) { - /* Set RTS rate to highest available basic rate */ - u8 hi_rate = ieee80211softmac_highest_supported_rate(softmac, - &bssinfo->supported_rates, 1); - hi_rate = rate_to_zd_rate(hi_rate); - - spin_lock_irqsave(&mac->lock, flags); - if (hi_rate != mac->rts_rate) { - mac->rts_rate = hi_rate; - need_set_rts_cts = 1; - } - spin_unlock_irqrestore(&mac->lock, flags); - - /* Set basic rates */ - need_set_rates = 1; - if (bssinfo->supported_rates.count == 0) { - /* Allow the device to be flexible */ - basic_rates = CR_RATES_80211B | CR_RATES_80211G; - } else { - int i = 0; - basic_rates = 0; - - for (i = 0; i < bssinfo->supported_rates.count; i++) { - u16 rate = bssinfo->supported_rates.rates[i]; - if ((rate & IEEE80211_BASIC_RATE_MASK) == 0) - continue; - - rate &= ~IEEE80211_BASIC_RATE_MASK; - basic_rates |= rate_to_cr_rate(rate); - } - } - spin_lock_irqsave(&mac->lock, flags); - mac->basic_rates = basic_rates; - spin_unlock_irqrestore(&mac->lock, flags); - } - - /* Schedule any changes we made above */ - - spin_lock_irqsave(&mac->lock, flags); - if (need_set_rts_cts && !mac->updating_rts_rate) { - mac->updating_rts_rate = 1; - netif_stop_queue(mac->netdev); - queue_delayed_work(zd_workqueue, &mac->set_rts_cts_work, 0); - } - if (need_set_rates && !mac->updating_basic_rates) { - mac->updating_basic_rates = 1; - netif_stop_queue(mac->netdev); - queue_delayed_work(zd_workqueue, &mac->set_basic_rates_work, - 0); - } - spin_unlock_irqrestore(&mac->lock, flags); -} - static void set_channel(struct net_device *netdev, u8 channel) { struct zd_mac *mac = zd_netdev_mac(netdev); @@ -608,6 +416,36 @@ return channel; } +/* Fallback to lowest rate, if rate is unknown. */ +static u8 rate_to_zd_rate(u8 rate) +{ + switch (rate) { + case IEEE80211_CCK_RATE_2MB: + return ZD_CCK_RATE_2M; + case IEEE80211_CCK_RATE_5MB: + return ZD_CCK_RATE_5_5M; + case IEEE80211_CCK_RATE_11MB: + return ZD_CCK_RATE_11M; + case IEEE80211_OFDM_RATE_6MB: + return ZD_OFDM_RATE_6M; + case IEEE80211_OFDM_RATE_9MB: + return ZD_OFDM_RATE_9M; + case IEEE80211_OFDM_RATE_12MB: + return ZD_OFDM_RATE_12M; + case IEEE80211_OFDM_RATE_18MB: + return ZD_OFDM_RATE_18M; + case IEEE80211_OFDM_RATE_24MB: + return ZD_OFDM_RATE_24M; + case IEEE80211_OFDM_RATE_36MB: + return ZD_OFDM_RATE_36M; + case IEEE80211_OFDM_RATE_48MB: + return ZD_OFDM_RATE_48M; + case IEEE80211_OFDM_RATE_54MB: + return ZD_OFDM_RATE_54M; + } + return ZD_CCK_RATE_1M; +} + int zd_mac_set_mode(struct zd_mac *mac, u32 mode) { struct ieee80211_device *ieee; @@ -768,32 +606,35 @@ u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); u8 rate; int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; - int is_multicast = is_multicast_ether_addr(hdr->addr1); - int short_preamble = ieee80211softmac_short_preamble_ok(softmac, - is_multicast, is_mgt); - - rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt); - cs->modulation = rate_to_zd_rate(rate); - - /* Set short preamble bit when appropriate */ - if (short_preamble && ZD_MODULATION_TYPE(cs->modulation) == ZD_CCK - && cs->modulation != ZD_CCK_RATE_1M) - cs->modulation |= ZD_CCK_PREA_SHORT; + + /* FIXME: 802.11a? short preamble? */ + rate = ieee80211softmac_suggest_txrate(softmac, + is_multicast_ether_addr(hdr->addr1), is_mgt); + cs->modulation = rate_to_zd_rate(rate);; } static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, struct ieee80211_hdr_4addr *header) { - struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); unsigned int tx_length = le16_to_cpu(cs->tx_length); u16 fctl = le16_to_cpu(header->frame_ctl); u16 ftype = WLAN_FC_GET_TYPE(fctl); u16 stype = WLAN_FC_GET_STYPE(fctl); /* - * CONTROL TODO: + * CONTROL: + * - start at 0x00 + * - if fragment 0, enable bit 0 * - if backoff needed, enable bit 0 * - if burst (backoff not needed) disable bit 0 + * - if multicast, enable bit 1 + * - if PS-POLL frame, enable bit 2 + * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable + * bit 4 (FIXME: wtf) + * - if frag_len > RTS threshold, set bit 5 as long if it isnt + * multicast or mgt + * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit + * 7 */ cs->control = 0; @@ -810,18 +651,17 @@ if (ftype == IEEE80211_FTYPE_CTL && stype == IEEE80211_STYPE_PSPOLL) cs->control |= ZD_CS_PS_POLL_FRAME; - /* Unicast data frames over the threshold should have RTS */ if (!is_multicast_ether_addr(header->addr1) && - ftype != IEEE80211_FTYPE_MGMT && - tx_length > zd_netdev_ieee80211(mac->netdev)->rts) - cs->control |= ZD_CS_RTS; - - /* Use CTS-to-self protection if required */ - if (ZD_MODULATION_TYPE(cs->modulation) == ZD_OFDM && - ieee80211softmac_protection_needed(softmac)) { - /* FIXME: avoid sending RTS *and* self-CTS, is that correct? */ - cs->control &= ~ZD_CS_RTS; - cs->control |= ZD_CS_SELF_CTS; + ftype != IEEE80211_FTYPE_MGMT && + tx_length > zd_netdev_ieee80211(mac->netdev)->rts) + { + /* FIXME: check the logic */ + if (ZD_MODULATION_TYPE(cs->modulation) == ZD_OFDM) { + /* 802.11g */ + cs->control |= ZD_CS_SELF_CTS; + } else { /* 802.11b */ + cs->control |= ZD_CS_RTS; + } } /* FIXME: Management frame? */ @@ -1262,7 +1102,6 @@ static void softmac_init(struct ieee80211softmac_device *sm) { sm->set_channel = set_channel; - sm->bssinfo_change = bssinfo_change; } struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) @@ -1308,7 +1147,7 @@ int r; spin_lock_irq(&mac->lock); - is_associated = sm->associnfo.associated != 0; + is_associated = sm->associated != 0; spin_unlock_irq(&mac->lock); r = zd_chip_control_leds(chip, --- linux-2.6.18.noarch/drivers/net/wireless/zd1211rw/zd_chip.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/drivers/net/wireless/zd1211rw/zd_chip.c 2008-08-12 17:06:50.000000000 -0400 @@ -1001,31 +1001,6 @@ return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); } -int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, - u8 rts_rate, int preamble) -{ - int rts_mod = ZD_RX_CCK; - u32 value = 0; - - /* Modulation bit */ - if (ZD_MODULATION_TYPE(rts_rate) == ZD_OFDM) - rts_mod = ZD_RX_OFDM; - - dev_dbg_f(zd_chip_dev(chip), "rts_rate=%x preamble=%x\n", - rts_rate, preamble); - - value |= ZD_PURE_RATE(rts_rate) << RTSCTS_SH_RTS_RATE; - value |= rts_mod << RTSCTS_SH_RTS_MOD_TYPE; - value |= preamble << RTSCTS_SH_RTS_PMB_TYPE; - value |= preamble << RTSCTS_SH_CTS_PMB_TYPE; - - /* We always send 11M self-CTS messages, like the vendor driver. */ - value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_CTS_RATE; - value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE; - - return zd_iowrite32_locked(chip, value, CR_RTS_CTS_RATE); -} - int zd_chip_enable_hwint(struct zd_chip *chip) { int r; @@ -1319,12 +1294,17 @@ return r; } -int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates) +int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) { - ZD_ASSERT((cr_rates & ~(CR_RATES_80211B | CR_RATES_80211G)) == 0); - dev_dbg_f(zd_chip_dev(chip), "%x\n", cr_rates); + int r; + + if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G)) + return -EINVAL; - return zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); + mutex_lock(&chip->mutex); + r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); + mutex_unlock(&chip->mutex); + return r; } static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size) --- linux-2.6.18.noarch/drivers/net/wireless/zd1211rw/zd_mac.h.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/drivers/net/wireless/zd1211rw/zd_mac.h 2008-08-12 17:06:50.000000000 -0400 @@ -20,7 +20,6 @@ #include #include -#include #include #include @@ -151,16 +150,11 @@ struct zd_chip chip; spinlock_t lock; struct net_device *netdev; - /* Unlocked reading possible */ struct iw_statistics iw_stats; - struct housekeeping housekeeping; struct work_struct set_multicast_hash_work; struct zd_mc_hash multicast_hash; - struct work_struct set_rts_cts_work; - struct work_struct set_basic_rates_work; - struct tasklet_struct rx_tasklet; struct sk_buff_head rx_queue; @@ -170,19 +164,6 @@ u8 regdomain; u8 default_regdomain; u8 requested_channel; - - /* A bitpattern of cr_rates */ - u16 basic_rates; - - /* A zd_rate */ - u8 rts_rate; - - /* Short preamble (used for RTS/CTS) */ - unsigned int short_preamble:1; - - /* flags to indicate update in progress */ - unsigned int updating_rts_rate:1; - unsigned int updating_basic_rates:1; }; static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac) --- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_auth.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_auth.c 2008-08-12 17:06:50.000000000 -0400 @@ -62,7 +62,7 @@ /* add to list */ list_add_tail(&auth->list, &mac->auth_queue); - queue_delayed_work(mac->wq, &auth->work, 0); + schedule_delayed_work(&auth->work, 0); spin_unlock_irqrestore(&mac->lock, flags); return 0; @@ -95,7 +95,7 @@ } net->authenticated = 0; /* add a timeout call so we eventually give up waiting for an auth reply */ - queue_delayed_work(mac->wq, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); + schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); auth->retry--; spin_unlock_irqrestore(&mac->lock, flags); if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state)) @@ -237,7 +237,7 @@ * request. */ cancel_delayed_work(&aq->work); INIT_WORK(&aq->work, &ieee80211softmac_auth_challenge_response, (void *)aq); - queue_delayed_work(mac->wq, &aq->work, 0); + schedule_delayed_work(&aq->work, 0); spin_unlock_irqrestore(&mac->lock, flags); return 0; case IEEE80211SOFTMAC_AUTH_SHARED_PASS: @@ -402,6 +402,6 @@ ieee80211softmac_deauth_from_net(mac, net); /* let's try to re-associate */ - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); + schedule_delayed_work(&mac->associnfo.work, 0); return 0; } --- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_module.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_module.c 2008-08-12 17:06:50.000000000 -0400 @@ -37,15 +37,6 @@ if (!dev) return NULL; softmac = ieee80211_priv(dev); -#if 0 /* Not in RHEL5... */ - softmac->wq = create_freezeable_workqueue("softmac"); -#else - softmac->wq = create_workqueue("softmac"); -#endif - if (!softmac->wq) { - free_ieee80211(dev); - return NULL; - } softmac->dev = dev; softmac->ieee = netdev_priv(dev); @@ -56,7 +47,6 @@ softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response; softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req; softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; - softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon; softmac->scaninfo = NULL; softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; @@ -69,7 +59,6 @@ INIT_LIST_HEAD(&softmac->network_list); INIT_LIST_HEAD(&softmac->events); - mutex_init(&softmac->associnfo.mutex); INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac); INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac); softmac->start_scan = ieee80211softmac_start_scan_implementation; @@ -114,7 +103,7 @@ cancel_delayed_work(&eventptr->work); spin_unlock_irqrestore(&sm->lock, flags); - flush_workqueue(sm->wq); + flush_scheduled_work(); /* now we should be save and no longer need locking... */ spin_lock_irqsave(&sm->lock, flags); @@ -148,7 +137,6 @@ ieee80211softmac_clear_pending_work(sm); kfree(sm->scaninfo); kfree(sm->wpa.IE); - destroy_workqueue(sm->wq); free_ieee80211(dev); } EXPORT_SYMBOL_GPL(free_ieee80211softmac); @@ -218,59 +206,35 @@ } EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate); -void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac, - u8 erp_value) -{ - int use_protection; - int short_preamble; - u32 changes = 0; - - /* Barker preamble mode */ - short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0 - && mac->associnfo.short_preamble_available) ? 1 : 0; - - /* Protection needed? */ - use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; - - if (mac->bssinfo.short_preamble != short_preamble) { - changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE; - mac->bssinfo.short_preamble = short_preamble; - } - - if (mac->bssinfo.use_protection != use_protection) { - changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION; - mac->bssinfo.use_protection = use_protection; - } - - if (mac->bssinfo_change && changes) - mac->bssinfo_change(mac->dev, changes); -} - void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac) { struct ieee80211softmac_txrates *txrates = &mac->txrates; + struct ieee80211softmac_txrates oldrates; u32 change = 0; + if (mac->txrates_change) + oldrates = mac->txrates; + change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; - txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0); + txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->associnfo.supported_rates, 0); change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; txrates->default_fallback = lower_rate(mac, txrates->default_rate); change |= IEEE80211SOFTMAC_TXRATECHG_MCAST; - txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1); + txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->associnfo.supported_rates, 1); if (mac->txrates_change) - mac->txrates_change(mac->dev, change); + mac->txrates_change(mac->dev, change, &oldrates); } -void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac) +void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac) { struct ieee80211_device *ieee = mac->ieee; u32 change = 0; struct ieee80211softmac_txrates *txrates = &mac->txrates; - struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo; + struct ieee80211softmac_txrates oldrates; /* TODO: We need some kind of state machine to lower the default rates * if we loose too many packets. @@ -278,6 +242,8 @@ /* Change the default txrate to the highest possible value. * The txrate machine will lower it, if it is too high. */ + if (mac->txrates_change) + oldrates = mac->txrates; if (ieee->modulation & IEEE80211_OFDM_MODULATION) txrates->user_rate = IEEE80211_OFDM_RATE_24MB; else @@ -296,23 +262,7 @@ change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST; if (mac->txrates_change) - mac->txrates_change(mac->dev, change); - - change = 0; - - bssinfo->supported_rates.count = 0; - memset(bssinfo->supported_rates.rates, 0, - sizeof(bssinfo->supported_rates.rates)); - change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES; - - bssinfo->short_preamble = 0; - change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE; - - bssinfo->use_protection = 0; - change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION; - - if (mac->bssinfo_change) - mac->bssinfo_change(mac->dev, change); + mac->txrates_change(mac->dev, change, &oldrates); mac->running = 1; } @@ -322,7 +272,7 @@ struct ieee80211softmac_device *mac = ieee80211_priv(dev); ieee80211softmac_start_check_rates(mac); - ieee80211softmac_init_bss(mac); + ieee80211softmac_init_txrates(mac); } EXPORT_SYMBOL_GPL(ieee80211softmac_start); @@ -375,6 +325,7 @@ static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac, int amount) { + struct ieee80211softmac_txrates oldrates; u8 default_rate = mac->txrates.default_rate; u8 default_fallback = mac->txrates.default_fallback; u32 changes = 0; @@ -387,6 +338,8 @@ mac->txrate_badness += amount; if (mac->txrate_badness <= -1000) { /* Very small badness. Try a faster bitrate. */ + if (mac->txrates_change) + memcpy(&oldrates, &mac->txrates, sizeof(oldrates)); default_rate = raise_rate(mac, default_rate); changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; default_fallback = get_fallback_rate(mac, default_rate); @@ -395,6 +348,8 @@ printk("Bitrate raised to %u\n", default_rate); } else if (mac->txrate_badness >= 10000) { /* Very high badness. Try a slower bitrate. */ + if (mac->txrates_change) + memcpy(&oldrates, &mac->txrates, sizeof(oldrates)); default_rate = lower_rate(mac, default_rate); changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; default_fallback = get_fallback_rate(mac, default_rate); @@ -407,7 +362,7 @@ mac->txrates.default_fallback = default_fallback; if (changes && mac->txrates_change) - mac->txrates_change(mac->dev, changes); + mac->txrates_change(mac->dev, changes, &oldrates); } void ieee80211softmac_fragment_lost(struct net_device *dev, @@ -451,11 +406,7 @@ memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len); softnet->supported_rates.count += net->rates_ex_len; sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL); - - /* we save the ERP value because it is needed at association time, and - * many AP's do not include an ERP IE in the association response. */ - softnet->erp_value = net->erp_value; - + softnet->capabilities = net->capability; return softnet; } --- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_priv.h.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_priv.h 2008-08-12 17:06:50.000000000 -0400 @@ -116,11 +116,9 @@ struct ieee80211softmac_essid *essid); /* Rates related */ -void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac, - u8 erp_value); int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate); u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta); -void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac); +void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac); void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac); static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) { return ieee80211softmac_lower_rate_delta(mac, rate, 1); @@ -135,9 +133,6 @@ /*** prototypes from _io.c */ int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, void* ptrarg, u32 type, u32 arg); -int ieee80211softmac_handle_beacon(struct net_device *dev, - struct ieee80211_beacon *beacon, - struct ieee80211_network *network); /*** prototypes from _auth.c */ /* do these have to go into the public header? */ @@ -194,7 +189,6 @@ authenticated:1, auth_desynced_once:1; - u8 erp_value; /* Saved ERP value */ u16 capabilities; /* Capabilities bitfield */ u8 challenge_len; /* Auth Challenge length */ char *challenge; /* Challenge Text */ --- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_io.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_io.c 2008-08-12 17:06:50.000000000 -0400 @@ -467,22 +467,3 @@ kfree(pkt); return 0; } - -/* Beacon handling */ -int ieee80211softmac_handle_beacon(struct net_device *dev, - struct ieee80211_beacon *beacon, - struct ieee80211_network *network) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - - /* This might race, but we don't really care and it's not worth - * adding heavyweight locking in this fastpath. - */ - if (mac->associnfo.associated) { - if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0) - ieee80211softmac_process_erp(mac, network->erp_value); - } - - return 0; -} - --- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_wx.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_wx.c 2008-08-12 17:07:45.000000000 -0400 @@ -70,32 +70,41 @@ char *extra) { struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + struct ieee80211softmac_network *n; struct ieee80211softmac_auth_queue_item *authptr; int length = 0; + unsigned long flags; -check_assoc_again: - mutex_lock(&sm->associnfo.mutex); - if((sm->associnfo.associating || sm->associnfo.associated) && - (data->essid.flags && data->essid.length)) { - dprintk(KERN_INFO PFX "Canceling existing associate request!\n"); - /* Cancel assoc work */ - cancel_delayed_work(&sm->associnfo.work); - /* We don't have to do this, but it's a little cleaner */ - list_for_each_entry(authptr, &sm->auth_queue, list) - cancel_delayed_work(&authptr->work); - sm->associnfo.bssvalid = 0; - sm->associnfo.bssfixed = 0; - sm->associnfo.associating = 0; - sm->associnfo.associated = 0; - /* We must unlock to avoid deadlocks with the assoc workqueue - * on the associnfo.mutex */ - mutex_unlock(&sm->associnfo.mutex); - flush_workqueue(sm->wq); - /* Avoid race! Check assoc status again. Maybe someone started an - * association while we flushed. */ - goto check_assoc_again; + /* Check if we're already associating to this or another network + * If it's another network, cancel and start over with our new network + * If it's our network, ignore the change, we're already doing it! + */ + if((sm->associnfo.associating || sm->associated) && + (data->essid.flags && data->essid.length && extra)) { + /* Get the associating network */ + n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid); + if(n && n->essid.len == (data->essid.length - 1) && + !memcmp(n->essid.data, extra, n->essid.len)) { + dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n", + MAC_ARG(sm->associnfo.bssid)); + return 0; + } else { + dprintk(KERN_INFO PFX "Canceling existing associate request!\n"); + spin_lock_irqsave(&sm->lock,flags); + /* Cancel assoc work */ + cancel_delayed_work(&sm->associnfo.work); + /* We don't have to do this, but it's a little cleaner */ + list_for_each_entry(authptr, &sm->auth_queue, list) + cancel_delayed_work(&authptr->work); + sm->associnfo.bssvalid = 0; + sm->associnfo.bssfixed = 0; + spin_unlock_irqrestore(&sm->lock, flags); + flush_scheduled_work(); + } } + spin_lock_irqsave(&sm->lock, flags); + sm->associnfo.static_essid = 0; sm->associnfo.assoc_wait = 0; @@ -111,12 +120,10 @@ * If applicable, we have already copied the data in */ sm->associnfo.req_essid.len = length; - sm->associnfo.associating = 1; /* queue lower level code to do work (if necessary) */ - queue_delayed_work(sm->wq, &sm->associnfo.work, 0); - - mutex_unlock(&sm->associnfo.mutex); + schedule_delayed_work(&sm->associnfo.work, 0); + spin_unlock_irqrestore(&sm->lock, flags); return 0; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid); @@ -128,8 +135,10 @@ char *extra) { struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + unsigned long flags; - mutex_lock(&sm->associnfo.mutex); + /* avoid getting inconsistent information */ + spin_lock_irqsave(&sm->lock, flags); /* If all fails, return ANY (empty) */ data->essid.length = 0; data->essid.flags = 0; /* active */ @@ -140,14 +149,14 @@ data->essid.flags = 1; /* active */ memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len); dprintk(KERN_INFO PFX "Getting essid from req_essid\n"); - } else if (sm->associnfo.associated || sm->associnfo.associating) { + } else if (sm->associated || sm->associnfo.associating) { /* If we're associating/associated, return that */ data->essid.length = sm->associnfo.associate_essid.len; data->essid.flags = 1; /* active */ memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len); dprintk(KERN_INFO PFX "Getting essid from associate_essid\n"); } - mutex_unlock(&sm->associnfo.mutex); + spin_unlock_irqrestore(&sm->lock, flags); return 0; } @@ -314,15 +323,15 @@ { struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); int err = 0; + unsigned long flags; - mutex_lock(&mac->associnfo.mutex); + spin_lock_irqsave(&mac->lock, flags); if (mac->associnfo.bssvalid) memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN); else memset(data->ap_addr.sa_data, 0xff, ETH_ALEN); data->ap_addr.sa_family = ARPHRD_ETHER; - mutex_unlock(&mac->associnfo.mutex); - + spin_unlock_irqrestore(&mac->lock, flags); return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap); @@ -334,27 +343,28 @@ char *extra) { struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + unsigned long flags; /* sanity check */ if (data->ap_addr.sa_family != ARPHRD_ETHER) { return -EINVAL; } - mutex_lock(&mac->associnfo.mutex); + spin_lock_irqsave(&mac->lock, flags); if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { /* the bssid we have is not to be fixed any longer, * and we should reassociate to the best AP. */ mac->associnfo.bssfixed = 0; /* force reassociation */ mac->associnfo.bssvalid = 0; - if (mac->associnfo.associated) - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); + if (mac->associated) + schedule_delayed_work(&mac->associnfo.work, 0); } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { /* the bssid we have is no longer fixed */ mac->associnfo.bssfixed = 0; } else { if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { - if (mac->associnfo.associating || mac->associnfo.associated) { + if (mac->associnfo.associating || mac->associated) { /* bssid unchanged and associated or associating - just return */ goto out; } @@ -365,12 +375,11 @@ /* tell the other code that this bssid should be used no matter what */ mac->associnfo.bssfixed = 1; /* queue associate if new bssid or (old one again and not associated) */ - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); + schedule_delayed_work(&mac->associnfo.work, 0); } out: - mutex_unlock(&mac->associnfo.mutex); - + spin_unlock_irqrestore(&mac->lock, flags); return 0; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap); @@ -386,8 +395,7 @@ int err = 0; char *buf; int i; - - mutex_lock(&mac->associnfo.mutex); + spin_lock_irqsave(&mac->lock, flags); /* bleh. shouldn't be locked for that kmalloc... */ @@ -425,8 +433,6 @@ out: spin_unlock_irqrestore(&mac->lock, flags); - mutex_unlock(&mac->associnfo.mutex); - return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie); @@ -441,8 +447,7 @@ unsigned long flags; int err = 0; int space = wrqu->data.length; - - mutex_lock(&mac->associnfo.mutex); + spin_lock_irqsave(&mac->lock, flags); wrqu->data.length = 0; @@ -455,7 +460,6 @@ err = -E2BIG; } spin_unlock_irqrestore(&mac->lock, flags); - mutex_unlock(&mac->associnfo.mutex); return err; } @@ -471,13 +475,10 @@ struct iw_mlme *mlme = (struct iw_mlme *)extra; u16 reason = mlme->reason_code; struct ieee80211softmac_network *net; - int err = -EINVAL; - - mutex_lock(&mac->associnfo.mutex); if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) { printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n"); - goto out; + return -EINVAL; } switch (mlme->cmd) { @@ -485,23 +486,14 @@ net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data); if (!net) { printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n"); - goto out; + return -EINVAL; } - err = ieee80211softmac_deauth_req(mac, net, reason); - goto out; + return ieee80211softmac_deauth_req(mac, net, reason); case IW_MLME_DISASSOC: ieee80211softmac_send_disassoc_req(mac, reason); - mac->associnfo.associated = 0; - mac->associnfo.associating = 0; - err = 0; - goto out; + return 0; default: - err = -EOPNOTSUPP; + return -EOPNOTSUPP; } - -out: - mutex_unlock(&mac->associnfo.mutex); - - return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme); --- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_assoc.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_assoc.c 2008-08-12 17:06:50.000000000 -0400 @@ -48,12 +48,12 @@ dprintk(KERN_INFO PFX "sent association request!\n"); spin_lock_irqsave(&mac->lock, flags); - mac->associnfo.associated = 0; /* just to make sure */ + mac->associated = 0; /* just to make sure */ /* Set a timer for timeout */ /* FIXME: make timeout configurable */ if (likely(mac->running)) - queue_delayed_work(mac->wq, &mac->associnfo.timeout, 5 * HZ); + schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); spin_unlock_irqrestore(&mac->lock, flags); } @@ -62,22 +62,24 @@ { struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; struct ieee80211softmac_network *n; + unsigned long flags; - mutex_lock(&mac->associnfo.mutex); + spin_lock_irqsave(&mac->lock, flags); /* we might race against ieee80211softmac_handle_assoc_response, * so make sure only one of us does something */ - if (!mac->associnfo.associating) - goto out; + if (!mac->associnfo.associating) { + spin_unlock_irqrestore(&mac->lock, flags); + return; + } mac->associnfo.associating = 0; mac->associnfo.bssvalid = 0; - mac->associnfo.associated = 0; + mac->associated = 0; n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid); + spin_unlock_irqrestore(&mac->lock, flags); dprintk(KERN_INFO PFX "assoc request timed out!\n"); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n); -out: - mutex_unlock(&mac->associnfo.mutex); } void @@ -91,10 +93,10 @@ netif_carrier_off(mac->dev); - mac->associnfo.associated = 0; + mac->associated = 0; mac->associnfo.bssvalid = 0; mac->associnfo.associating = 0; - ieee80211softmac_init_bss(mac); + ieee80211softmac_init_txrates(mac); ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); spin_unlock_irqrestore(&mac->lock, flags); } @@ -105,7 +107,7 @@ { struct ieee80211softmac_network *found; - if (mac->associnfo.bssvalid && mac->associnfo.associated) { + if (mac->associnfo.bssvalid && mac->associated) { found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); if (found) ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); @@ -194,18 +196,17 @@ int bssvalid; unsigned long flags; - mutex_lock(&mac->associnfo.mutex); - - if (!mac->associnfo.associating) - goto out; - /* ieee80211_disassoc might clear this */ bssvalid = mac->associnfo.bssvalid; /* meh */ - if (mac->associnfo.associated) + if (mac->associated) ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); + spin_lock_irqsave(&mac->lock, flags); + mac->associnfo.associating = 1; + spin_unlock_irqrestore(&mac->lock, flags); + /* try to find the requested network in our list, if we found one already */ if (bssvalid || mac->associnfo.bssfixed) found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); @@ -259,7 +260,9 @@ if (!found) { if (mac->associnfo.scan_retry > 0) { + spin_lock_irqsave(&mac->lock, flags); mac->associnfo.scan_retry--; + spin_unlock_irqrestore(&mac->lock, flags); /* We know of no such network. Let's scan. * NB: this also happens if we had no memory to copy the network info... @@ -270,17 +273,19 @@ if (ieee80211softmac_start_scan(mac)) { dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); } - goto out; + return; } else { + spin_lock_irqsave(&mac->lock, flags); mac->associnfo.associating = 0; - mac->associnfo.associated = 0; + mac->associated = 0; + spin_unlock_irqrestore(&mac->lock, flags); dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); /* reset the retry counter for the next user request since we * break out and don't reschedule ourselves after this point. */ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); - goto out; + return; } } @@ -293,7 +298,7 @@ /* copy the ESSID for displaying it */ mac->associnfo.associate_essid.len = found->essid.len; memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); - + /* we found a network! authenticate (if necessary) and associate to it. */ if (found->authenticating) { dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n"); @@ -301,7 +306,7 @@ mac->associnfo.assoc_wait = 1; ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); } - goto out; + return; } if (!found->authenticated && !found->authenticating) { /* This relies on the fact that _auth_req only queues the work, @@ -317,14 +322,11 @@ mac->associnfo.assoc_wait = 0; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); } - goto out; + return; } /* finally! now we can start associating */ mac->associnfo.assoc_wait = 0; ieee80211softmac_assoc(mac, found); - -out: - mutex_unlock(&mac->associnfo.mutex); } /* call this to do whatever is necessary when we're associated */ @@ -333,19 +335,11 @@ struct ieee80211_assoc_response * resp, struct ieee80211softmac_network *net) { - u16 cap = le16_to_cpu(resp->capability); - u8 erp_value = net->erp_value; - mac->associnfo.associating = 0; - mac->bssinfo.supported_rates = net->supported_rates; + mac->associnfo.supported_rates = net->supported_rates; ieee80211softmac_recalc_txrates(mac); - mac->associnfo.associated = 1; - - mac->associnfo.short_preamble_available = - (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0; - ieee80211softmac_process_erp(mac, erp_value); - + mac->associated = 1; if (mac->set_bssid_filter) mac->set_bssid_filter(mac->dev, net->bssid); memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN); @@ -358,9 +352,9 @@ int ieee80211softmac_handle_assoc_response(struct net_device * dev, struct ieee80211_assoc_response * resp, - struct ieee80211_network * _ieee80211_network) + struct ieee80211_network * _ieee80211_network_do_not_use) { - /* NOTE: the network parameter has to be mostly ignored by + /* NOTE: the network parameter has to be ignored by * this code because it is the ieee80211's pointer * to the struct, not ours (we made a copy) */ @@ -393,11 +387,6 @@ /* now that we know it was for us, we can cancel the timeout */ cancel_delayed_work(&mac->associnfo.timeout); - /* if the association response included an ERP IE, update our saved - * copy */ - if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE) - network->erp_value = _ieee80211_network->erp_value; - switch (status) { case 0: dprintk(KERN_INFO PFX "associated!\n"); @@ -414,14 +403,14 @@ network->authenticated = 0; /* we don't want to do this more than once ... */ network->auth_desynced_once = 1; - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); + schedule_delayed_work(&mac->associnfo.work, 0); break; } default: dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); mac->associnfo.associating = 0; mac->associnfo.bssvalid = 0; - mac->associnfo.associated = 0; + mac->associated = 0; ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); } @@ -436,7 +425,7 @@ spin_lock_irqsave(&mac->lock, flags); mac->associnfo.associating = 1; - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); + schedule_delayed_work(&mac->associnfo.work, 0); spin_unlock_irqrestore(&mac->lock, flags); } @@ -478,7 +467,7 @@ dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); return 0; } - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); + schedule_delayed_work(&mac->associnfo.work, 0); return 0; } --- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_scan.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_scan.c 2008-08-12 17:06:50.000000000 -0400 @@ -121,7 +121,7 @@ spin_unlock_irqrestore(&sm->lock, flags); break; } - queue_delayed_work(sm->wq, &si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); + schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); spin_unlock_irqrestore(&sm->lock, flags); return; } else { @@ -188,7 +188,7 @@ sm->scaninfo->started = 1; sm->scaninfo->stop = 0; INIT_COMPLETION(sm->scaninfo->finished); - queue_delayed_work(sm->wq, &sm->scaninfo->softmac_scan, 0); + schedule_delayed_work(&sm->scaninfo->softmac_scan, 0); spin_unlock_irqrestore(&sm->lock, flags); return 0; } --- linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_event.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/softmac/ieee80211softmac_event.c 2008-08-12 17:06:50.000000000 -0400 @@ -170,7 +170,7 @@ /* User may have subscribed to ANY event, so * we tell them which event triggered it. */ eventptr->event_type = event; - queue_delayed_work(mac->wq, &eventptr->work, 0); + schedule_delayed_work(&eventptr->work, 0); } } } --- linux-2.6.18.noarch/net/ieee80211/ieee80211_rx.c.orig 2008-08-12 17:06:39.000000000 -0400 +++ linux-2.6.18.noarch/net/ieee80211/ieee80211_rx.c 2008-08-12 17:06:50.000000000 -0400 @@ -429,16 +429,17 @@ ieee->host_mc_decrypt : ieee->host_decrypt; if (can_be_decrypted) { + int idx = 0; if (skb->len >= hdrlen + 3) { /* Top two-bits of byte 3 are the key index */ - keyidx = skb->data[hdrlen + 3] >> 6; + idx = skb->data[hdrlen + 3] >> 6; } - /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx - * is only allowed 2-bits of storage, no value of keyidx can - * be provided via above code that would result in keyidx + /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx + * is only allowed 2-bits of storage, no value of idx can + * be provided via above code that would result in idx * being out of range */ - crypt = ieee->crypt[keyidx]; + crypt = ieee->crypt[idx]; #ifdef NOT_YET sta = NULL; @@ -496,11 +497,6 @@ goto rx_exit; } #endif - /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */ - if (sc == ieee->prev_seq_ctl) - goto rx_dropped; - else - ieee->prev_seq_ctl = sc; /* Data frame - extract src/dst addresses */ if (skb->len < IEEE80211_3ADDR_LEN) @@ -682,51 +678,6 @@ goto rx_dropped; } - /* If the frame was decrypted in hardware, we may need to strip off - * any security data (IV, ICV, etc) that was left behind */ - if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) && - ieee->host_strip_iv_icv) { - int trimlen = 0; - - /* Top two-bits of byte 3 are the key index */ - if (skb->len >= hdrlen + 3) - keyidx = skb->data[hdrlen + 3] >> 6; - - /* To strip off any security data which appears before the - * payload, we simply increase hdrlen (as the header gets - * chopped off immediately below). For the security data which - * appears after the payload, we use skb_trim. */ - - switch (ieee->sec.encode_alg[keyidx]) { - case SEC_ALG_WEP: - /* 4 byte IV */ - hdrlen += 4; - /* 4 byte ICV */ - trimlen = 4; - break; - case SEC_ALG_TKIP: - /* 4 byte IV, 4 byte ExtIV */ - hdrlen += 8; - /* 8 byte MIC, 4 byte ICV */ - trimlen = 12; - break; - case SEC_ALG_CCMP: - /* 8 byte CCMP header */ - hdrlen += 8; - /* 8 byte MIC */ - trimlen = 8; - break; - } - - if (skb->len < trimlen) - goto rx_dropped; - - __skb_trim(skb, skb->len - trimlen); - - if (skb->len < hdrlen) - goto rx_dropped; - } - /* skb: hdr + (possible reassembled) full plaintext payload */ payload = skb->data + hdrlen;