From 9a613195123ab2c2400004c7aaee4d25f3b8ae52 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 5 Jul 2008 15:11:57 +0200 Subject: rt2x00: Fix NULL pointer error in adhoc/master mode As soon as an interface is enabled, and that interface is in adhoc or master mode, the device will start raising beacondone interrupts. But before the first interrupt is raised, mac80211 will probably not have send any beacons to the device yet, which results in a NULL pointer error when the skb is being freed. Note that the "raise beacondone interrupts without a beacon" is also a bug, and will be addressed later. The more important bug however is preventing the NULL pointer failt itself, since there might be other conditions that could trigger it as well. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 3ddce538ef4..ecf57f8f34b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -108,6 +108,9 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { + if (!skb) + return; + rt2x00queue_unmap_skb(rt2x00dev, skb); dev_kfree_skb_any(skb); } -- cgit v1.2.3-18-g5258 From 500c11973233437cbfd298b9d41ba942550aec76 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Wed, 9 Jul 2008 01:11:59 +0300 Subject: rtl8187: Fixed section mismatch in rtl8187_dev.c When CONFIG_HOTPLUG=n the following error occures on vmlinux linkage: `.exit.text' referenced in section `.data' of drivers/built-in.o: defined in discarded section `.exit.text' of drivers/built-in.o 'rtl8187_disconnect' function marked as __devexit isn't compiled with no hotplug support. Added __devexit_p macros to fix the problem. Signed-off-by: Ihar Hrachyshka Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 33527e58256..bdea1d8ad8e 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -1180,7 +1180,7 @@ static struct usb_driver rtl8187_driver = { .name = KBUILD_MODNAME, .id_table = rtl8187_table, .probe = rtl8187_probe, - .disconnect = rtl8187_disconnect, + .disconnect = __devexit_p(rtl8187_disconnect), }; static int __init rtl8187_init(void) -- cgit v1.2.3-18-g5258 From 9d139c810a2aa17365cc548d0cd2a189d8433c65 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 9 Jul 2008 14:40:37 +0200 Subject: mac80211: revamp beacon configuration This patch changes mac80211's beacon configuration handling to never pass skbs to the driver directly but rather always require the driver to use ieee80211_beacon_get(). Additionally, it introduces "change flags" on the config_interface() call to enable drivers to figure out what is changing. Finally, it removes the beacon_update() driver callback in favour of having IBSS beacon delivered by ieee80211_beacon_get() as well. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 13 +++++++- drivers/net/wireless/b43/main.c | 48 ++++++++++++----------------- drivers/net/wireless/b43legacy/main.c | 45 ++++++++++----------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 19 ++++++++++-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 18 +++++++++-- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 ++ drivers/net/wireless/rt2x00/rt2x00dev.c | 10 +++--- drivers/net/wireless/rt2x00/rt2x00mac.c | 22 +++++++++---- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- drivers/net/wireless/zd1211rw/zd_mac.c | 22 +++++-------- 14 files changed, 115 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index a43e9b25169..217d506527a 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -207,7 +207,6 @@ static struct ieee80211_ops ath5k_hw_ops = { .get_tx_stats = ath5k_get_tx_stats, .get_tsf = ath5k_get_tsf, .reset_tsf = ath5k_reset_tsf, - .beacon_update = ath5k_beacon_update, }; /* @@ -2785,6 +2784,18 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, * a clean way of letting us retrieve this yet. */ ath5k_hw_set_associd(ah, ah->ah_bssid, 0); } + + if (conf->changed & IEEE80211_IFCC_BEACON && + vif->type == IEEE80211_IF_TYPE_IBSS) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + if (!beacon) { + ret = -ENOMEM; + goto unlock; + } + /* call old handler for now */ + ath5k_beacon_update(hw, beacon); + } + mutex_unlock(&sc->lock); return ath5k_reset(hw); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9d2eb273b72..381dbd33dfc 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1675,14 +1675,24 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) /* Asynchronously update the packet templates in template RAM. * Locking: Requires wl->irq_lock to be locked. */ -static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) +static void b43_update_templates(struct b43_wl *wl) { + struct sk_buff *beacon; + /* This is the top half of the ansynchronous beacon update. * The bottom half is the beacon IRQ. * Beacon update must be asynchronous to avoid sending an * invalid beacon. This can happen for example, if the firmware * transmits a beacon while we are updating it. */ + /* We could modify the existing beacon and set the aid bit in + * the TIM field, but that would probably require resizing and + * moving of data within the beacon template. + * Simply request a new beacon and let mac80211 do the hard work. */ + beacon = ieee80211_beacon_get(wl->hw, wl->vif); + if (unlikely(!beacon)) + return; + if (wl->current_beacon) dev_kfree_skb_any(wl->current_beacon); wl->current_beacon = beacon; @@ -3645,10 +3655,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, if (b43_status(dev) >= B43_STAT_INITIALIZED) { if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) { - B43_WARN_ON(conf->type != wl->if_type); - b43_set_ssid(dev, conf->ssid, conf->ssid_len); - if (conf->beacon) - b43_update_templates(wl, conf->beacon); + B43_WARN_ON(vif->type != wl->if_type); + if (conf->changed & IEEE80211_IFCC_SSID) + b43_set_ssid(dev, conf->ssid, conf->ssid_len); + if (conf->changed & IEEE80211_IFCC_BEACON) + b43_update_templates(wl); + } else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) { + if (conf->changed & IEEE80211_IFCC_BEACON) + b43_update_templates(wl); } b43_write_mac_bssid_templates(dev); } @@ -4334,33 +4348,12 @@ out_unlock: } static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct sk_buff *beacon; - unsigned long flags; - - /* We could modify the existing beacon and set the aid bit in - * the TIM field, but that would probably require resizing and - * moving of data within the beacon template. - * Simply request a new beacon and let mac80211 do the hard work. */ - beacon = ieee80211_beacon_get(hw, wl->vif); - if (unlikely(!beacon)) - return -ENOMEM; - spin_lock_irqsave(&wl->irq_lock, flags); - b43_update_templates(wl, beacon); - spin_unlock_irqrestore(&wl->irq_lock, flags); - - return 0; -} - -static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *beacon) { struct b43_wl *wl = hw_to_b43_wl(hw); unsigned long flags; spin_lock_irqsave(&wl->irq_lock, flags); - b43_update_templates(wl, beacon); + b43_update_templates(wl); spin_unlock_irqrestore(&wl->irq_lock, flags); return 0; @@ -4391,7 +4384,6 @@ static const struct ieee80211_ops b43_hw_ops = { .stop = b43_op_stop, .set_retry_limit = b43_op_set_retry_limit, .set_tim = b43_op_beacon_set_tim, - .beacon_update = b43_op_ibss_beacon_update, .sta_notify = b43_op_sta_notify, }; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 069157eea05..a1b8bf3ee73 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1138,14 +1138,22 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, /* Asynchronously update the packet templates in template RAM. * Locking: Requires wl->irq_lock to be locked. */ -static void b43legacy_update_templates(struct b43legacy_wl *wl, - struct sk_buff *beacon) +static void b43legacy_update_templates(struct b43legacy_wl *wl) { + struct sk_buff *beacon; /* This is the top half of the ansynchronous beacon update. The bottom * half is the beacon IRQ. Beacon update must be asynchronous to avoid * sending an invalid beacon. This can happen for example, if the * firmware transmits a beacon while we are updating it. */ + /* We could modify the existing beacon and set the aid bit in the TIM + * field, but that would probably require resizing and moving of data + * within the beacon template. Simply request a new beacon and let + * mac80211 do the hard work. */ + beacon = ieee80211_beacon_get(wl->hw, wl->vif); + if (unlikely(!beacon)) + return; + if (wl->current_beacon) dev_kfree_skb_any(wl->current_beacon); wl->current_beacon = beacon; @@ -2727,10 +2735,13 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw, memset(wl->bssid, 0, ETH_ALEN); if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) { - B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); + B43legacy_WARN_ON(vif->type != IEEE80211_IF_TYPE_AP); b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len); - if (conf->beacon) - b43legacy_update_templates(wl, conf->beacon); + if (conf->changed & IEEE80211_IFCC_BEACON) + b43legacy_update_templates(wl); + } else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) { + if (conf->changed & IEEE80211_IFCC_BEACON) + b43legacy_update_templates(wl); } b43legacy_write_mac_bssid_templates(dev); } @@ -3394,33 +3405,12 @@ out_unlock: static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct sk_buff *beacon; - unsigned long flags; - - /* We could modify the existing beacon and set the aid bit in the TIM - * field, but that would probably require resizing and moving of data - * within the beacon template. Simply request a new beacon and let - * mac80211 do the hard work. */ - beacon = ieee80211_beacon_get(hw, wl->vif); - if (unlikely(!beacon)) - return -ENOMEM; - spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_update_templates(wl, beacon); - spin_unlock_irqrestore(&wl->irq_lock, flags); - - return 0; -} - -static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *beacon) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); unsigned long flags; spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_update_templates(wl, beacon); + b43legacy_update_templates(wl); spin_unlock_irqrestore(&wl->irq_lock, flags); return 0; @@ -3440,7 +3430,6 @@ static const struct ieee80211_ops b43legacy_hw_ops = { .stop = b43legacy_op_stop, .set_retry_limit = b43legacy_op_set_retry_limit, .set_tim = b43legacy_op_beacon_set_tim, - .beacon_update = b43legacy_op_ibss_beacon_update, }; /* Hard-reset the chip. Do not call this directly. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1a7d18fea89..7d015f86ee8 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6907,6 +6907,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) * clear sta table, add BCAST sta... */ } +/* temporary */ +static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); + static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) @@ -6924,10 +6927,21 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, return 0; } + /* handle this temporarily here */ + if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + conf->changed & IEEE80211_IFCC_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + if (!beacon) + return -ENOMEM; + rc = iwl3945_mac_beacon_update(hw, beacon); + if (rc) + return rc; + } + /* XXX: this MUST use conf->mac_addr */ if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && - (!conf->beacon || !conf->ssid_len)) { + (!conf->ssid_len)) { IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n"); return 0; @@ -6959,7 +6973,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = conf->beacon; + priv->ibss_beacon = ieee80211_beacon_get(hw, vif); } if (iwl3945_is_rfkill(priv)) @@ -7940,7 +7954,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { .conf_tx = iwl3945_mac_conf_tx, .get_tsf = iwl3945_mac_get_tsf, .reset_tsf = iwl3945_mac_reset_tsf, - .beacon_update = iwl3945_mac_beacon_update, .hw_scan = iwl3945_mac_hw_scan }; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 7f65d9123b2..d6fe0ded59d 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2912,6 +2912,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv) * clear sta table, add BCAST sta... */ } +/* temporary */ +static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); + static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) @@ -2929,8 +2932,18 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, return 0; } + if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + conf->changed & IEEE80211_IFCC_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + if (!beacon) + return -ENOMEM; + rc = iwl4965_mac_beacon_update(hw, beacon); + if (rc) + return rc; + } + if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && - (!conf->beacon || !conf->ssid_len)) { + (!conf->ssid_len)) { IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n"); return 0; @@ -2962,7 +2975,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = conf->beacon; + priv->ibss_beacon = ieee80211_beacon_get(hw, vif); } if (iwl_is_rfkill(priv)) @@ -4090,7 +4103,6 @@ static struct ieee80211_ops iwl4965_hw_ops = { .get_tx_stats = iwl4965_mac_get_tx_stats, .conf_tx = iwl4965_mac_conf_tx, .reset_tsf = iwl4965_mac_reset_tsf, - .beacon_update = iwl4965_mac_beacon_update, .bss_info_changed = iwl4965_bss_info_changed, .ampdu_action = iwl4965_mac_ampdu_action, .hw_scan = iwl4965_mac_hw_scan diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index ee953ca0c6a..89b874ca610 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1581,7 +1581,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .conf_tx = rt2400pci_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2400pci_get_tsf, - .beacon_update = rt2400pci_beacon_update, .tx_last_beacon = rt2400pci_tx_last_beacon, }; @@ -1601,6 +1600,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, + .beacon_update = rt2400pci_beacon_update, .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, .config_erp = rt2400pci_config_erp, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0423c251c78..a64bb18322e 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1875,7 +1875,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2500pci_get_tsf, - .beacon_update = rt2500pci_beacon_update, .tx_last_beacon = rt2500pci_tx_last_beacon, }; @@ -1895,6 +1894,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, + .beacon_update = rt2500pci_beacon_update, .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, .config_erp = rt2500pci_config_erp, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 0dd1cb537b9..8ce1726d750 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1775,7 +1775,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, - .beacon_update = rt2500usb_beacon_update, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { @@ -1793,6 +1792,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, + .beacon_update = rt2500usb_beacon_update, .config_filter = rt2500usb_config_filter, .config_intf = rt2500usb_config_intf, .config_erp = rt2500usb_config_erp, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c07d9ef383f..9ad3ce43e6c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -534,6 +534,8 @@ struct rt2x00lib_ops { /* * Configuration handlers. */ + int (*beacon_update) (struct ieee80211_hw *hw, struct sk_buff *bcn); + void (*config_filter) (struct rt2x00_dev *rt2x00dev, const unsigned int filter_flags); void (*config_intf) (struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b48c04e80a3..1b7f87799a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -409,7 +409,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); - struct sk_buff *skb; struct ieee80211_bss_conf conf; int delayed_flags; @@ -436,10 +435,11 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, return; if (delayed_flags & DELAYED_UPDATE_BEACON) { - skb = ieee80211_beacon_get(rt2x00dev->hw, vif); - if (skb && - rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb)) - dev_kfree_skb(skb); + struct ieee80211_if_conf conf; + conf.bssid = conf.ssid = NULL; + conf.ssid_len = 0; + conf.changed = IEEE80211_IFCC_BEACON; + rt2x00dev->ops->hw->config_interface(rt2x00dev->hw, vif, &conf); } if (delayed_flags & DELAYED_CONFIG_ERP) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3a1fb6d47e5..84b51f49175 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -348,6 +348,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); + struct sk_buff *beacon; int status; /* @@ -363,8 +364,11 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, * If the interface does not work in master mode, * then the bssid value in the interface structure * should now be set. + * + * conf->bssid can be NULL if coming from the internal + * beacon update routine. */ - if (conf->type != IEEE80211_IF_TYPE_AP) + if (conf->bssid && vif->type != IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->bssid, ETH_ALEN); spin_unlock(&intf->lock); @@ -375,17 +379,23 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, * values as arguments we make keep access to rt2x00_intf thread safe * even without the lock. */ - rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid); + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, conf->bssid); /* - * We only need to initialize the beacon when master mode is enabled. + * We only need to initialize the beacon when in master/ibss mode. */ - if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon) + if ((vif->type != IEEE80211_IF_TYPE_AP && + vif->type != IEEE80211_IF_TYPE_IBSS) || + !(conf->changed & IEEE80211_IFCC_BEACON)) return 0; - status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon); + beacon = ieee80211_beacon_get(rt2x00dev->hw, vif); + if (!beacon) + return -ENOMEM; + + status = rt2x00dev->ops->lib->beacon_update(rt2x00dev->hw, beacon); if (status) - dev_kfree_skb(conf->beacon); + dev_kfree_skb(beacon); return status; } diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index bbf1048f640..852d193a11a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2427,7 +2427,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt61pci_get_tsf, - .beacon_update = rt61pci_beacon_update, }; static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { @@ -2449,6 +2448,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, + .beacon_update = rt61pci_beacon_update, .config_filter = rt61pci_config_filter, .config_intf = rt61pci_config_intf, .config_erp = rt61pci_config_erp, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 3ef318e098e..65720097242 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2031,7 +2031,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt73usb_get_tsf, - .beacon_update = rt73usb_beacon_update, }; static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { @@ -2052,6 +2051,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, + .beacon_update = rt73usb_beacon_update, .config_filter = rt73usb_config_filter, .config_intf = rt73usb_config_intf, .config_erp = rt73usb_config_erp, diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 665f76af2fe..68e2749b2ce 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -727,15 +727,19 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || mac->type == IEEE80211_IF_TYPE_IBSS) { associated = true; - if (conf->beacon) { - r = zd_mac_config_beacon(hw, conf->beacon); + if (conf->changed & IEEE80211_IFCC_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + + if (!beacon) + return -ENOMEM; + r = zd_mac_config_beacon(hw, beacon); if (r < 0) return r; r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | hw->conf.beacon_int); if (r < 0) return r; - kfree_skb(conf->beacon); + kfree_skb(beacon); } } else associated = is_valid_ether_addr(conf->bssid); @@ -889,17 +893,6 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw, } } -static int zd_op_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct zd_mac *mac = zd_hw_mac(hw); - zd_mac_config_beacon(hw, skb); - kfree_skb(skb); - zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | - hw->conf.beacon_int); - return 0; -} - static const struct ieee80211_ops zd_ops = { .tx = zd_op_tx, .start = zd_op_start, @@ -910,7 +903,6 @@ static const struct ieee80211_ops zd_ops = { .config_interface = zd_op_config_interface, .configure_filter = zd_op_configure_filter, .bss_info_changed = zd_op_bss_info_changed, - .beacon_update = zd_op_beacon_update, }; struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) -- cgit v1.2.3-18-g5258 From e360c4cb2bc2fb2a37981809685984efe8433c52 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 9 Jul 2008 15:12:06 +0200 Subject: rt2x00: Add support for CTS protection in rt2x00lib Inform drivers about the changed CTS protection settings. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 1 + drivers/net/wireless/rt2x00/rt2x00config.c | 2 ++ drivers/net/wireless/rt2x00/rt2x00mac.c | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 9ad3ce43e6c..b32fedf4a1b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -434,6 +434,7 @@ struct rt2x00lib_conf { */ struct rt2x00lib_erp { int short_preamble; + int cts_protection; int ack_timeout; int ack_consume_time; diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 48608e8cc8b..f20ca712504 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -84,6 +84,8 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, memset(&erp, 0, sizeof(erp)); erp.short_preamble = bss_conf->use_short_preamble; + erp.cts_protection = bss_conf->use_cts_prot; + erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10); erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 84b51f49175..ff853c430bd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -511,7 +511,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ - if (changes & BSS_CHANGED_ERP_PREAMBLE) { + if (changes & (BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_ERP_CTS_PROT)) { if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); else -- cgit v1.2.3-18-g5258 From bd88a7812f1afd50549f3789cacb707b983fef54 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 9 Jul 2008 15:12:44 +0200 Subject: rt2x00: Reorganize beacon handling With the new beacon handling from mac80211 we can reorganize the beacon handling in rt2x00 as well. This patch will move the function to the TX handlers, and move all duplicate code into rt2x00queue.c. After this change the descriptor helper functions from rt2x00queue.c no longer need to be exported outside of rt2x00lib and can be declared static. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 89 +++++++---------- drivers/net/wireless/rt2x00/rt2500pci.c | 90 +++++++---------- drivers/net/wireless/rt2x00/rt2500usb.c | 154 ++++++++++++------------------ drivers/net/wireless/rt2x00/rt2x00.h | 36 +------ drivers/net/wireless/rt2x00/rt2x00dev.c | 9 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 8 ++ drivers/net/wireless/rt2x00/rt2x00mac.c | 31 ++---- drivers/net/wireless/rt2x00/rt2x00queue.c | 64 +++++++++++-- drivers/net/wireless/rt2x00/rt61pci.c | 103 +++++++------------- drivers/net/wireless/rt2x00/rt73usb.c | 115 +++++++++------------- 10 files changed, 289 insertions(+), 410 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 89b874ca610..027580bfa7c 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1058,6 +1058,40 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ +static void rt2400pci_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_pci *entry_priv = entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + u32 word; + u32 reg; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + + /* + * Replace rt2x00lib allocated descriptor with the + * pointer to the _real_ hardware descriptor. + * After that, map the beacon to DMA and update the + * descriptor. + */ + memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry_priv->desc; + + rt2x00queue_map_txskb(rt2x00dev, entry->skb); + + rt2x00_desc_read(entry_priv->desc, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); + rt2x00_desc_write(entry_priv->desc, 1, word); +} + static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -1504,59 +1538,6 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct queue_entry_priv_pci *entry_priv; - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - u32 reg; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - entry_priv = intf->beacon->priv_data; - - /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - intf->beacon->skb = skb; - rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); - rt2x00_set_field32(®, CSR14_TBCN, 0); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - - /* - * Enable beacon generation. - * Write entire beacon with descriptor to register, - * and kick the beacon generator. - */ - rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); - - return 0; -} - static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1598,9 +1579,9 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .link_tuner = rt2400pci_link_tuner, .write_tx_desc = rt2400pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, + .write_beacon = rt2400pci_write_beacon, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, - .beacon_update = rt2400pci_beacon_update, .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, .config_erp = rt2400pci_config_erp, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index a64bb18322e..50f9e8f6cd6 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1216,6 +1216,40 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ +static void rt2500pci_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_pci *entry_priv = entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + u32 word; + u32 reg; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + + /* + * Replace rt2x00lib allocated descriptor with the + * pointer to the _real_ hardware descriptor. + * After that, map the beacon to DMA and update the + * descriptor. + */ + memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry_priv->desc; + + rt2x00queue_map_txskb(rt2x00dev, entry->skb); + + rt2x00_desc_read(entry_priv->desc, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); + rt2x00_desc_write(entry_priv->desc, 1, word); +} + static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -1797,60 +1831,6 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct queue_entry_priv_pci *entry_priv; - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - u32 reg; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - - entry_priv = intf->beacon->priv_data; - - /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - intf->beacon->skb = skb; - rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); - rt2x00_set_field32(®, CSR14_TBCN, 0); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - - /* - * Enable beacon generation. - * Write entire beacon with descriptor to register, - * and kick the beacon generator. - */ - rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); - - return 0; -} - static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1892,9 +1872,9 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .link_tuner = rt2500pci_link_tuner, .write_tx_desc = rt2500pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, + .write_beacon = rt2500pci_write_beacon, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, - .beacon_update = rt2500pci_beacon_update, .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, .config_erp = rt2500pci_config_erp, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8ce1726d750..1423fd0bdbb 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1100,6 +1100,65 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 0, word); } +/* + * TX data initialization + */ +static void rt2500usb_beacondone(struct urb *urb); + +static void rt2500usb_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); + struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + int pipe = usb_sndbulkpipe(usb_dev, 1); + int length; + u16 reg; + + /* + * Add the descriptor in front of the skb. + */ + skb_push(entry->skb, entry->queue->desc_size); + memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry->skb->data; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + + /* + * USB devices cannot blindly pass the skb->len as the + * length of the data to usb_fill_bulk_urb. Pass the skb + * to the driver to determine what the length should be. + */ + length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); + + usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, + entry->skb->data, length, rt2500usb_beacondone, + entry); + + /* + * Second we need to create the guardian byte. + * We only need a single byte, so lets recycle + * the 'flags' field we are not using for beacons. + */ + bcn_priv->guardian_data = 0; + usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe, + &bcn_priv->guardian_data, 1, rt2500usb_beacondone, + entry); + + /* + * Send out the guardian byte. + */ + usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); +} + static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { @@ -1115,9 +1174,6 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, return length; } -/* - * TX data initialization - */ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -1672,96 +1728,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) return 0; } -/* - * IEEE80211 stack callback functions. - */ -static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct queue_entry_priv_usb_bcn *bcn_priv; - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - int pipe = usb_sndbulkpipe(usb_dev, 1); - int length; - u16 reg; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - - bcn_priv = intf->beacon->priv_data; - - /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - intf->beacon->skb = skb; - rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); - - /* - * Add the descriptor in front of the skb. - */ - skb_push(skb, intf->beacon->queue->desc_size); - memset(skb->data, 0, intf->beacon->queue->desc_size); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = skb->data; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - - /* - * USB devices cannot blindly pass the skb->len as the - * length of the data to usb_fill_bulk_urb. Pass the skb - * to the driver to determine what the length should be. - */ - length = rt2500usb_get_tx_data_len(rt2x00dev, skb); - - usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, - skb->data, length, rt2500usb_beacondone, - intf->beacon); - - /* - * Second we need to create the guardian byte. - * We only need a single byte, so lets recycle - * the 'flags' field we are not using for beacons. - */ - bcn_priv->guardian_data = 0; - usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe, - &bcn_priv->guardian_data, 1, rt2500usb_beacondone, - intf->beacon); - - /* - * Send out the guardian byte. - */ - usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); - - /* - * Enable beacon generation. - */ - rt2500usb_kick_tx_queue(rt2x00dev, QID_BEACON); - - return 0; -} - static const struct ieee80211_ops rt2500usb_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -1789,10 +1755,10 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .link_tuner = rt2500usb_link_tuner, .write_tx_desc = rt2500usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, + .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, - .beacon_update = rt2500usb_beacon_update, .config_filter = rt2500usb_config_filter, .config_intf = rt2500usb_config_intf, .config_erp = rt2500usb_config_erp, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index b32fedf4a1b..f0d7e083d8f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -521,6 +521,7 @@ struct rt2x00lib_ops { struct sk_buff *skb, struct txentry_desc *txdesc); int (*write_tx_data) (struct queue_entry *entry); + void (*write_beacon) (struct queue_entry *entry); int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, @@ -535,8 +536,6 @@ struct rt2x00lib_ops { /* * Configuration handlers. */ - int (*beacon_update) (struct ieee80211_hw *hw, struct sk_buff *bcn); - void (*config_filter) (struct rt2x00_dev *rt2x00dev, const unsigned int filter_flags); void (*config_intf) (struct rt2x00_dev *rt2x00dev, @@ -912,39 +911,6 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) */ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); -/** - * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input - * @entry: The entry which will be used to transfer the TX frame. - * @txdesc: rt2x00 TX descriptor which will be initialized by this function. - * - * This function will initialize the &struct txentry_desc based on information - * from mac80211. This descriptor can then be used by rt2x00lib and the drivers - * to correctly initialize the hardware descriptor. - * Note that before calling this function the skb->cb array must be untouched - * by rt2x00lib. Only after this function completes will it be save to - * overwrite the skb->cb information. - * The reason for this is that mac80211 writes its own tx information into - * the skb->cb array, and this function will use that information to initialize - * the &struct txentry_desc structure. - */ -void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc); - -/** - * rt2x00queue_write_tx_descriptor - Write TX descriptor to hardware - * @entry: The entry which will be used to transfer the TX frame. - * @txdesc: TX descriptor which will be used to write hardware descriptor - * - * This function will write a TX descriptor initialized by - * &rt2x00queue_create_tx_descriptor to the hardware. After this call - * has completed the frame is now owned by the hardware, the hardware - * queue will have automatically be kicked unless this frame was generated - * by rt2x00lib, in which case the frame is "special" and must be kicked - * by the caller. - */ -void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc); - /** * rt2x00queue_get_queue - Convert queue index to queue pointer * @rt2x00dev: Pointer to &struct rt2x00_dev. diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 1b7f87799a7..8c93eb8353b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -434,13 +434,8 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) return; - if (delayed_flags & DELAYED_UPDATE_BEACON) { - struct ieee80211_if_conf conf; - conf.bssid = conf.ssid = NULL; - conf.ssid_len = 0; - conf.changed = IEEE80211_IFCC_BEACON; - rt2x00dev->ops->hw->config_interface(rt2x00dev->hw, vif, &conf); - } + if (delayed_flags & DELAYED_UPDATE_BEACON) + rt2x00queue_update_beacon(rt2x00dev, vif); if (delayed_flags & DELAYED_CONFIG_ERP) rt2x00lib_config_erp(rt2x00dev, intf, &conf); diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index eae5ce1d4de..f2c9b0e79b5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -138,6 +138,14 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); */ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); +/** + * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @vif: Interface for which the beacon should be updated. + */ +int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif); + /** * rt2x00queue_index_inc - Index incrementation function * @queue: Queue (&struct data_queue) to perform the action on. diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index ff853c430bd..16b72d9ca1c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -348,8 +348,8 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); - struct sk_buff *beacon; - int status; + int update_bssid = 0; + int status = 0; /* * Mac80211 might be calling this function while we are trying @@ -361,15 +361,13 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, spin_lock(&intf->lock); /* - * If the interface does not work in master mode, - * then the bssid value in the interface structure - * should now be set. - * * conf->bssid can be NULL if coming from the internal * beacon update routine. */ - if (conf->bssid && vif->type != IEEE80211_IF_TYPE_AP) + if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { + update_bssid = 1; memcpy(&intf->bssid, conf->bssid, ETH_ALEN); + } spin_unlock(&intf->lock); @@ -379,23 +377,14 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, * values as arguments we make keep access to rt2x00_intf thread safe * even without the lock. */ - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, conf->bssid); + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, + update_bssid ? conf->bssid : NULL); /* - * We only need to initialize the beacon when in master/ibss mode. + * Update the beacon. */ - if ((vif->type != IEEE80211_IF_TYPE_AP && - vif->type != IEEE80211_IF_TYPE_IBSS) || - !(conf->changed & IEEE80211_IFCC_BEACON)) - return 0; - - beacon = ieee80211_beacon_get(rt2x00dev->hw, vif); - if (!beacon) - return -ENOMEM; - - status = rt2x00dev->ops->lib->beacon_update(rt2x00dev->hw, beacon); - if (status) - dev_kfree_skb(beacon); + if (conf->changed & IEEE80211_IFCC_BEACON) + status = rt2x00queue_update_beacon(rt2x00dev, vif); return status; } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index ecf57f8f34b..7f442030f5a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -115,8 +115,8 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) dev_kfree_skb_any(skb); } -void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc) +static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); @@ -240,10 +240,9 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, txdesc->signal |= 0x08; } } -EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor); -void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc) +static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct data_queue *queue = entry->queue; struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; @@ -273,7 +272,6 @@ void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); } -EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor); int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) { @@ -323,6 +321,60 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) return 0; } +int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif) +{ + struct rt2x00_intf *intf = vif_to_intf(vif); + struct skb_frame_desc *skbdesc; + struct txentry_desc txdesc; + __le32 desc[16]; + + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); + if (!intf->beacon->skb) + return -ENOMEM; + + /* + * Copy all TX descriptor information into txdesc, + * after that we are free to use the skb->cb array + * for our information. + */ + rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); + + /* + * For the descriptor we use a local array from where the + * driver can move it to the correct location required for + * the hardware. + */ + memset(desc, 0, sizeof(desc)); + + /* + * Fill in skb descriptor + */ + skbdesc = get_skb_frame_desc(intf->beacon->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->desc = desc; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + + /* + * Write TX descriptor into reserved room in front of the beacon. + */ + rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); + + /* + * Send beacon to hardware. + * Also enable beacon generation, which might have been disabled + * by the driver during the config_beacon() callback function. + */ + rt2x00dev->ops->lib->write_beacon(intf->beacon); + rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); + + return 0; +} + struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 852d193a11a..80c4445e628 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1591,6 +1591,41 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ +static void rt61pci_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + unsigned int beacon_base; + u32 reg; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + + /* + * Write entire beacon with descriptor to register. + */ + beacon_base = HW_BEACON_OFFSET(entry->entry_idx); + rt2x00pci_register_multiwrite(rt2x00dev, + beacon_base, + skbdesc->desc, skbdesc->desc_len); + rt2x00pci_register_multiwrite(rt2x00dev, + beacon_base + skbdesc->desc_len, + entry->skb->data, entry->skb->len); + + /* + * Clean up beacon skb. + */ + dev_kfree_skb_any(entry->skb); + entry->skb = NULL; +} + static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -2346,72 +2381,6 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct queue_entry_priv_pci *entry_priv; - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - unsigned int beacon_base; - u32 reg; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - - /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - intf->beacon->skb = skb; - rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); - - entry_priv = intf->beacon->priv_data; - memset(entry_priv->desc, 0, intf->beacon->queue->desc_size); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); - - /* - * Write entire beacon with descriptor to register, - * and kick the beacon generator. - */ - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, - skbdesc->desc, skbdesc->desc_len); - rt2x00pci_register_multiwrite(rt2x00dev, - beacon_base + skbdesc->desc_len, - skb->data, skb->len); - rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON); - - /* - * Clean up beacon skb. - */ - dev_kfree_skb_any(skb); - intf->beacon->skb = NULL; - - return 0; -} - static const struct ieee80211_ops rt61pci_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -2446,9 +2415,9 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .link_tuner = rt61pci_link_tuner, .write_tx_desc = rt61pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, + .write_beacon = rt61pci_write_beacon, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, - .beacon_update = rt61pci_beacon_update, .config_filter = rt61pci_config_filter, .config_intf = rt61pci_config_intf, .config_erp = rt61pci_config_erp, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 65720097242..6f89b4c75e1 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1334,6 +1334,49 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 0, word); } +/* + * TX data initialization + */ +static void rt73usb_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + unsigned int beacon_base; + u32 reg; + + /* + * Add the descriptor in front of the skb. + */ + skb_push(entry->skb, entry->queue->desc_size); + memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry->skb->data; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + + /* + * Write entire beacon with descriptor to register. + */ + beacon_base = HW_BEACON_OFFSET(entry->entry_idx); + rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, beacon_base, 0, + entry->skb->data, entry->skb->len, + REGISTER_TIMEOUT32(entry->skb->len)); + + /* + * Clean up the beacon skb. + */ + dev_kfree_skb(entry->skb); + entry->skb = NULL; +} + static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { @@ -1349,9 +1392,6 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, return length; } -/* - * TX data initialization - */ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue) { @@ -1949,73 +1989,6 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) #define rt73usb_get_tsf NULL #endif -static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - unsigned int beacon_base; - u32 reg; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - - /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - intf->beacon->skb = skb; - rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); - - /* - * Add the descriptor in front of the skb. - */ - skb_push(skb, intf->beacon->queue->desc_size); - memset(skb->data, 0, intf->beacon->queue->desc_size); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = skb->data; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); - - /* - * Write entire beacon with descriptor to register, - * and kick the beacon generator. - */ - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, beacon_base, 0, - skb->data, skb->len, - REGISTER_TIMEOUT32(skb->len)); - rt73usb_kick_tx_queue(rt2x00dev, QID_BEACON); - - /* - * Clean up the beacon skb. - */ - dev_kfree_skb(skb); - intf->beacon->skb = NULL; - - return 0; -} - static const struct ieee80211_ops rt73usb_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -2048,10 +2021,10 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .link_tuner = rt73usb_link_tuner, .write_tx_desc = rt73usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, + .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, - .beacon_update = rt73usb_beacon_update, .config_filter = rt73usb_config_filter, .config_intf = rt73usb_config_intf, .config_erp = rt73usb_config_erp, -- cgit v1.2.3-18-g5258 From 4ece16a1cf9d36fee6d3ccb2c933296cf660e44d Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Thu, 10 Jul 2008 18:55:23 -0300 Subject: rtl8187: use different ANAPARAM*_OFF values for 8187B For RTL8187B it seems we need special values too for ANAPARAM*_OFF values (and not use RTL8187 ones). The ANAPARAM*_OFF values used are the stock ones read from the hardware after a cold boot. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_dev.c | 21 ++++++++++++++------- drivers/net/wireless/rtl8187_rtl8225.c | 21 +++++++++++++++++---- drivers/net/wireless/rtl8187_rtl8225.h | 15 +++++++++++---- 3 files changed, 42 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index bdea1d8ad8e..d3067b1216c 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -430,8 +430,10 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, + RTL8187_RTL8225_ANAPARAM_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187_RTL8225_ANAPARAM2_ON); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, @@ -453,8 +455,10 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, + RTL8187_RTL8225_ANAPARAM_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187_RTL8225_ANAPARAM2_ON); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); @@ -566,9 +570,12 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, 0x727f3f52); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, 0x45090658); - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, 0); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187B_RTL8225_ANAPARAM2_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, + RTL8187B_RTL8225_ANAPARAM_ON); + rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, + RTL8187B_RTL8225_ANAPARAM3_ON); rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); reg = rtl818x_ioread8(priv, (u8 *)0xFF62); diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c index 1e059de9711..1bae8990341 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl8187_rtl8225.c @@ -307,7 +307,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187_RTL8225_ANAPARAM2_ON); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); @@ -560,7 +561,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187_RTL8225_ANAPARAM2_ON); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); @@ -913,8 +915,19 @@ static void rtl8225_rf_stop(struct ieee80211_hw *dev) rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF); + if (!priv->is_rtl8187b) { + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187_RTL8225_ANAPARAM2_OFF); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, + RTL8187_RTL8225_ANAPARAM_OFF); + } else { + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187B_RTL8225_ANAPARAM2_OFF); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, + RTL8187B_RTL8225_ANAPARAM_OFF); + rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, + RTL8187B_RTL8225_ANAPARAM3_OFF); + } rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); } diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h index d39ed0295b6..20c5b6ead0f 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.h +++ b/drivers/net/wireless/rtl8187_rtl8225.h @@ -15,10 +15,17 @@ #ifndef RTL8187_RTL8225_H #define RTL8187_RTL8225_H -#define RTL8225_ANAPARAM_ON 0xa0000a59 -#define RTL8225_ANAPARAM2_ON 0x860c7312 -#define RTL8225_ANAPARAM_OFF 0xa00beb59 -#define RTL8225_ANAPARAM2_OFF 0x840dec11 +#define RTL8187_RTL8225_ANAPARAM_ON 0xa0000a59 +#define RTL8187_RTL8225_ANAPARAM2_ON 0x860c7312 +#define RTL8187_RTL8225_ANAPARAM_OFF 0xa00beb59 +#define RTL8187_RTL8225_ANAPARAM2_OFF 0x840dec11 + +#define RTL8187B_RTL8225_ANAPARAM_ON 0x45090658 +#define RTL8187B_RTL8225_ANAPARAM2_ON 0x727f3f52 +#define RTL8187B_RTL8225_ANAPARAM3_ON 0x00 +#define RTL8187B_RTL8225_ANAPARAM_OFF 0x55480658 +#define RTL8187B_RTL8225_ANAPARAM2_OFF 0x72003f50 +#define RTL8187B_RTL8225_ANAPARAM3_OFF 0x00 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *); -- cgit v1.2.3-18-g5258 From f591fa5dbbbeaebd95c9c019b3a536a327fb79de Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Jul 2008 11:21:26 +0200 Subject: mac80211: fix TX sequence numbers This patch makes mac80211 assign proper sequence numbers to QoS-data frames. It also removes the old sequence number code because we noticed that only the driver or hardware can assign sequence numbers to non-QoS-data and especially management frames in a race-free manner because beacons aren't passed through mac80211's TX path. This patch also adds temporary code to the rt2x00 drivers to not break them completely, that code will have to be reworked for proper sequence numbers on beacons. It also moves sequence number assignment down in the TX path so no sequence numbers are assigned to frames that are dropped. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 3 ++- drivers/net/wireless/b43legacy/xmit.c | 3 +-- drivers/net/wireless/rt2x00/rt2x00.h | 2 ++ drivers/net/wireless/rt2x00/rt2x00mac.c | 13 +++++++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index bf6f6c1ed4c..8d54502222a 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -317,7 +317,8 @@ int b43_generate_txhdr(struct b43_wldev *dev, /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43_TXH_MAC_ACK; - if (!ieee80211_is_pspoll(fctl)) + /* use hardware sequence counter as the non-TID counter */ + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) mac_ctl |= B43_TXH_MAC_HWSEQ; if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) mac_ctl |= B43_TXH_MAC_STMSDU; diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index a3540787eb5..e969ed8d412 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -295,8 +295,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43legacy_TX4_MAC_ACK; - if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && - ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) mac_ctl |= B43legacy_TX4_MAC_HWSEQ; if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) mac_ctl |= B43legacy_TX4_MAC_STMSDU; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index f0d7e083d8f..9fab0df18c3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -364,6 +364,8 @@ struct rt2x00_intf { #define DELAYED_UPDATE_BEACON 0x00000001 #define DELAYED_CONFIG_ERP 0x00000002 #define DELAYED_LED_ASSOC 0x00000004 + + u16 seqno; }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 16b72d9ca1c..77af1df5d89 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -96,6 +96,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; enum data_queue_qid qid = skb_get_queue_mapping(skb); + struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); struct data_queue *queue; u16 frame_control; @@ -151,6 +152,18 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) } } + /* + * XXX: This is as wrong as the old mac80211 code was, + * due to beacons not getting sequence numbers assigned + * properly. + */ + if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + intf->seqno += 0x10; + ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + ieee80211hdr->seq_ctrl |= cpu_to_le16(intf->seqno); + } + if (rt2x00queue_write_tx_frame(queue, skb)) { ieee80211_stop_queue(rt2x00dev->hw, qid); return NETDEV_TX_BUSY; -- cgit v1.2.3-18-g5258 From df70b4aca5ef8a154a32ecbdd3c322d6d41a0d33 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Jul 2008 11:56:33 +0200 Subject: mac80211 hwsim: fix endianness bug Radiotap is entirely little endian. Found with sparse. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 5d30c57e396..913dc9fe08f 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -126,7 +126,7 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, (1 << IEEE80211_RADIOTAP_CHANNEL)); hdr->rt_flags = 0; hdr->rt_rate = txrate->bitrate / 5; - hdr->rt_channel = data->channel->center_freq; + hdr->rt_channel = cpu_to_le16(data->channel->center_freq); flags = IEEE80211_CHAN_2GHZ; if (txrate->flags & IEEE80211_RATE_ERP_G) flags |= IEEE80211_CHAN_OFDM; -- cgit v1.2.3-18-g5258 From a05ffd395e1f1293d05a814ef697c12efa411ad8 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 10 Jul 2008 14:28:42 +0300 Subject: iwlwif: remove compilation warnings iwl_add_radiotap Use directly put_unaligned_leX instead of put_unaligned(cpu_to_leX Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-rx.c | 37 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 3e8500ecf59..e2d9afba38a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -29,6 +29,7 @@ #include #include +#include #include "iwl-eeprom.h" #include "iwl-dev.h" #include "iwl-core.h" @@ -829,23 +830,22 @@ static void iwl_add_radiotap(struct iwl_priv *priv, iwl4965_rt->rt_hdr.it_pad = 0; /* total header + data */ - put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)), - &iwl4965_rt->rt_hdr.it_len); + put_unaligned_le16(sizeof(*iwl4965_rt), &iwl4965_rt->rt_hdr.it_len); /* Indicate all the fields we add to the radiotap header */ - put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | - (1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | - (1 << IEEE80211_RADIOTAP_ANTENNA)), - &iwl4965_rt->rt_hdr.it_present); + put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) | + (1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_CHANNEL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | + (1 << IEEE80211_RADIOTAP_ANTENNA), + &(iwl4965_rt->rt_hdr.it_present)); /* Zero the flags, we'll add to them as we go */ iwl4965_rt->rt_flags = 0; - put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf); + put_unaligned_le64(tsf, &iwl4965_rt->rt_tsf); iwl4965_rt->rt_dbmsignal = signal; iwl4965_rt->rt_dbmnoise = noise; @@ -853,17 +853,14 @@ static void iwl_add_radiotap(struct iwl_priv *priv, /* Convert the channel frequency and set the flags */ put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz); if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) - put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_5GHZ), - &iwl4965_rt->rt_chbitmask); + put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, + &iwl4965_rt->rt_chbitmask); else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) - put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK | - IEEE80211_CHAN_2GHZ), - &iwl4965_rt->rt_chbitmask); + put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, + &iwl4965_rt->rt_chbitmask); else /* 802.11g */ - put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_2GHZ), - &iwl4965_rt->rt_chbitmask); + put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, + &iwl4965_rt->rt_chbitmask); if (rate == -1) iwl4965_rt->rt_rate = 0; -- cgit v1.2.3-18-g5258 From 4bd9b4f334c31a79bdfee4db5dbb6aa430090446 Mon Sep 17 00:00:00 2001 From: Adel Gadllah Date: Fri, 11 Jul 2008 11:53:29 +0800 Subject: iwl3965: remove useless network and duplicate checking mac802 can handle duplicate packages on its own, so let it do it. The patch is based on patch from Johannes Berg for iwl4965. Signed-off-by: Adel Gadllah Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 50 +++++------ drivers/net/wireless/iwlwifi/iwl-3945.h | 19 ----- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 126 ---------------------------- 4 files changed, 25 insertions(+), 172 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 94e177a9f51..c2a76785b66 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -514,6 +514,23 @@ static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, } #endif +/* This is necessary only for a number of statistics, see the caller. */ +static int iwl3945_is_network_packet(struct iwl3945_priv *priv, + struct ieee80211_hdr *header) +{ + /* Filter incoming packets to determine if they are targeted toward + * this network, discarding packets coming from ourselves */ + switch (priv->iw_mode) { + case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ + /* packets to our IBSS update information */ + return !compare_ether_addr(header->addr3, priv->bssid); + case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ + /* packets to our IBSS update information */ + return !compare_ether_addr(header->addr2, priv->bssid); + default: + return 1; + } +} static void iwl3945_add_radiotap(struct iwl3945_priv *priv, struct sk_buff *skb, @@ -608,12 +625,12 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, stats->flag |= RX_FLAG_RADIOTAP; } -static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, +static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb, struct ieee80211_rx_status *stats) { - struct ieee80211_hdr *hdr; struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); short len = le16_to_cpu(rx_hdr->len); @@ -635,8 +652,6 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, /* Set the size of the skb to the size of the frame */ skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); - hdr = (void *)rxb->skb->data; - if (iwl3945_param_hwcrypto) iwl3945_set_decrypted_flag(priv, rxb->skb, le32_to_cpu(rx_end->status), stats); @@ -645,7 +660,7 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats); #ifdef CONFIG_IWL3945_LEDS - if (is_data) + if (ieee80211_is_data(hdr->frame_control)) priv->rxtxpackets += len; #endif ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); @@ -694,7 +709,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, } if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { - iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); + iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); return; } @@ -842,27 +857,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, } } - iwl3945_handle_data_packet(priv, 0, rxb, &rx_status); - break; - - case IEEE80211_FTYPE_CTL: - break; - - case IEEE80211_FTYPE_DATA: { - DECLARE_MAC_BUF(mac1); - DECLARE_MAC_BUF(mac2); - DECLARE_MAC_BUF(mac3); - - if (unlikely(iwl3945_is_duplicate_packet(priv, header))) - IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n", - print_mac(mac1, header->addr1), - print_mac(mac2, header->addr2), - print_mac(mac3, header->addr3)); - else - iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); + case IEEE80211_FTYPE_DATA: + /* fall through */ + default: + iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); break; } - } } int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 9c0a09eaca6..a7ef59bd194 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -510,8 +510,6 @@ struct iwl3945_ucode { u8 data[0]; /* data in same order as "size" elements */ }; -#define IWL_IBSS_MAC_HASH_SIZE 32 - struct iwl3945_ibss_seq { u8 mac[ETH_ALEN]; u16 seq_num; @@ -569,17 +567,8 @@ extern int iwl3945_send_add_station(struct iwl3945_priv *priv, struct iwl3945_addsta_cmd *sta, u8 flags); extern u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *bssid, int is_ap, u8 flags); -extern int iwl3945_is_network_packet(struct iwl3945_priv *priv, - struct ieee80211_hdr *header); extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); -extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb, - void *data, short len, - struct ieee80211_rx_status *stats, - u16 phy_flags); -extern int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, - struct ieee80211_hdr *header); extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv); extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq); @@ -859,14 +848,6 @@ struct iwl3945_priv { u32 last_beacon_time; u64 last_tsf; - /* Duplicate packet detection */ - u16 last_seq_num; - u16 last_frag_num; - unsigned long last_packet_time; - - /* Hash table for finding stations in IBSS network */ - struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE]; - /* eeprom */ struct iwl3945_eeprom eeprom; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c8d3d97cf48..163502dabf6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -490,8 +490,6 @@ struct iwl_ucode { u8 data[0]; /* data in same order as "size" elements */ }; -#define IWL_IBSS_MAC_HASH_SIZE 32 - struct iwl4965_ibss_seq { u8 mac[ETH_ALEN]; u16 seq_num; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7d015f86ee8..4a22d3fba75 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2035,36 +2035,6 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) return rc; } -int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) -{ - /* Filter incoming packets to determine if they are targeted toward - * this network, discarding packets coming from ourselves */ - switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ - /* packets from our adapter are dropped (echo) */ - if (!compare_ether_addr(header->addr2, priv->mac_addr)) - return 0; - /* {broad,multi}cast packets to our IBSS go through */ - if (is_multicast_ether_addr(header->addr1)) - return !compare_ether_addr(header->addr3, priv->bssid); - /* packets to our adapter go through */ - return !compare_ether_addr(header->addr1, priv->mac_addr); - case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ - /* packets from our adapter are dropped (echo) */ - if (!compare_ether_addr(header->addr3, priv->mac_addr)) - return 0; - /* {broad,multi}cast packets to our BSS go through */ - if (is_multicast_ether_addr(header->addr1)) - return !compare_ether_addr(header->addr2, priv->bssid); - /* packets to our adapter go through */ - return !compare_ether_addr(header->addr1, priv->mac_addr); - default: - return 1; - } - - return 1; -} - /** * iwl3945_scan_cancel - Cancel any currently executing HW scan * @@ -2117,20 +2087,6 @@ static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long return ret; } -static void iwl3945_sequence_reset(struct iwl3945_priv *priv) -{ - /* Reset ieee stats */ - - /* We don't reset the net_device_stats (ieee->stats) on - * re-association */ - - priv->last_seq_num = -1; - priv->last_frag_num = -1; - priv->last_packet_time = 0; - - iwl3945_scan_cancel(priv); -} - #define MAX_UCODE_BEACON_INTERVAL 1024 #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) @@ -2925,72 +2881,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, } } -#define IWL_PACKET_RETRY_TIME HZ - -int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) -{ - u16 sc = le16_to_cpu(header->seq_ctrl); - u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4; - u16 frag = sc & IEEE80211_SCTL_FRAG; - u16 *last_seq, *last_frag; - unsigned long *last_time; - - switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_IBSS:{ - struct list_head *p; - struct iwl3945_ibss_seq *entry = NULL; - u8 *mac = header->addr2; - int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1); - - __list_for_each(p, &priv->ibss_mac_hash[index]) { - entry = list_entry(p, struct iwl3945_ibss_seq, list); - if (!compare_ether_addr(entry->mac, mac)) - break; - } - if (p == &priv->ibss_mac_hash[index]) { - entry = kzalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) { - IWL_ERROR("Cannot malloc new mac entry\n"); - return 0; - } - memcpy(entry->mac, mac, ETH_ALEN); - entry->seq_num = seq; - entry->frag_num = frag; - entry->packet_time = jiffies; - list_add(&entry->list, &priv->ibss_mac_hash[index]); - return 0; - } - last_seq = &entry->seq_num; - last_frag = &entry->frag_num; - last_time = &entry->packet_time; - break; - } - case IEEE80211_IF_TYPE_STA: - last_seq = &priv->last_seq_num; - last_frag = &priv->last_frag_num; - last_time = &priv->last_packet_time; - break; - default: - return 0; - } - if ((*last_seq == seq) && - time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) { - if (*last_frag == frag) - goto drop; - if (*last_frag + 1 != frag) - /* out-of-order fragment */ - goto drop; - } else - *last_seq = seq; - - *last_frag = frag; - *last_time = jiffies; - return 0; - - drop: - return 1; -} - #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT #include "iwl-spectrum.h" @@ -6531,8 +6421,6 @@ static void iwl3945_bg_post_associate(struct work_struct *data) break; } - iwl3945_sequence_reset(priv); - iwl3945_activate_qos(priv, 0); /* we have just associated, don't start scan too early */ @@ -7963,7 +7851,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e struct iwl3945_priv *priv; struct ieee80211_hw *hw; struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); - int i; unsigned long flags; DECLARE_MAC_BUF(mac); @@ -8024,9 +7911,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); - for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) - INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); - INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); @@ -8199,8 +8083,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) { struct iwl3945_priv *priv = pci_get_drvdata(pdev); - struct list_head *p, *q; - int i; unsigned long flags; if (!priv) @@ -8221,14 +8103,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl_synchronize_irq(priv); - /* Free MAC hash list for ADHOC */ - for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { - list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { - list_del(p); - kfree(list_entry(p, struct iwl3945_ibss_seq, list)); - } - } - sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); iwl3945_rfkill_unregister(priv); -- cgit v1.2.3-18-g5258 From 474086396276a01190974797a69a95fb14ae7cc9 Mon Sep 17 00:00:00 2001 From: Esti Kummer Date: Fri, 11 Jul 2008 11:53:30 +0800 Subject: iwlwifi: adding pci device ids to iwl_hw_card_ids The patch adds PCI device IDs to iwl_hw_card_ids. Signed-off-by: Esti Kummer Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 18 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 10 +++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 717db0d5ffb..3697d033510 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1506,6 +1506,24 @@ struct iwl_cfg iwl5300_agn_cfg = { .mod_params = &iwl50_mod_params, }; +struct iwl_cfg iwl5100_bg_cfg = { + .name = "5100BG", + .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", + .sku = IWL_SKU_G, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .mod_params = &iwl50_mod_params, +}; + +struct iwl_cfg iwl5100_abg_cfg = { + .name = "5100ABG", + .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", + .sku = IWL_SKU_A|IWL_SKU_G, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .mod_params = &iwl50_mod_params, +}; + struct iwl_cfg iwl5100_agn_cfg = { .name = "5100AGN", .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 163502dabf6..0177a1deabd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -51,6 +51,8 @@ extern struct iwl_cfg iwl4965_agn_cfg; extern struct iwl_cfg iwl5300_agn_cfg; extern struct iwl_cfg iwl5100_agn_cfg; extern struct iwl_cfg iwl5350_agn_cfg; +extern struct iwl_cfg iwl5100_bg_cfg; +extern struct iwl_cfg iwl5100_abg_cfg; /* Change firmware file name, using "-" and incrementing number, * *only* when uCode interface or architecture changes so that it diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d6fe0ded59d..aca67d4a305 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -4421,8 +4421,16 @@ static struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, #ifdef CONFIG_IWL5000 - {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, + {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)}, + {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, + {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)}, + {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)}, {IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)}, #endif /* CONFIG_IWL5000 */ {0} -- cgit v1.2.3-18-g5258 From a326a5d096f031af46c0073dd78eb80dea1f311a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 11 Jul 2008 11:53:31 +0800 Subject: iwlwifi: fixes RTS / CTS support This patch fixes the RTS / CTS support in iwlwifi. 5000 will send CTS to self when allowed by spec, 4965 will send RTS or CTS to self according to mac80211 request. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 13 +++++++++++++ drivers/net/wireless/iwlwifi/iwl-5000.c | 11 +++++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-tx.c | 8 +------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 +++ 6 files changed, 37 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 04365b39279..e0e43bdb05e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -642,6 +642,18 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, data->beacon_count = 0; } +static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, + __le32 *tx_flags) +{ + if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + *tx_flags |= TX_CMD_FLG_RTS_MSK; + *tx_flags &= ~TX_CMD_FLG_CTS_MSK; + } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + *tx_flags &= ~TX_CMD_FLG_RTS_MSK; + *tx_flags |= TX_CMD_FLG_CTS_MSK; + } +} + static void iwl4965_bg_txpower_work(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, @@ -2372,6 +2384,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .build_addsta_hcmd = iwl4965_build_addsta_hcmd, .chain_noise_reset = iwl4965_chain_noise_reset, .gain_computation = iwl4965_gain_computation, + .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, }; static struct iwl_lib_ops iwl4965_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 3697d033510..b518792c723 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -370,6 +370,16 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) } } +static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, + __le32 *tx_flags) +{ + if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || + (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) + *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; + else + *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; +} + static struct iwl_sensitivity_ranges iwl5000_sensitivity = { .min_nrg_cck = 95, .max_nrg_cck = 0, @@ -1437,6 +1447,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .build_addsta_hcmd = iwl5000_build_addsta_hcmd, .gain_computation = iwl5000_gain_computation, .chain_noise_reset = iwl5000_chain_noise_reset, + .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, }; static struct iwl_lib_ops iwl5000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index fe05d60ebe6..d877039e2d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -556,6 +556,8 @@ enum { #define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3 << 25) #define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1 << 25) #define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2 << 25) +/* CTS to self (if spec allows) flag */ +#define RXON_FLG_SELF_CTS_EN __constant_cpu_to_le32(0x1<<30) /* rx_config filter flags */ /* accept all data frames */ @@ -1139,6 +1141,11 @@ struct iwl4965_rx_mpdu_res_start { /* REPLY_TX Tx flags field */ +/* 1: Use RTS/CTS protocol or CTS-to-self if spec alows it + * before this frame. if CTS-to-self required check + * RXON_FLG_SELF_CTS_EN status. */ +#define TX_CMD_FLG_RTS_CTS_MSK __constant_cpu_to_le32(1 << 0) + /* 1: Use Request-To-Send protocol before this frame. * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ #define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index dafd62c7dfd..8d18227dc4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -93,6 +93,8 @@ struct iwl_hcmd_utils_ops { u16 min_average_noise_antennat_i, u32 min_average_noise); void (*chain_noise_reset)(struct iwl_priv *priv); + void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, + __le32 *tx_flags); }; struct iwl_lib_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 0be2a71990b..9b50b1052b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -601,13 +601,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { - tx_flags |= TX_CMD_FLG_RTS_MSK; - tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { - tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_flags |= TX_CMD_FLG_CTS_MSK; - } + priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index aca67d4a305..516508f5fd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -250,6 +250,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) /* always get timestamp with Rx frame */ priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; + /* allow CTS-to-self if possible. this is relevant only for + * 5000, but will not damage 4965 */ + priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; ret = iwl4965_check_rxon_cmd(&priv->staging_rxon); if (ret) { -- cgit v1.2.3-18-g5258 From 65fdbb48eb43e33e94239677a75422ddc6f5eb75 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 11 Jul 2008 11:53:32 +0800 Subject: iwlwifi: remove post associate work This patch removes post associate work. It wasn't used. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl4965-base.c | 18 ------------------ 2 files changed, 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0177a1deabd..81a57cb2266 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1065,7 +1065,6 @@ struct iwl_priv { struct delayed_work init_alive_start; struct delayed_work alive_start; struct delayed_work scan_check; - struct delayed_work post_associate; /* TX Power */ s8 tx_power_user_lmt; s8 tx_power_channel_lmt; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 516508f5fd4..fbb854e31bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2520,18 +2520,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } - -static void iwl4965_bg_post_associate(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, - post_associate.work); - - mutex_lock(&priv->mutex); - iwl4965_post_associate(priv); - mutex_unlock(&priv->mutex); - -} - static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); static void iwl_bg_scan_completed(struct work_struct *work) @@ -2662,7 +2650,6 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw) */ mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); - cancel_delayed_work(&priv->post_associate); mutex_unlock(&priv->mutex); } @@ -3064,7 +3051,6 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, if (iwl_is_ready_rf(priv)) { iwl_scan_cancel_timeout(priv, 100); - cancel_delayed_work(&priv->post_associate); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); } @@ -3429,8 +3415,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) iwl_reset_qos(priv); - cancel_delayed_work(&priv->post_associate); - spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = 0; priv->assoc_capability = 0; @@ -4032,7 +4016,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update); INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor); INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); - INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate); INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); @@ -4059,7 +4042,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); - cancel_delayed_work(&priv->post_associate); cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); } -- cgit v1.2.3-18-g5258 From 6c5379077f47f6eff9c23caf8513751d2f582e72 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 11 Jul 2008 11:53:33 +0800 Subject: iwlwifi: rs always set lq_sta->priv This patch fixes printk NULL pointer exceptions in rs code. Signed-off-by: Tomas Winkler Signed-off-by: Guy Cohen Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index c7ebb3bf06f..3ccb84aa5db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -2265,9 +2265,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, /* as default allow aggregation for all tids */ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; -#ifdef CONFIG_MAC80211_DEBUGFS lq_sta->drv = priv; -#endif rs_initialize_lq(priv, conf, sta); } -- cgit v1.2.3-18-g5258 From 1ff50bda6eef4466366e197541508fc69af0f0c0 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 11 Jul 2008 11:53:34 +0800 Subject: iwlwifi: make iwl4965_mac_conf_tx in atomic context This patch fixes iwl4965_mac_conf_tx. A mutex was taken in atomic context leading to Oops. This patch removes the mutex and extends the hold priv->lock. None of the field of QOS is accessed without priv->lock held. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 6 ++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 12 ++++----- drivers/net/wireless/iwlwifi/iwl4965-base.c | 39 +++++++++++------------------ 3 files changed, 24 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index d877039e2d4..92754ee49e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -725,7 +725,7 @@ struct iwl4965_csa_notification { * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW * value, to cap the CW value. */ -struct iwl4965_ac_qos { +struct iwl_ac_qos { __le16 cw_min; __le16 cw_max; u8 aifsn; @@ -747,9 +747,9 @@ struct iwl4965_ac_qos { * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs * 0: Background, 1: Best Effort, 2: Video, 3: Voice. */ -struct iwl4965_qosparam_cmd { +struct iwl_qosparam_cmd { __le32 qos_flags; - struct iwl4965_ac_qos ac[AC_NUM]; + struct iwl_ac_qos ac[AC_NUM]; } __attribute__ ((packed)); /****************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 81a57cb2266..92a37664d45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -290,7 +290,7 @@ struct iwl_cmd { struct iwl4965_bt_cmd bt; struct iwl4965_rxon_time_cmd rxon_time; struct iwl4965_powertable_cmd powertable; - struct iwl4965_qosparam_cmd qosparam; + struct iwl_qosparam_cmd qosparam; struct iwl_tx_cmd tx; struct iwl4965_tx_beacon_cmd tx_beacon; struct iwl4965_rxon_assoc_cmd rxon_assoc; @@ -435,7 +435,7 @@ struct iwl_ht_info { u8 non_GF_STA_present; }; -union iwl4965_qos_capabity { +union iwl_qos_capabity { struct { u8 edca_count:4; /* bit 0-3 */ u8 q_ack:1; /* bit 4 */ @@ -456,11 +456,11 @@ union iwl4965_qos_capabity { }; /* QoS structures */ -struct iwl4965_qos_info { +struct iwl_qos_info { int qos_enable; int qos_active; - union iwl4965_qos_capabity qos_cap; - struct iwl4965_qosparam_cmd def_qos_parm; + union iwl_qos_capabity qos_cap; + struct iwl_qosparam_cmd def_qos_parm; }; #define STA_PS_STATUS_WAKE 0 @@ -1042,7 +1042,7 @@ struct iwl_priv { u16 assoc_capability; u8 ps_mode; - struct iwl4965_qos_info qos_data; + struct iwl_qos_info qos_data; struct workqueue_struct *workqueue; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index fbb854e31bd..55648a8c88a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -575,25 +575,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, /* * QoS support */ -static int iwl4965_send_qos_params_command(struct iwl_priv *priv, - struct iwl4965_qosparam_cmd *qos) +static void iwl_activate_qos(struct iwl_priv *priv, u8 force) { - - return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM, - sizeof(struct iwl4965_qosparam_cmd), qos); -} - -static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) -{ - unsigned long flags; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (!priv->qos_data.qos_enable) return; - spin_lock_irqsave(&priv->lock, flags); priv->qos_data.def_qos_parm.qos_flags = 0; if (priv->qos_data.qos_cap.q_AP.queue_request && @@ -607,15 +596,14 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) if (priv->current_ht_config.is_ht) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; - spin_unlock_irqrestore(&priv->lock, flags); - if (force || iwl_is_associated(priv)) { IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", priv->qos_data.qos_active, priv->qos_data.def_qos_parm.qos_flags); - iwl4965_send_qos_params_command(priv, - &(priv->qos_data.def_qos_parm)); + iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, + sizeof(struct iwl_qosparam_cmd), + &priv->qos_data.def_qos_parm, NULL); } } @@ -2424,6 +2412,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) struct ieee80211_conf *conf = NULL; int ret = 0; DECLARE_MAC_BUF(mac); + unsigned long flags; if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); @@ -2513,7 +2502,9 @@ static void iwl4965_post_associate(struct iwl_priv *priv) if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) priv->assoc_station_added = 1; - iwl4965_activate_qos(priv, 0); + spin_lock_irqsave(&priv->lock, flags); + iwl_activate_qos(priv, 0); + spin_unlock_irqrestore(&priv->lock, flags); iwl_power_update_mode(priv, 0); /* we have just associated, don't start scan too early */ @@ -2845,6 +2836,7 @@ out: static void iwl4965_config_ap(struct iwl_priv *priv) { int ret = 0; + unsigned long flags; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -2892,7 +2884,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); - iwl4965_activate_qos(priv, 1); + spin_lock_irqsave(&priv->lock, flags); + iwl_activate_qos(priv, 1); + spin_unlock_irqrestore(&priv->lock, flags); iwl_rxon_add_station(priv, iwl_bcast_addr, 0); } iwl4965_send_beacon_cmd(priv); @@ -3340,15 +3334,12 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; priv->qos_data.qos_active = 1; - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); if (priv->iw_mode == IEEE80211_IF_TYPE_AP) - iwl4965_activate_qos(priv, 1); + iwl_activate_qos(priv, 1); else if (priv->assoc_id && iwl_is_associated(priv)) - iwl4965_activate_qos(priv, 0); + iwl_activate_qos(priv, 0); - mutex_unlock(&priv->mutex); + spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_MAC80211("leave\n"); return 0; -- cgit v1.2.3-18-g5258 From 9f17b318a1e2335b45cf35ad6509b90e972c0e6b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 11 Jul 2008 11:53:35 +0800 Subject: iwlwifi: differentiate 4965 and 5000 hw ampdu queues number This patch asks to allocate the correct amount of sw queues according to hw ampdu queues number. Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 1 + drivers/net/wireless/iwlwifi/iwl-4965.c | 19 +++++++++++++------ drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 19 +++++++++++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + 6 files changed, 30 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 10f630e1afa..fce950f4163 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -819,6 +819,7 @@ enum { #define IWL49_NUM_FIFOS 7 #define IWL49_CMD_FIFO_NUM 4 #define IWL49_NUM_QUEUES 16 +#define IWL49_NUM_AMPDU_QUEUES 8 /** * struct iwl_tfd_frame_data diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e0e43bdb05e..a20adab6163 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -52,6 +52,7 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); /* module parameters */ static struct iwl_mod_params iwl4965_mod_params = { .num_of_queues = IWL49_NUM_QUEUES, + .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, .enable_qos = 1, .amsdu_size_8K = 1, .restart_fw = 1, @@ -1943,9 +1944,11 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, { int ret = 0; - if (IWL49_FIRST_AMPDU_QUEUE > txq_id) { - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL49_FIRST_AMPDU_QUEUE); + if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || + (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { + IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + txq_id, IWL49_FIRST_AMPDU_QUEUE, + IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); return -EINVAL; } @@ -2012,9 +2015,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, int ret; u16 ra_tid; - if (IWL49_FIRST_AMPDU_QUEUE > txq_id) - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL49_FIRST_AMPDU_QUEUE); + if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || + (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { + IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + txq_id, IWL49_FIRST_AMPDU_QUEUE, + IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); + return -EINVAL; + } ra_tid = BUILD_RAxTID(sta_id, tid); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 4efe0c06b5b..17d4f31c593 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -81,6 +81,7 @@ #define IWL50_QUEUE_SIZE 256 #define IWL50_CMD_FIFO_NUM 7 #define IWL50_NUM_QUEUES 20 +#define IWL50_NUM_AMPDU_QUEUES 10 #define IWL50_FIRST_AMPDU_QUEUE 10 #define IWL_sta_id_POS 12 diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index b518792c723..878d6193b23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1016,9 +1016,13 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, int ret; u16 ra_tid; - if (IWL50_FIRST_AMPDU_QUEUE > txq_id) - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE); + if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || + (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { + IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + txq_id, IWL50_FIRST_AMPDU_QUEUE, + IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); + return -EINVAL; + } ra_tid = BUILD_RAxTID(sta_id, tid); @@ -1077,9 +1081,11 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, { int ret; - if (IWL50_FIRST_AMPDU_QUEUE > txq_id) { - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE); + if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || + (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { + IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + txq_id, IWL50_FIRST_AMPDU_QUEUE, + IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); return -EINVAL; } @@ -1501,6 +1507,7 @@ static struct iwl_ops iwl5000_ops = { static struct iwl_mod_params iwl50_mod_params = { .num_of_queues = IWL50_NUM_QUEUES, + .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, .enable_qos = 1, .amsdu_size_8K = 1, .restart_fw = 1, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index eee220cf52a..a44188bf445 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -825,7 +825,7 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->queues = 4; /* queues to support 11n aggregation */ if (priv->cfg->sku & IWL_SKU_N) - hw->ampdu_queues = 12; + hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues; hw->conf.beacon_int = 100; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8d18227dc4b..0293ae91c35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -159,6 +159,7 @@ struct iwl_mod_params { int debug; /* def: 0 = minimal debug log messages */ int disable_hw_scan; /* def: 0 = use h/w scan */ int num_of_queues; /* def: HW dependent */ + int num_of_ampdu_queues;/* def: HW dependent */ int enable_qos; /* def: 1 = use quality of service */ int disable_11n; /* def: 0 = disable 11n capabilities */ int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ -- cgit v1.2.3-18-g5258 From 0eee612731e133604023bfa8d20047e98160845e Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 11 Jul 2008 11:53:36 +0800 Subject: iwlwifi: fix LED stall This patch fixes LED stall. last_blink_time was updated only if LED command was sent, causing wrong computation of the througput. Some code cleanup comes with this patch as well Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 85 +++++++++++++++------------------- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- 3 files changed, 39 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 92a37664d45..bd06e0f8711 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -933,7 +933,7 @@ struct iwl_priv { #endif #ifdef CONFIG_IWLWIFI_LEDS - struct iwl4965_led led[IWL_LED_TRG_MAX]; + struct iwl_led led[IWL_LED_TRG_MAX]; unsigned long last_blink_time; u8 last_blink_rate; u8 allow_blinking; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index aa6ad18494c..afd10758c03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -48,10 +48,21 @@ #define IWL_LED_THRESHOLD (16) #define IWL_MAX_BLINK_TBL (10) +#ifdef CONFIG_IWLWIFI_DEBUG +static const char *led_type_str[] = { + __stringify(IWL_LED_TRG_TX), + __stringify(IWL_LED_TRG_RX), + __stringify(IWL_LED_TRG_ASSOC), + __stringify(IWL_LED_TRG_RADIO), + NULL +}; +#endif /* CONFIG_IWLWIFI_DEBUG */ + + static const struct { u16 tpt; u8 on_time; - u8 of_time; + u8 off_time; } blink_tbl[] = { {300, 25, 25}, @@ -155,21 +166,6 @@ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) return 0; } -/* Set led blink command */ -static int iwl4965_led_not_solid(struct iwl_priv *priv, int led_id, - u8 brightness) -{ - struct iwl4965_led_cmd led_cmd = { - .id = led_id, - .on = brightness, - .off = brightness, - .interval = IWL_DEF_LED_INTRVL - }; - - return iwl_send_led_cmd(priv, &led_cmd); -} - - /* * brightness call back function for Tx/Rx LED */ @@ -189,16 +185,18 @@ static int iwl4965_led_associated(struct iwl_priv *priv, int led_id) /* * brightness call back for association and radio */ -static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, +static void iwl_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct iwl4965_led *led = container_of(led_cdev, - struct iwl4965_led, led_dev); + struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev); struct iwl_priv *priv = led->priv; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + + IWL_DEBUG_LED("Led type = %s brightness = %d\n", + led_type_str[led->type], brightness); switch (brightness) { case LED_FULL: if (led->type == IWL_LED_TRG_ASSOC) @@ -226,8 +224,7 @@ static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, /* * Register led class with the system */ -static int iwl_leds_register_led(struct iwl_priv *priv, - struct iwl4965_led *led, +static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, enum led_type type, u8 set_led, const char *name, char *trigger) { @@ -235,7 +232,7 @@ static int iwl_leds_register_led(struct iwl_priv *priv, int ret; led->led_dev.name = name; - led->led_dev.brightness_set = iwl4965_led_brightness_set; + led->led_dev.brightness_set = iwl_led_brightness_set; led->led_dev.default_trigger = trigger; led->priv = priv; @@ -263,12 +260,14 @@ static inline u8 get_blink_rate(struct iwl_priv *priv) { int i; u8 blink_rate; - u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes; + u64 current_tpt = priv->tx_stats[2].bytes; + /* FIXME: + priv->rx_stats[2].bytes; */ s64 tpt = current_tpt - priv->led_tpt; if (tpt < 0) /* wrapparound */ tpt = -tpt; + IWL_DEBUG_LED("tpt %lld current_tpt %lld\n", tpt, current_tpt); priv->led_tpt = current_tpt; if (tpt < IWL_LED_THRESHOLD) { @@ -329,15 +328,13 @@ void iwl_leds_background(struct iwl_priv *priv) /* call only if blink rate change */ if (blink_rate != priv->last_blink_rate) { if (blink_rate != IWL_LED_SOLID) { - priv->last_blink_time = jiffies + - msecs_to_jiffies(1000); - iwl4965_led_not_solid(priv, IWL_LED_LINK, blink_rate); + iwl4965_led_pattern(priv, IWL_LED_LINK, blink_rate); } else { - priv->last_blink_time = 0; iwl4965_led_on(priv, IWL_LED_LINK); } } + priv->last_blink_time = jiffies; priv->last_blink_rate = blink_rate; } EXPORT_SYMBOL(iwl_leds_background); @@ -362,10 +359,8 @@ int iwl_leds_register(struct iwl_priv *priv) priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg; priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; - ret = iwl_leds_register_led(priv, - &priv->led[IWL_LED_TRG_RADIO], - IWL_LED_TRG_RADIO, 1, - name, trigger); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], + IWL_LED_TRG_RADIO, 1, name, trigger); if (ret) goto exit_fail; @@ -373,10 +368,9 @@ int iwl_leds_register(struct iwl_priv *priv) snprintf(name, sizeof(name), "iwl-%s:assoc", wiphy_name(priv->hw->wiphy)); - ret = iwl_leds_register_led(priv, - &priv->led[IWL_LED_TRG_ASSOC], - IWL_LED_TRG_ASSOC, 0, - name, trigger); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], + IWL_LED_TRG_ASSOC, 0, name, trigger); + /* for assoc always turn led on */ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg; priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg; @@ -386,14 +380,11 @@ int iwl_leds_register(struct iwl_priv *priv) goto exit_fail; trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:RX", - wiphy_name(priv->hw->wiphy)); + snprintf(name, sizeof(name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy)); - ret = iwl_leds_register_led(priv, - &priv->led[IWL_LED_TRG_RX], - IWL_LED_TRG_RX, 0, - name, trigger); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], + IWL_LED_TRG_RX, 0, name, trigger); priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated; priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated; @@ -403,12 +394,10 @@ int iwl_leds_register(struct iwl_priv *priv) goto exit_fail; trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:TX", - wiphy_name(priv->hw->wiphy)); - ret = iwl_leds_register_led(priv, - &priv->led[IWL_LED_TRG_TX], - IWL_LED_TRG_TX, 0, - name, trigger); + snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], + IWL_LED_TRG_TX, 0, name, trigger); + priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated; priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated; priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern; @@ -425,7 +414,7 @@ exit_fail: EXPORT_SYMBOL(iwl_leds_register); /* unregister led class */ -static void iwl_leds_unregister_led(struct iwl4965_led *led, u8 set_led) +static void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led) { if (!led->registered) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 5bb04128cd6..c9466d5373e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -49,7 +49,7 @@ enum led_type { }; -struct iwl4965_led { +struct iwl_led { struct iwl_priv *priv; struct led_classdev led_dev; -- cgit v1.2.3-18-g5258 From ec1a746042ea4c1c93065185897d6e8d3e7de894 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 11 Jul 2008 11:53:37 +0800 Subject: iwlwifi: LED use correctly blink table This patch makes correct usage of the LED blink table. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 125 +++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-led.h | 3 +- 4 files changed, 61 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 92754ee49e4..3e96df8e810 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2926,7 +2926,7 @@ struct iwl5000_calibration_chain_noise_gain_cmd { * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field), * this command turns it on or off, or sets up a periodic blinking cycle. */ -struct iwl4965_led_cmd { +struct iwl_led_cmd { __le32 interval; /* "interval" in uSec */ u8 id; /* 1: Activity, 2: Link, 3: Tech */ u8 off; /* # intervals off while blinking; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bd06e0f8711..84a3ecfec48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -282,7 +282,7 @@ struct iwl_cmd { struct iwl_cmd_header hdr; /* uCode API */ union { struct iwl_addsta_cmd addsta; - struct iwl4965_led_cmd led; + struct iwl_led_cmd led; u32 flags; u8 val8; u16 val16; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index afd10758c03..0c09b901a25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -44,10 +44,6 @@ #include "iwl-io.h" #include "iwl-helpers.h" -#define IWL_1MB_RATE (128 * 1024) -#define IWL_LED_THRESHOLD (16) -#define IWL_MAX_BLINK_TBL (10) - #ifdef CONFIG_IWLWIFI_DEBUG static const char *led_type_str[] = { __stringify(IWL_LED_TRG_TX), @@ -74,26 +70,31 @@ static const struct { {15, 95, 95 }, {10, 110, 110}, {5, 130, 130}, - {0, 167, 167} + {0, 167, 167}, +/* SOLID_ON */ + {-1, IWL_LED_SOLID, 0} }; -static int iwl_led_cmd_callback(struct iwl_priv *priv, - struct iwl_cmd *cmd, struct sk_buff *skb) +#define IWL_1MB_RATE (128 * 1024) +#define IWL_LED_THRESHOLD (16) +#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ +#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) + +/* [0-256] -> [0..8] FIXME: we need [0..10] */ +static inline int iwl_brightness_to_idx(enum led_brightness brightness) { - return 1; + return fls(0x000000FF & (u32)brightness); } - /* Send led command */ -static int iwl_send_led_cmd(struct iwl_priv *priv, - struct iwl4965_led_cmd *led_cmd) +static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) { struct iwl_host_cmd cmd = { .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl4965_led_cmd), + .len = sizeof(struct iwl_led_cmd), .data = led_cmd, .meta.flags = CMD_ASYNC, - .meta.u.callback = iwl_led_cmd_callback + .meta.u.callback = NULL, }; u32 reg; @@ -104,33 +105,19 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, return iwl_send_cmd(priv, &cmd); } - -/* Set led on command */ -static int iwl4965_led_on(struct iwl_priv *priv, int led_id) +/* Set led pattern command */ +static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, int idx) { - struct iwl4965_led_cmd led_cmd = { + struct iwl_led_cmd led_cmd = { .id = led_id, - .on = IWL_LED_SOLID, - .off = 0, .interval = IWL_DEF_LED_INTRVL }; - return iwl_send_led_cmd(priv, &led_cmd); -} -/* Set led on command */ -static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, - enum led_brightness brightness) -{ - struct iwl4965_led_cmd led_cmd = { - .id = led_id, - .on = brightness, - .off = brightness, - .interval = IWL_DEF_LED_INTRVL - }; - if (brightness == LED_FULL) { - led_cmd.on = IWL_LED_SOLID; - led_cmd.off = 0; - } + BUG_ON(idx > IWL_MAX_BLINK_TBL); + + led_cmd.on = blink_tbl[idx].on_time; + led_cmd.off = blink_tbl[idx].off_time; + return iwl_send_led_cmd(priv, &led_cmd); } @@ -143,10 +130,22 @@ static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) } #if 0 +/* Set led on command */ +static int iwl4965_led_on(struct iwl_priv *priv, int led_id) +{ + struct iwl_led_cmd led_cmd = { + .id = led_id, + .on = IWL_LED_SOLID, + .off = 0, + .interval = IWL_DEF_LED_INTRVL + }; + return iwl_send_led_cmd(priv, &led_cmd); +} + /* Set led off command */ int iwl4965_led_off(struct iwl_priv *priv, int led_id) { - struct iwl4965_led_cmd led_cmd = { + struct iwl_led_cmd led_cmd = { .id = led_id, .on = 0, .off = 0, @@ -169,7 +168,7 @@ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) /* * brightness call back function for Tx/Rx LED */ -static int iwl4965_led_associated(struct iwl_priv *priv, int led_id) +static int iwl_led_associated(struct iwl_priv *priv, int led_id) { if (test_bit(STATUS_EXIT_PENDING, &priv->status) || !test_bit(STATUS_READY, &priv->status)) @@ -213,8 +212,10 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev, led->led_off(priv, IWL_LED_LINK); break; default: - if (led->led_pattern) - led->led_pattern(priv, IWL_LED_LINK, brightness); + if (led->led_pattern) { + int idx = iwl_brightness_to_idx(brightness); + led->led_pattern(priv, IWL_LED_LINK, idx); + } break; } } @@ -256,10 +257,9 @@ static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, /* * calculate blink rate according to last 2 sec Tx/Rx activities */ -static inline u8 get_blink_rate(struct iwl_priv *priv) +static int iwl_get_blink_rate(struct iwl_priv *priv) { int i; - u8 blink_rate; u64 current_tpt = priv->tx_stats[2].bytes; /* FIXME: + priv->rx_stats[2].bytes; */ s64 tpt = current_tpt - priv->led_tpt; @@ -270,20 +270,15 @@ static inline u8 get_blink_rate(struct iwl_priv *priv) IWL_DEBUG_LED("tpt %lld current_tpt %lld\n", tpt, current_tpt); priv->led_tpt = current_tpt; - if (tpt < IWL_LED_THRESHOLD) { + if (!priv->allow_blinking) i = IWL_MAX_BLINK_TBL; - } else { + else for (i = 0; i < IWL_MAX_BLINK_TBL; i++) if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) break; - } - /* if 0 frame is transfered */ - if ((i == IWL_MAX_BLINK_TBL) || !priv->allow_blinking) - blink_rate = IWL_LED_SOLID; - else - blink_rate = blink_tbl[i].on_time; - return blink_rate; + IWL_DEBUG_LED("LED BLINK IDX=%d", i); + return i; } static inline int is_rf_kill(struct iwl_priv *priv) @@ -299,7 +294,7 @@ static inline int is_rf_kill(struct iwl_priv *priv) */ void iwl_leds_background(struct iwl_priv *priv) { - u8 blink_rate; + u8 blink_idx; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { priv->last_blink_time = 0; @@ -312,9 +307,10 @@ void iwl_leds_background(struct iwl_priv *priv) if (!priv->allow_blinking) { priv->last_blink_time = 0; - if (priv->last_blink_rate != IWL_LED_SOLID) { - priv->last_blink_rate = IWL_LED_SOLID; - iwl4965_led_on(priv, IWL_LED_LINK); + if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { + priv->last_blink_rate = IWL_SOLID_BLINK_IDX; + iwl4965_led_pattern(priv, IWL_LED_LINK, + IWL_SOLID_BLINK_IDX); } return; } @@ -323,19 +319,14 @@ void iwl_leds_background(struct iwl_priv *priv) msecs_to_jiffies(1000))) return; - blink_rate = get_blink_rate(priv); + blink_idx = iwl_get_blink_rate(priv); /* call only if blink rate change */ - if (blink_rate != priv->last_blink_rate) { - if (blink_rate != IWL_LED_SOLID) { - iwl4965_led_pattern(priv, IWL_LED_LINK, blink_rate); - } else { - iwl4965_led_on(priv, IWL_LED_LINK); - } - } + if (blink_idx != priv->last_blink_rate) + iwl4965_led_pattern(priv, IWL_LED_LINK, blink_idx); priv->last_blink_time = jiffies; - priv->last_blink_rate = blink_rate; + priv->last_blink_rate = blink_idx; } EXPORT_SYMBOL(iwl_leds_background); @@ -386,8 +377,8 @@ int iwl_leds_register(struct iwl_priv *priv) ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], IWL_LED_TRG_RX, 0, name, trigger); - priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated; - priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated; + priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; + priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern; if (ret) @@ -398,8 +389,8 @@ int iwl_leds_register(struct iwl_priv *priv) ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], IWL_LED_TRG_TX, 0, name, trigger); - priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated; - priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated; + priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; + priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern; if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index c9466d5373e..05e6a6113b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -55,8 +55,7 @@ struct iwl_led { int (*led_on) (struct iwl_priv *priv, int led_id); int (*led_off) (struct iwl_priv *priv, int led_id); - int (*led_pattern) (struct iwl_priv *priv, int led_id, - enum led_brightness brightness); + int (*led_pattern) (struct iwl_priv *priv, int led_id, int idx); enum led_type type; unsigned int registered; -- cgit v1.2.3-18-g5258 From d16dc48a2ea14af9980d0ea79d041f4b53e47b62 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 11 Jul 2008 11:53:38 +0800 Subject: iwlwifi: unify 4965 and 5000 scanning code This patch unifies 4965 and 5000 scanning code. We increases the version number to 1.3.27. Since new uCode iwlwifi-4965-2.ucode is required for 4965 cards. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 10 ++++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 15 +++++++++------ drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 6 ------ drivers/net/wireless/iwlwifi/iwl-scan.c | 23 +++++++++++++---------- 5 files changed, 33 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a20adab6163..9afecb81371 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -49,6 +49,13 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv); static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); +/* Change firmware file name, using "-" and incrementing number, + * *only* when uCode interface or architecture changes so that it + * is not compatible with earlier drivers. + * This number will also appear in << 8 position of 1st dword of uCode file */ +#define IWL4965_UCODE_API "-2" + + /* module parameters */ static struct iwl_mod_params iwl4965_mod_params = { .num_of_queues = IWL49_NUM_QUEUES, @@ -2454,6 +2461,9 @@ struct iwl_cfg iwl4965_agn_cfg = { .mod_params = &iwl4965_mod_params, }; +/* Module firmware */ +MODULE_FIRMWARE("iwlwifi-4965" IWL4965_UCODE_API ".ucode"); + module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(disable, iwl4965_mod_params.disable, int, 0444); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 3e96df8e810..e9bb1de0ce3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2099,6 +2099,9 @@ struct iwl_ct_kill_config { * *****************************************************************************/ +#define SCAN_CHANNEL_TYPE_PASSIVE __constant_cpu_to_le32(0) +#define SCAN_CHANNEL_TYPE_ACTIVE __constant_cpu_to_le32(1) + /** * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table * @@ -2122,12 +2125,12 @@ struct iwl_scan_channel { /* * type is defined as: * 0:0 1 = active, 0 = passive - * 1:4 SSID direct bit map; if a bit is set, then corresponding + * 1:20 SSID direct bit map; if a bit is set, then corresponding * SSID IE is transmitted in probe request. - * 5:7 reserved + * 21:31 reserved */ - u8 type; - u8 channel; /* band is selected by iwl4965_scan_cmd "flags" field */ + __le32 type; + __le16 channel; /* band is selected by iwl_scan_cmd "flags" field */ u8 tx_gain; /* gain for analog radio */ u8 dsp_atten; /* gain for DSP */ __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ @@ -2147,9 +2150,9 @@ struct iwl_ssid_ie { u8 ssid[32]; } __attribute__ ((packed)); -#define PROBE_OPTION_MAX 0x4 +#define PROBE_OPTION_MAX 0x14 #define TX_CMD_LIFE_TIME_INFINITE __constant_cpu_to_le32(0xFFFFFFFF) -#define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1) +#define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 /* diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 0293ae91c35..db66114f1e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -70,7 +70,7 @@ struct iwl_host_cmd; struct iwl_cmd; -#define IWLWIFI_VERSION "1.2.26k" +#define IWLWIFI_VERSION "1.3.27k" #define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" #define IWL_PCI_DEVICE(dev, subdev, cfg) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 84a3ecfec48..4d789e353e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -54,12 +54,6 @@ extern struct iwl_cfg iwl5350_agn_cfg; extern struct iwl_cfg iwl5100_bg_cfg; extern struct iwl_cfg iwl5100_abg_cfg; -/* Change firmware file name, using "-" and incrementing number, - * *only* when uCode interface or architecture changes so that it - * is not compatible with earlier drivers. - * This number will also appear in << 8 position of 1st dword of uCode file */ -#define IWL4965_UCODE_API "-1" - /* CT-KILL constants */ #define CT_KILL_THRESHOLD 110 /* in Celsius */ diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5b420b43af5..cf24c2703c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -375,6 +375,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; + u16 channel; sband = iwl_get_hw_mode(priv, band); if (!sband) @@ -389,24 +390,25 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, if (channels[i].flags & IEEE80211_CHAN_DISABLED) continue; - scan_ch->channel = + channel = ieee80211_frequency_to_channel(channels[i].center_freq); + scan_ch->channel = cpu_to_le16(channel); - ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); + ch_info = iwl_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", - scan_ch->channel); + channel); continue; } if (!is_active || is_channel_passive(ch_info) || (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) - scan_ch->type = 0; + scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; else - scan_ch->type = 1; + scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; - if (scan_ch->type & 1) - scan_ch->type |= (direct_mask << 1); + if (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) + scan_ch->type |= cpu_to_le32(direct_mask << 1); scan_ch->active_dwell = cpu_to_le16(active_dwell); scan_ch->passive_dwell = cpu_to_le16(passive_dwell); @@ -425,9 +427,10 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, } IWL_DEBUG_SCAN("Scanning %d [%s %d]\n", - scan_ch->channel, - (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE", - (scan_ch->type & 1) ? + channel, + (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? + "ACTIVE" : "PASSIVE", + (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? active_dwell : passive_dwell); scan_ch++; -- cgit v1.2.3-18-g5258 From fe905f1d5a8404f45fa0df26e6a870bf1e3b5983 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 11 Jul 2008 11:53:39 +0800 Subject: iwlwifi: enable active scanning This patch enables active scan on active channels. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-scan.c | 86 +++++++++++++++++---------------- 1 file changed, 45 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index cf24c2703c9..efc750d2fc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -38,8 +38,11 @@ /* 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. */ -#define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */ -#define IWL_ACTIVE_DWELL_TIME_52 (10) +#define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ +#define IWL_ACTIVE_DWELL_TIME_52 (20) + +#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3) +#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2) /* For faster active scanning, scan will move to the next channel if fewer than * PLCP_QUIET_THRESH packets are heard on this channel within @@ -48,7 +51,7 @@ * no other traffic). * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ #define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ -#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */ +#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. * Must be set longer than active dwell time. @@ -58,10 +61,15 @@ #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 +#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) + + static int scan_tx_ant[3] = { RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK }; + + static int iwl_is_empty_essid(const char *essid, int essid_len) { /* Single white space is for Linksys APs */ @@ -226,8 +234,9 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", notif->channel, notif->band ? "bg" : "a", - notif->tsf_high, - notif->tsf_low, notif->status, notif->beacon_timer); + le32_to_cpu(notif->tsf_high), + le32_to_cpu(notif->tsf_low), + notif->status, notif->beacon_timer); } /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ @@ -332,19 +341,21 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) + enum ieee80211_band band, + u8 n_probes) { if (band == IEEE80211_BAND_5GHZ) - return IWL_ACTIVE_DWELL_TIME_52; + return IWL_ACTIVE_DWELL_TIME_52 + + IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); else - return IWL_ACTIVE_DWELL_TIME_24; + return IWL_ACTIVE_DWELL_TIME_24 + + IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); } static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) + enum ieee80211_band band) { - u16 active = iwl_get_active_dwell_time(priv, band); - u16 passive = (band != IEEE80211_BAND_5GHZ) ? + u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -358,15 +369,12 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; } - if (passive <= active) - passive = active + 1; - return passive; } static int iwl_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, - u8 is_active, u8 direct_mask, + u8 is_active, u8 n_probes, struct iwl_scan_channel *scan_ch) { const struct ieee80211_channel *channels = NULL; @@ -383,9 +391,12 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, channels = sband->channels; - active_dwell = iwl_get_active_dwell_time(priv, band); + active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); passive_dwell = iwl_get_passive_dwell_time(priv, band); + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + for (i = 0, added = 0; i < sband->n_channels; i++) { if (channels[i].flags & IEEE80211_CHAN_DISABLED) continue; @@ -407,8 +418,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, else scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; - if (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) - scan_ch->type |= cpu_to_le32(direct_mask << 1); + if ((scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) && n_probes) + scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); scan_ch->active_dwell = cpu_to_le16(active_dwell); scan_ch->passive_dwell = cpu_to_le16(passive_dwell); @@ -416,18 +427,17 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, /* Set txpower levels to defaults */ scan_ch->dsp_atten = 110; + /* NOTE: if we were doing 6Mb OFDM for scans we'd use + * power level: + * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; + */ if (band == IEEE80211_BAND_5GHZ) scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; - else { + else scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level: - * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; - */ - } - IWL_DEBUG_SCAN("Scanning %d [%s %d]\n", - channel, + IWL_DEBUG_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n", + channel, le32_to_cpu(scan_ch->type), (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE", (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? @@ -676,7 +686,7 @@ static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band) break; } } - + IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind); return scan_tx_ant[ind]; } @@ -696,7 +706,7 @@ static void iwl_bg_request_scan(struct work_struct *data) u32 tx_ant; u16 cmd_len; enum ieee80211_band band; - u8 direct_mask; + u8 n_probes = 2; u8 rx_chain = 0x7; /* bitmap: ABC chains */ conf = ieee80211_get_hw_conf(priv->hw); @@ -796,17 +806,16 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->direct_scan[0].len = priv->direct_ssid_len; memcpy(scan->direct_scan[0].ssid, priv->direct_ssid, priv->direct_ssid_len); - direct_mask = 1; + n_probes++; } else if (!iwl_is_associated(priv) && priv->essid_len) { IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n", iwl_escape_essid(priv->essid, priv->essid_len)); scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); - direct_mask = 1; + n_probes++; } else { IWL_DEBUG_SCAN("Start indirect scan.\n"); - direct_mask = 0; } scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; @@ -863,16 +872,11 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | RXON_FILTER_BCON_AWARE_MSK); - if (direct_mask) - scan->channel_count = - iwl_get_channels_for_scan(priv, band, 1, /* active */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); - else - scan->channel_count = - iwl_get_channels_for_scan(priv, band, 0, /* passive */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + scan->channel_count = + iwl_get_channels_for_scan(priv, band, 1, /* active */ + n_probes, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + if (scan->channel_count == 0) { IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); goto done; -- cgit v1.2.3-18-g5258 From 36da7d70e307f8650db1b1c7350d2161ca3829ef Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 11 Jul 2008 11:53:40 +0800 Subject: iwlwifi: send TXPOWER command after a new RXON command The patch fixes the problem that TXPOWER command is not sent after we issue a new RXON command which requires a tune. Otherwise we won't be able to Tx any frames. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl4965-base.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 55648a8c88a..71f5da3fe5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -328,16 +328,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) if (!priv->error_recovering) priv->start_calib = 0; - iwl_init_sensitivity(priv); - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ - ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - if (ret) { - IWL_ERROR("Error sending TX power (%d)\n", ret); - return ret; - } - /* Add the broadcast address so we can send broadcast frames */ if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == IWL_INVALID_STATION) { @@ -373,6 +363,16 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); } + iwl_init_sensitivity(priv); + + /* If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames */ + ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + if (ret) { + IWL_ERROR("Error sending TX power (%d)\n", ret); + return ret; + } + return 0; } -- cgit v1.2.3-18-g5258 From 9a9ad0cda72a651fc6b99fa9ec040a5d41005a88 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 11 Jul 2008 11:53:41 +0800 Subject: iwlwifi: Fix LEDs for 3945 The patch fixes LEDs problem for 3945. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 146 ++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-3945-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 1 + 3 files changed, 64 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 8b1528e52d4..6be1fe13fa5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -42,14 +42,11 @@ #include "iwl-3945.h" #include "iwl-helpers.h" -#define IWL_1MB_RATE (128 * 1024) -#define IWL_LED_THRESHOLD (16) -#define IWL_MAX_BLINK_TBL (10) static const struct { u16 brightness; u8 on_time; - u8 of_time; + u8 off_time; } blink_tbl[] = { {300, 25, 25}, @@ -61,9 +58,16 @@ static const struct { {15, 95, 95 }, {10, 110, 110}, {5, 130, 130}, - {0, 167, 167} + {0, 167, 167}, + /*SOLID_ON*/ + {-1, IWL_LED_SOLID, 0} }; +#define IWL_1MB_RATE (128 * 1024) +#define IWL_LED_THRESHOLD (16) +#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/ +#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) + static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, struct iwl3945_cmd *cmd, struct sk_buff *skb) @@ -71,6 +75,10 @@ static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, return 1; } +static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) +{ + return fls(0x000000FF & (u32)brightness); +} /* Send led command */ static int iwl_send_led_cmd(struct iwl3945_priv *priv, @@ -81,49 +89,45 @@ static int iwl_send_led_cmd(struct iwl3945_priv *priv, .len = sizeof(struct iwl3945_led_cmd), .data = led_cmd, .meta.flags = CMD_ASYNC, - .meta.u.callback = iwl3945_led_cmd_callback + .meta.u.callback = iwl3945_led_cmd_callback, }; return iwl3945_send_cmd(priv, &cmd); } + /* Set led on command */ -static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) +static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, + unsigned int idx) { struct iwl3945_led_cmd led_cmd = { .id = led_id, - .on = IWL_LED_SOLID, - .off = 0, .interval = IWL_DEF_LED_INTRVL }; + + BUG_ON(idx > IWL_MAX_BLINK_TBL); + + led_cmd.on = blink_tbl[idx].on_time; + led_cmd.off = blink_tbl[idx].off_time; + return iwl_send_led_cmd(priv, &led_cmd); } + +#if 1 /* Set led on command */ -static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, - enum led_brightness brightness) +static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) { struct iwl3945_led_cmd led_cmd = { .id = led_id, - .on = brightness, - .off = brightness, + .on = IWL_LED_SOLID, + .off = 0, .interval = IWL_DEF_LED_INTRVL }; - if (brightness == LED_FULL) { - led_cmd.on = IWL_LED_SOLID; - led_cmd.off = 0; - } return iwl_send_led_cmd(priv, &led_cmd); } -/* Set led register off */ -static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id) -{ - IWL_DEBUG_LED("led on %d\n", led_id); - return iwl3945_led_on(priv, led_id); -} - /* Set led off command */ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) { @@ -136,27 +140,7 @@ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) IWL_DEBUG_LED("led off %d\n", led_id); return iwl_send_led_cmd(priv, &led_cmd); } - -/* Set led register off */ -static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id) -{ - iwl3945_led_off(priv, led_id); - return 0; -} - -/* Set led blink command */ -static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id, - u8 brightness) -{ - struct iwl3945_led_cmd led_cmd = { - .id = led_id, - .on = brightness, - .off = brightness, - .interval = IWL_DEF_LED_INTRVL - }; - - return iwl_send_led_cmd(priv, &led_cmd); -} +#endif /* @@ -206,8 +190,10 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, led->led_off(priv, IWL_LED_LINK); break; default: - if (led->led_pattern) - led->led_pattern(priv, IWL_LED_LINK, brightness); + if (led->led_pattern) { + int idx = iwl3945_brightness_to_idx(brightness); + led->led_pattern(priv, IWL_LED_LINK, idx); + } break; } } @@ -252,24 +238,20 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv, static inline u8 get_blink_rate(struct iwl3945_priv *priv) { int index; - u8 blink_rate; - - if (priv->rxtxpackets < IWL_LED_THRESHOLD) - index = 10; - else { - for (index = 0; index < IWL_MAX_BLINK_TBL; index++) { - if (priv->rxtxpackets > (blink_tbl[index].brightness * - IWL_1MB_RATE)) - break; - } - } - /* if 0 frame is transfered */ - if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking) - blink_rate = IWL_LED_SOLID; - else - blink_rate = blink_tbl[index].on_time; + u64 current_tpt = priv->rxtxpackets; + s64 tpt = current_tpt - priv->led_tpt; - return blink_rate; + if (tpt < 0) + tpt = -tpt; + priv->led_tpt = current_tpt; + + if (!priv->allow_blinking) + index = IWL_MAX_BLINK_TBL; + else + for (index = 0; index < IWL_MAX_BLINK_TBL; index++) + if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE)) + break; + return index; } static inline int is_rf_kill(struct iwl3945_priv *priv) @@ -285,7 +267,7 @@ static inline int is_rf_kill(struct iwl3945_priv *priv) */ void iwl3945_led_background(struct iwl3945_priv *priv) { - u8 blink_rate; + u8 blink_idx; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { priv->last_blink_time = 0; @@ -298,9 +280,10 @@ void iwl3945_led_background(struct iwl3945_priv *priv) if (!priv->allow_blinking) { priv->last_blink_time = 0; - if (priv->last_blink_rate != IWL_LED_SOLID) { - priv->last_blink_rate = IWL_LED_SOLID; - iwl3945_led_on(priv, IWL_LED_LINK); + if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { + priv->last_blink_rate = IWL_SOLID_BLINK_IDX; + iwl3945_led_pattern(priv, IWL_LED_LINK, + IWL_SOLID_BLINK_IDX); } return; } @@ -309,21 +292,14 @@ void iwl3945_led_background(struct iwl3945_priv *priv) msecs_to_jiffies(1000))) return; - blink_rate = get_blink_rate(priv); + blink_idx = get_blink_rate(priv); /* call only if blink rate change */ - if (blink_rate != priv->last_blink_rate) { - if (blink_rate != IWL_LED_SOLID) { - priv->last_blink_time = jiffies + - msecs_to_jiffies(1000); - iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate); - } else { - priv->last_blink_time = 0; - iwl3945_led_on(priv, IWL_LED_LINK); - } - } + if (blink_idx != priv->last_blink_rate) + iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx); - priv->last_blink_rate = blink_rate; + priv->last_blink_time = jiffies; + priv->last_blink_rate = blink_idx; priv->rxtxpackets = 0; } @@ -337,6 +313,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv) priv->last_blink_rate = 0; priv->rxtxpackets = 0; + priv->led_tpt = 0; priv->last_blink_time = 0; priv->allow_blinking = 0; @@ -344,8 +321,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv) snprintf(name, sizeof(name), "iwl-%s:radio", wiphy_name(priv->hw->wiphy)); - priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg; - priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg; + priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; + priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; ret = iwl3945_led_register_led(priv, @@ -364,8 +341,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv) IWL_LED_TRG_ASSOC, 0, name, trigger); /* for assoc always turn led on */ - priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg; - priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg; + priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; + priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; if (ret) @@ -391,6 +368,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv) trigger = ieee80211_get_tx_led_name(priv->hw); snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); + ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_TX], IWL_LED_TRG_TX, 0, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index b1d2f6b8b25..6463e6e34aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -54,7 +54,7 @@ struct iwl3945_led { int (*led_on) (struct iwl3945_priv *priv, int led_id); int (*led_off) (struct iwl3945_priv *priv, int led_id); int (*led_pattern) (struct iwl3945_priv *priv, int led_id, - enum led_brightness brightness); + int idx); enum led_type type; unsigned int registered; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index a7ef59bd194..fa81ba1af3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -794,6 +794,7 @@ struct iwl3945_priv { u8 last_blink_rate; u8 allow_blinking; unsigned int rxtxpackets; + u64 led_tpt; #endif -- cgit v1.2.3-18-g5258 From 3eb2011a67b044859069359948579b942993c416 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 11 Jul 2008 11:53:42 +0800 Subject: iwlwifi: make index unsigned int for iwl_send_led_cmd This is a small fix to change the idx type from int to unsigned. Signed-off-by: Abhijeet Kolekar Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 3 ++- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 6463e6e34aa..47b7e0bac80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -54,7 +54,7 @@ struct iwl3945_led { int (*led_on) (struct iwl3945_priv *priv, int led_id); int (*led_off) (struct iwl3945_priv *priv, int led_id); int (*led_pattern) (struct iwl3945_priv *priv, int led_id, - int idx); + unsigned int idx); enum led_type type; unsigned int registered; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 0c09b901a25..899d7a2567a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -106,7 +106,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) } /* Set led pattern command */ -static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, int idx) +static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, + unsigned int idx) { struct iwl_led_cmd led_cmd = { .id = led_id, diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 05e6a6113b7..1980ae5a7e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -55,7 +55,7 @@ struct iwl_led { int (*led_on) (struct iwl_priv *priv, int led_id); int (*led_off) (struct iwl_priv *priv, int led_id); - int (*led_pattern) (struct iwl_priv *priv, int led_id, int idx); + int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx); enum led_type type; unsigned int registered; -- cgit v1.2.3-18-g5258 From 4c9adafff7d910f142fe44fae37ed12c6b99f20f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 13 Jul 2008 10:07:48 +0200 Subject: rt2x00: Reset LED assoc status after firmware update According to the legacy drivers the LED association status must be reset after the firmware has been uploaded to the hardware. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00firmware.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index b971bc6e7ee..bab05a56e7a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -100,6 +100,14 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev, rt2x00dev->fw->data, rt2x00dev->fw->size); + + /* + * When the firmware is uploaded to the hardware the LED + * association status might have been triggered, for correct + * LED handling it should now be reset. + */ + rt2x00leds_led_assoc(rt2x00dev, false); + return retval; } -- cgit v1.2.3-18-g5258