aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/at76c50x-usb.c108
-rw-r--r--drivers/net/wireless/at76c50x-usb.h1
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c20
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c33
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c119
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c22
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h28
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c21
-rw-r--r--drivers/net/wireless/b43/main.c2
-rw-r--r--drivers/net/wireless/b43/sdio.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c3
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c2
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c160
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c (renamed from drivers/net/wireless/iwlwifi/iwl-calib.c)27
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c72
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c284
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c73
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c22
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c238
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c106
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c2
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c12
-rw-r--r--drivers/net/wireless/libertas/Makefile3
-rw-r--r--drivers/net/wireless/libertas/assoc.c2264
-rw-r--r--drivers/net/wireless/libertas/assoc.h155
-rw-r--r--drivers/net/wireless/libertas/cfg.c2038
-rw-r--r--drivers/net/wireless/libertas/cfg.h21
-rw-r--r--drivers/net/wireless/libertas/cmd.c87
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c83
-rw-r--r--drivers/net/wireless/libertas/debugfs.c54
-rw-r--r--drivers/net/wireless/libertas/decl.h8
-rw-r--r--drivers/net/wireless/libertas/dev.h62
-rw-r--r--drivers/net/wireless/libertas/ethtool.c5
-rw-r--r--drivers/net/wireless/libertas/host.h28
-rw-r--r--drivers/net/wireless/libertas/main.c226
-rw-r--r--drivers/net/wireless/libertas/mesh.c6
-rw-r--r--drivers/net/wireless/libertas/mesh.h5
-rw-r--r--drivers/net/wireless/libertas/rx.c121
-rw-r--r--drivers/net/wireless/libertas/scan.c1354
-rw-r--r--drivers/net/wireless/libertas/scan.h63
-rw-r--r--drivers/net/wireless/libertas/tx.c12
-rw-r--r--drivers/net/wireless/libertas/wext.c2353
-rw-r--r--drivers/net/wireless/libertas/wext.h17
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c5
-rw-r--r--drivers/net/wireless/rndis_wlan.c20
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c104
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c33
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c17
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c30
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c74
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.h18
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c43
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c51
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h10
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c2
-rw-r--r--include/linux/eeprom_93cx6.h1
-rw-r--r--include/linux/nl80211.h22
-rw-r--r--include/net/cfg80211.h15
-rw-r--r--include/net/mac80211.h39
-rw-r--r--net/mac80211/Kconfig1
-rw-r--r--net/mac80211/cfg.c25
-rw-r--r--net/mac80211/driver-ops.h7
-rw-r--r--net/mac80211/driver-trace.h22
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mesh_plink.c42
-rw-r--r--net/mac80211/mlme.c39
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c3
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h2
-rw-r--r--net/mac80211/rc80211_minstrel_ht_debugfs.c2
-rw-r--r--net/mac80211/rx.c18
-rw-r--r--net/mac80211/scan.c6
-rw-r--r--net/mac80211/sta_info.h16
-rw-r--r--net/mac80211/status.c4
-rw-r--r--net/wireless/core.c2
-rw-r--r--net/wireless/nl80211.c31
-rw-r--r--net/wireless/reg.c6
-rw-r--r--net/wireless/reg.h2
-rw-r--r--net/wireless/wext-compat.c10
111 files changed, 3633 insertions, 7660 deletions
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 429b281d40d1..cd8caeab86ea 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -7,6 +7,7 @@
7 * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com> 7 * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com>
8 * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org> 8 * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org>
9 * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi> 9 * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi>
10 * Copyright (c) 2010 Sebastian Smolorz <sesmo@gmx.net>
10 * 11 *
11 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as 13 * modify it under the terms of the GNU General Public License as
@@ -1649,6 +1650,58 @@ exit:
1649 return NULL; 1650 return NULL;
1650} 1651}
1651 1652
1653static int at76_join(struct at76_priv *priv)
1654{
1655 struct at76_req_join join;
1656 int ret;
1657
1658 memset(&join, 0, sizeof(struct at76_req_join));
1659 memcpy(join.essid, priv->essid, priv->essid_size);
1660 join.essid_size = priv->essid_size;
1661 memcpy(join.bssid, priv->bssid, ETH_ALEN);
1662 join.bss_type = INFRASTRUCTURE_MODE;
1663 join.channel = priv->channel;
1664 join.timeout = cpu_to_le16(2000);
1665
1666 at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
1667 ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
1668 sizeof(struct at76_req_join));
1669
1670 if (ret < 0) {
1671 printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
1672 wiphy_name(priv->hw->wiphy), ret);
1673 return 0;
1674 }
1675
1676 ret = at76_wait_completion(priv, CMD_JOIN);
1677 at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
1678 if (ret != CMD_STATUS_COMPLETE) {
1679 printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
1680 wiphy_name(priv->hw->wiphy), ret);
1681 return 0;
1682 }
1683
1684 at76_set_pm_mode(priv);
1685
1686 return 0;
1687}
1688
1689static void at76_work_join_bssid(struct work_struct *work)
1690{
1691 struct at76_priv *priv = container_of(work, struct at76_priv,
1692 work_join_bssid);
1693
1694 if (priv->device_unplugged)
1695 return;
1696
1697 mutex_lock(&priv->mtx);
1698
1699 if (is_valid_ether_addr(priv->bssid))
1700 at76_join(priv);
1701
1702 mutex_unlock(&priv->mtx);
1703}
1704
1652static void at76_mac80211_tx_callback(struct urb *urb) 1705static void at76_mac80211_tx_callback(struct urb *urb)
1653{ 1706{
1654 struct at76_priv *priv = urb->context; 1707 struct at76_priv *priv = urb->context;
@@ -1686,6 +1739,7 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1686 struct at76_priv *priv = hw->priv; 1739 struct at76_priv *priv = hw->priv;
1687 struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer; 1740 struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
1688 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1741 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1742 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
1689 int padding, submit_len, ret; 1743 int padding, submit_len, ret;
1690 1744
1691 at76_dbg(DBG_MAC80211, "%s()", __func__); 1745 at76_dbg(DBG_MAC80211, "%s()", __func__);
@@ -1696,6 +1750,21 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1696 return NETDEV_TX_BUSY; 1750 return NETDEV_TX_BUSY;
1697 } 1751 }
1698 1752
1753 /* The following code lines are important when the device is going to
1754 * authenticate with a new bssid. The driver must send CMD_JOIN before
1755 * an authentication frame is transmitted. For this to succeed, the
1756 * correct bssid of the AP must be known. As mac80211 does not inform
1757 * drivers about the bssid prior to the authentication process the
1758 * following workaround is necessary. If the TX frame is an
1759 * authentication frame extract the bssid and send the CMD_JOIN. */
1760 if (mgmt->frame_control & cpu_to_le16(IEEE80211_STYPE_AUTH)) {
1761 if (compare_ether_addr(priv->bssid, mgmt->bssid)) {
1762 memcpy(priv->bssid, mgmt->bssid, ETH_ALEN);
1763 ieee80211_queue_work(hw, &priv->work_join_bssid);
1764 return NETDEV_TX_BUSY;
1765 }
1766 }
1767
1699 ieee80211_stop_queues(hw); 1768 ieee80211_stop_queues(hw);
1700 1769
1701 at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */ 1770 at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */
@@ -1770,6 +1839,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw)
1770 at76_dbg(DBG_MAC80211, "%s()", __func__); 1839 at76_dbg(DBG_MAC80211, "%s()", __func__);
1771 1840
1772 cancel_delayed_work(&priv->dwork_hw_scan); 1841 cancel_delayed_work(&priv->dwork_hw_scan);
1842 cancel_work_sync(&priv->work_join_bssid);
1773 cancel_work_sync(&priv->work_set_promisc); 1843 cancel_work_sync(&priv->work_set_promisc);
1774 1844
1775 mutex_lock(&priv->mtx); 1845 mutex_lock(&priv->mtx);
@@ -1818,42 +1888,6 @@ static void at76_remove_interface(struct ieee80211_hw *hw,
1818 at76_dbg(DBG_MAC80211, "%s()", __func__); 1888 at76_dbg(DBG_MAC80211, "%s()", __func__);
1819} 1889}
1820 1890
1821static int at76_join(struct at76_priv *priv)
1822{
1823 struct at76_req_join join;
1824 int ret;
1825
1826 memset(&join, 0, sizeof(struct at76_req_join));
1827 memcpy(join.essid, priv->essid, priv->essid_size);
1828 join.essid_size = priv->essid_size;
1829 memcpy(join.bssid, priv->bssid, ETH_ALEN);
1830 join.bss_type = INFRASTRUCTURE_MODE;
1831 join.channel = priv->channel;
1832 join.timeout = cpu_to_le16(2000);
1833
1834 at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
1835 ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
1836 sizeof(struct at76_req_join));
1837
1838 if (ret < 0) {
1839 printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
1840 wiphy_name(priv->hw->wiphy), ret);
1841 return 0;
1842 }
1843
1844 ret = at76_wait_completion(priv, CMD_JOIN);
1845 at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
1846 if (ret != CMD_STATUS_COMPLETE) {
1847 printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
1848 wiphy_name(priv->hw->wiphy), ret);
1849 return 0;
1850 }
1851
1852 at76_set_pm_mode(priv);
1853
1854 return 0;
1855}
1856
1857static void at76_dwork_hw_scan(struct work_struct *work) 1891static void at76_dwork_hw_scan(struct work_struct *work)
1858{ 1892{
1859 struct at76_priv *priv = container_of(work, struct at76_priv, 1893 struct at76_priv *priv = container_of(work, struct at76_priv,
@@ -2107,6 +2141,7 @@ static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
2107 mutex_init(&priv->mtx); 2141 mutex_init(&priv->mtx);
2108 INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc); 2142 INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc);
2109 INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx); 2143 INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx);
2144 INIT_WORK(&priv->work_join_bssid, at76_work_join_bssid);
2110 INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan); 2145 INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan);
2111 2146
2112 tasklet_init(&priv->rx_tasklet, at76_rx_tasklet, 0); 2147 tasklet_init(&priv->rx_tasklet, at76_rx_tasklet, 0);
@@ -2508,5 +2543,6 @@ MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>");
2508MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"); 2543MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
2509MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>"); 2544MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
2510MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>"); 2545MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>");
2546MODULE_AUTHOR("Sebastian Smolorz <sesmo@gmx.net>");
2511MODULE_DESCRIPTION(DRIVER_DESC); 2547MODULE_DESCRIPTION(DRIVER_DESC);
2512MODULE_LICENSE("GPL"); 2548MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/at76c50x-usb.h b/drivers/net/wireless/at76c50x-usb.h
index 972ea0fc1a0b..4a37447dfc01 100644
--- a/drivers/net/wireless/at76c50x-usb.h
+++ b/drivers/net/wireless/at76c50x-usb.h
@@ -387,6 +387,7 @@ struct at76_priv {
387 /* work queues */ 387 /* work queues */
388 struct work_struct work_set_promisc; 388 struct work_struct work_set_promisc;
389 struct work_struct work_submit_rx; 389 struct work_struct work_submit_rx;
390 struct work_struct work_join_bssid;
390 struct delayed_work dwork_hw_scan; 391 struct delayed_work dwork_hw_scan;
391 392
392 struct tasklet_struct rx_tasklet; 393 struct tasklet_struct rx_tasklet;
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 73c4fcd142bb..6284c389ba18 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1768,7 +1768,7 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
1768 1768
1769 if (enable) { 1769 if (enable) {
1770 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, 1770 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
1771 AR5K_PHY_RESTART_DIV_GC, 1); 1771 AR5K_PHY_RESTART_DIV_GC, 4);
1772 1772
1773 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, 1773 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
1774 AR5K_PHY_FAST_ANT_DIV_EN); 1774 AR5K_PHY_FAST_ANT_DIV_EN);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 82c3ab756cd0..064168909108 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -295,6 +295,26 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
295 /* Several PCIe massages to ensure proper behaviour */ 295 /* Several PCIe massages to ensure proper behaviour */
296 if (ah->config.pcie_waen) 296 if (ah->config.pcie_waen)
297 REG_WRITE(ah, AR_WA, ah->config.pcie_waen); 297 REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
298 else
299 REG_WRITE(ah, AR_WA, ah->WARegVal);
300 }
301
302 /*
303 * Configire PCIE after Ini init. SERDES values now come from ini file
304 * This enables PCIe low power mode.
305 */
306 if (ah->config.pcieSerDesWrite) {
307 unsigned int i;
308 struct ar5416IniArray *array;
309
310 array = power_off ? &ah->iniPcieSerdes :
311 &ah->iniPcieSerdesLowPower;
312
313 for (i = 0; i < array->ia_rows; i++) {
314 REG_WRITE(ah,
315 INI_RA(array, i, 0),
316 INI_RA(array, i, 1));
317 }
298 } 318 }
299} 319}
300 320
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 8d163ae4255e..72d5e52abb8f 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -226,6 +226,7 @@ struct ath_buf_state {
226 int bfs_retries; 226 int bfs_retries;
227 u8 bf_type; 227 u8 bf_type;
228 u8 bfs_paprd; 228 u8 bfs_paprd;
229 unsigned long bfs_paprd_timestamp;
229 u32 bfs_keyix; 230 u32 bfs_keyix;
230 enum ath9k_key_type bfs_keytype; 231 enum ath9k_key_type bfs_keytype;
231}; 232};
@@ -425,6 +426,8 @@ int ath_beaconq_config(struct ath_softc *sc);
425#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ 426#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
426#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ 427#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
427 428
429#define ATH_PAPRD_TIMEOUT 100 /* msecs */
430
428void ath_paprd_calibrate(struct work_struct *work); 431void ath_paprd_calibrate(struct work_struct *work);
429void ath_ani_calibrate(unsigned long data); 432void ath_ani_calibrate(unsigned long data);
430 433
@@ -516,6 +519,7 @@ void ath_deinit_leds(struct ath_softc *sc);
516#define SC_OP_TSF_RESET BIT(11) 519#define SC_OP_TSF_RESET BIT(11)
517#define SC_OP_BT_PRIORITY_DETECTED BIT(12) 520#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
518#define SC_OP_BT_SCAN BIT(13) 521#define SC_OP_BT_SCAN BIT(13)
522#define SC_OP_ANI_RUN BIT(14)
519 523
520/* Powersave flags */ 524/* Powersave flags */
521#define PS_WAIT_FOR_BEACON BIT(0) 525#define PS_WAIT_FOR_BEACON BIT(0)
@@ -559,7 +563,6 @@ struct ath_softc {
559 struct mutex mutex; 563 struct mutex mutex;
560 struct work_struct paprd_work; 564 struct work_struct paprd_work;
561 struct completion paprd_complete; 565 struct completion paprd_complete;
562 int paprd_txok;
563 566
564 u32 intrstatus; 567 u32 intrstatus;
565 u32 sc_flags; /* SC_OP_* */ 568 u32 sc_flags; /* SC_OP_* */
@@ -628,6 +631,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
628 631
629extern struct ieee80211_ops ath9k_ops; 632extern struct ieee80211_ops ath9k_ops;
630extern int modparam_nohwcrypt; 633extern int modparam_nohwcrypt;
634extern int led_blink;
631 635
632irqreturn_t ath_isr(int irq, void *dev); 636irqreturn_t ath_isr(int irq, void *dev);
633int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, 637int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 0ee75e79fe35..3a8ee999da5d 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -76,7 +76,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
76 case LED_FULL: 76 case LED_FULL:
77 if (led->led_type == ATH_LED_ASSOC) { 77 if (led->led_type == ATH_LED_ASSOC) {
78 sc->sc_flags |= SC_OP_LED_ASSOCIATED; 78 sc->sc_flags |= SC_OP_LED_ASSOCIATED;
79 ieee80211_queue_delayed_work(sc->hw, 79 if (led_blink)
80 ieee80211_queue_delayed_work(sc->hw,
80 &sc->ath_led_blink_work, 0); 81 &sc->ath_led_blink_work, 0);
81 } else if (led->led_type == ATH_LED_RADIO) { 82 } else if (led->led_type == ATH_LED_RADIO) {
82 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); 83 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
@@ -143,7 +144,8 @@ void ath_init_leds(struct ath_softc *sc)
143 /* LED off, active low */ 144 /* LED off, active low */
144 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); 145 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
145 146
146 INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); 147 if (led_blink)
148 INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
147 149
148 trigger = ieee80211_get_radio_led_name(sc->hw); 150 trigger = ieee80211_get_radio_led_name(sc->hw);
149 snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), 151 snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
@@ -180,7 +182,8 @@ void ath_init_leds(struct ath_softc *sc)
180 return; 182 return;
181 183
182fail: 184fail:
183 cancel_delayed_work_sync(&sc->ath_led_blink_work); 185 if (led_blink)
186 cancel_delayed_work_sync(&sc->ath_led_blink_work);
184 ath_deinit_leds(sc); 187 ath_deinit_leds(sc);
185} 188}
186 189
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 5f3ea7091ae0..ad9134bddd1e 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -16,10 +16,27 @@
16 16
17#include "htc.h" 17#include "htc.h"
18 18
19/* identify firmware images */
20#define FIRMWARE_AR7010 "ar7010.fw"
21#define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw"
22#define FIRMWARE_AR9271 "ar9271.fw"
23
24MODULE_FIRMWARE(FIRMWARE_AR7010);
25MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
26MODULE_FIRMWARE(FIRMWARE_AR9271);
27
19static struct usb_device_id ath9k_hif_usb_ids[] = { 28static struct usb_device_id ath9k_hif_usb_ids[] = {
20 { USB_DEVICE(0x0cf3, 0x9271) }, 29 { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
21 { USB_DEVICE(0x0cf3, 0x1006) }, 30 { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */
22 { USB_DEVICE(0x0cf3, 0x7010) }, 31 { USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */
32 { USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */
33 { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */
34 { USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */
35 { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */
36 { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
37 { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
38 { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
39 { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
23 { }, 40 { },
24}; 41};
25 42
@@ -879,17 +896,15 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
879 /* Find out which firmware to load */ 896 /* Find out which firmware to load */
880 897
881 switch(hif_dev->device_id) { 898 switch(hif_dev->device_id) {
882 case 0x9271:
883 case 0x1006:
884 hif_dev->fw_name = "ar9271.fw";
885 break;
886 case 0x7010: 899 case 0x7010:
900 case 0x9018:
887 if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) 901 if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
888 hif_dev->fw_name = "ar7010_1_1.fw"; 902 hif_dev->fw_name = FIRMWARE_AR7010_1_1;
889 else 903 else
890 hif_dev->fw_name = "ar7010.fw"; 904 hif_dev->fw_name = FIRMWARE_AR7010;
891 break; 905 break;
892 default: 906 default:
907 hif_dev->fw_name = FIRMWARE_AR9271;
893 break; 908 break;
894 } 909 }
895 910
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 58f52a1dc7ea..3756400e6bf9 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -287,6 +287,7 @@ struct ath9k_debug {
287#define ATH_LED_PIN_DEF 1 287#define ATH_LED_PIN_DEF 1
288#define ATH_LED_PIN_9287 8 288#define ATH_LED_PIN_9287 8
289#define ATH_LED_PIN_9271 15 289#define ATH_LED_PIN_9271 15
290#define ATH_LED_PIN_7010 12
290#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ 291#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */
291#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ 292#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */
292 293
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index a63ae88abf3e..148b43317fdb 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -244,17 +244,12 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
244 */ 244 */
245 245
246 switch(devid) { 246 switch(devid) {
247 case 0x9271:
248 case 0x1006:
249 priv->htc->credits = 33;
250 break;
251 case 0x7010: 247 case 0x7010:
248 case 0x9018:
252 priv->htc->credits = 45; 249 priv->htc->credits = 45;
253 break; 250 break;
254 default: 251 default:
255 dev_err(priv->dev, "ath9k_htc: Unsupported device id: 0x%x\n", 252 priv->htc->credits = 33;
256 devid);
257 goto err;
258 } 253 }
259 254
260 ret = htc_init(priv->htc); 255 ret = htc_init(priv->htc);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 05445d8a9818..e38ca66db849 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -931,6 +931,8 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
931 priv->ah->led_pin = ATH_LED_PIN_9287; 931 priv->ah->led_pin = ATH_LED_PIN_9287;
932 else if (AR_SREV_9271(priv->ah)) 932 else if (AR_SREV_9271(priv->ah))
933 priv->ah->led_pin = ATH_LED_PIN_9271; 933 priv->ah->led_pin = ATH_LED_PIN_9271;
934 else if (AR_DEVID_7010(priv->ah))
935 priv->ah->led_pin = ATH_LED_PIN_7010;
934 else 936 else
935 priv->ah->led_pin = ATH_LED_PIN_DEF; 937 priv->ah->led_pin = ATH_LED_PIN_DEF;
936 938
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 62597f4ca319..3ed5c9ec7bc1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -388,6 +388,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
388 ah->config.ht_enable = 0; 388 ah->config.ht_enable = 0;
389 389
390 ah->config.rx_intr_mitigation = true; 390 ah->config.rx_intr_mitigation = true;
391 ah->config.pcieSerDesWrite = true;
391 392
392 /* 393 /*
393 * We need this for PCI devices only (Cardbus, PCI, miniPCI) 394 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
@@ -571,24 +572,13 @@ static int __ath9k_hw_init(struct ath_hw *ah)
571 ath9k_hw_init_mode_regs(ah); 572 ath9k_hw_init_mode_regs(ah);
572 573
573 /* 574 /*
574 * Configire PCIE after Ini init. SERDES values now come from ini file 575 * Read back AR_WA into a permanent copy and set bits 14 and 17.
575 * This enables PCIe low power mode. 576 * We need to do this to avoid RMW of this register. We cannot
577 * read the reg when chip is asleep.
576 */ 578 */
577 if (AR_SREV_9300_20_OR_LATER(ah)) { 579 ah->WARegVal = REG_READ(ah, AR_WA);
578 u32 regval; 580 ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
579 unsigned int i; 581 AR_WA_ASPM_TIMER_BASED_DISABLE);
580
581 /* Set Bits 16 and 17 in the AR_WA register. */
582 regval = REG_READ(ah, AR_WA);
583 regval |= 0x00030000;
584 REG_WRITE(ah, AR_WA, regval);
585
586 for (i = 0; i < ah->iniPcieSerdesLowPower.ia_rows; i++) {
587 REG_WRITE(ah,
588 INI_RA(&ah->iniPcieSerdesLowPower, i, 0),
589 INI_RA(&ah->iniPcieSerdesLowPower, i, 1));
590 }
591 }
592 582
593 if (ah->is_pciexpress) 583 if (ah->is_pciexpress)
594 ath9k_hw_configpcipowersave(ah, 0, 0); 584 ath9k_hw_configpcipowersave(ah, 0, 0);
@@ -1009,6 +999,11 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
1009 999
1010 ENABLE_REGWRITE_BUFFER(ah); 1000 ENABLE_REGWRITE_BUFFER(ah);
1011 1001
1002 if (AR_SREV_9300_20_OR_LATER(ah)) {
1003 REG_WRITE(ah, AR_WA, ah->WARegVal);
1004 udelay(10);
1005 }
1006
1012 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | 1007 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
1013 AR_RTC_FORCE_WAKE_ON_INT); 1008 AR_RTC_FORCE_WAKE_ON_INT);
1014 1009
@@ -1063,6 +1058,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
1063{ 1058{
1064 ENABLE_REGWRITE_BUFFER(ah); 1059 ENABLE_REGWRITE_BUFFER(ah);
1065 1060
1061 if (AR_SREV_9300_20_OR_LATER(ah)) {
1062 REG_WRITE(ah, AR_WA, ah->WARegVal);
1063 udelay(10);
1064 }
1065
1066 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | 1066 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
1067 AR_RTC_FORCE_WAKE_ON_INT); 1067 AR_RTC_FORCE_WAKE_ON_INT);
1068 1068
@@ -1070,6 +1070,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
1070 REG_WRITE(ah, AR_RC, AR_RC_AHB); 1070 REG_WRITE(ah, AR_RC, AR_RC_AHB);
1071 1071
1072 REG_WRITE(ah, AR_RTC_RESET, 0); 1072 REG_WRITE(ah, AR_RTC_RESET, 0);
1073 udelay(2);
1073 1074
1074 REGWRITE_BUFFER_FLUSH(ah); 1075 REGWRITE_BUFFER_FLUSH(ah);
1075 DISABLE_REGWRITE_BUFFER(ah); 1076 DISABLE_REGWRITE_BUFFER(ah);
@@ -1099,6 +1100,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
1099 1100
1100static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) 1101static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
1101{ 1102{
1103 if (AR_SREV_9300_20_OR_LATER(ah)) {
1104 REG_WRITE(ah, AR_WA, ah->WARegVal);
1105 udelay(10);
1106 }
1107
1102 REG_WRITE(ah, AR_RTC_FORCE_WAKE, 1108 REG_WRITE(ah, AR_RTC_FORCE_WAKE,
1103 AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); 1109 AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
1104 1110
@@ -1262,7 +1268,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1262 macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; 1268 macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
1263 1269
1264 /* For chips on which RTC reset is done, save TSF before it gets cleared */ 1270 /* For chips on which RTC reset is done, save TSF before it gets cleared */
1265 if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) 1271 if (AR_SREV_9100(ah) ||
1272 (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
1266 tsf = ath9k_hw_gettsf64(ah); 1273 tsf = ath9k_hw_gettsf64(ah);
1267 1274
1268 saveLedState = REG_READ(ah, AR_CFG_LED) & 1275 saveLedState = REG_READ(ah, AR_CFG_LED) &
@@ -1294,7 +1301,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1294 } 1301 }
1295 1302
1296 /* Restore TSF */ 1303 /* Restore TSF */
1297 if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) 1304 if (tsf)
1298 ath9k_hw_settsf64(ah, tsf); 1305 ath9k_hw_settsf64(ah, tsf);
1299 1306
1300 if (AR_SREV_9280_10_OR_LATER(ah)) 1307 if (AR_SREV_9280_10_OR_LATER(ah))
@@ -1307,6 +1314,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1307 if (r) 1314 if (r)
1308 return r; 1315 return r;
1309 1316
1317 /*
1318 * Some AR91xx SoC devices frequently fail to accept TSF writes
1319 * right after the chip reset. When that happens, write a new
1320 * value after the initvals have been applied, with an offset
1321 * based on measured time difference
1322 */
1323 if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
1324 tsf += 1500;
1325 ath9k_hw_settsf64(ah, tsf);
1326 }
1327
1310 /* Setup MFP options for CCMP */ 1328 /* Setup MFP options for CCMP */
1311 if (AR_SREV_9280_20_OR_LATER(ah)) { 1329 if (AR_SREV_9280_20_OR_LATER(ah)) {
1312 /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt 1330 /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
@@ -1492,7 +1510,7 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
1492} 1510}
1493EXPORT_SYMBOL(ath9k_hw_keyreset); 1511EXPORT_SYMBOL(ath9k_hw_keyreset);
1494 1512
1495bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) 1513static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
1496{ 1514{
1497 u32 macHi, macLo; 1515 u32 macHi, macLo;
1498 u32 unicast_flag = AR_KEYTABLE_VALID; 1516 u32 unicast_flag = AR_KEYTABLE_VALID;
@@ -1530,7 +1548,6 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
1530 1548
1531 return true; 1549 return true;
1532} 1550}
1533EXPORT_SYMBOL(ath9k_hw_keysetmac);
1534 1551
1535bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, 1552bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
1536 const struct ath9k_keyval *k, 1553 const struct ath9k_keyval *k,
@@ -1731,17 +1748,6 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
1731} 1748}
1732EXPORT_SYMBOL(ath9k_hw_set_keycache_entry); 1749EXPORT_SYMBOL(ath9k_hw_set_keycache_entry);
1733 1750
1734bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry)
1735{
1736 if (entry < ah->caps.keycache_size) {
1737 u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
1738 if (val & AR_KEYTABLE_VALID)
1739 return true;
1740 }
1741 return false;
1742}
1743EXPORT_SYMBOL(ath9k_hw_keyisvalid);
1744
1745/******************************/ 1751/******************************/
1746/* Power Management (Chipset) */ 1752/* Power Management (Chipset) */
1747/******************************/ 1753/******************************/
@@ -1768,6 +1774,11 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
1768 REG_CLR_BIT(ah, (AR_RTC_RESET), 1774 REG_CLR_BIT(ah, (AR_RTC_RESET),
1769 AR_RTC_RESET_EN); 1775 AR_RTC_RESET_EN);
1770 } 1776 }
1777
1778 /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
1779 if (AR_SREV_9300_20_OR_LATER(ah))
1780 REG_WRITE(ah, AR_WA,
1781 ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
1771} 1782}
1772 1783
1773/* 1784/*
@@ -1794,6 +1805,10 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
1794 AR_RTC_FORCE_WAKE_EN); 1805 AR_RTC_FORCE_WAKE_EN);
1795 } 1806 }
1796 } 1807 }
1808
1809 /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */
1810 if (AR_SREV_9300_20_OR_LATER(ah))
1811 REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
1797} 1812}
1798 1813
1799static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) 1814static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
@@ -1801,6 +1816,12 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
1801 u32 val; 1816 u32 val;
1802 int i; 1817 int i;
1803 1818
1819 /* Set Bits 14 and 17 of AR_WA before powering on the chip. */
1820 if (AR_SREV_9300_20_OR_LATER(ah)) {
1821 REG_WRITE(ah, AR_WA, ah->WARegVal);
1822 udelay(10);
1823 }
1824
1804 if (setChip) { 1825 if (setChip) {
1805 if ((REG_READ(ah, AR_RTC_STATUS) & 1826 if ((REG_READ(ah, AR_RTC_STATUS) &
1806 AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { 1827 AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
@@ -2155,6 +2176,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
2155 2176
2156 if (AR_SREV_9271(ah)) 2177 if (AR_SREV_9271(ah))
2157 pCap->num_gpio_pins = AR9271_NUM_GPIO; 2178 pCap->num_gpio_pins = AR9271_NUM_GPIO;
2179 else if (AR_DEVID_7010(ah))
2180 pCap->num_gpio_pins = AR7010_NUM_GPIO;
2158 else if (AR_SREV_9285_10_OR_LATER(ah)) 2181 else if (AR_SREV_9285_10_OR_LATER(ah))
2159 pCap->num_gpio_pins = AR9285_NUM_GPIO; 2182 pCap->num_gpio_pins = AR9285_NUM_GPIO;
2160 else if (AR_SREV_9280_10_OR_LATER(ah)) 2183 else if (AR_SREV_9280_10_OR_LATER(ah))
@@ -2295,8 +2318,15 @@ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
2295 2318
2296 BUG_ON(gpio >= ah->caps.num_gpio_pins); 2319 BUG_ON(gpio >= ah->caps.num_gpio_pins);
2297 2320
2298 gpio_shift = gpio << 1; 2321 if (AR_DEVID_7010(ah)) {
2322 gpio_shift = gpio;
2323 REG_RMW(ah, AR7010_GPIO_OE,
2324 (AR7010_GPIO_OE_AS_INPUT << gpio_shift),
2325 (AR7010_GPIO_OE_MASK << gpio_shift));
2326 return;
2327 }
2299 2328
2329 gpio_shift = gpio << 1;
2300 REG_RMW(ah, 2330 REG_RMW(ah,
2301 AR_GPIO_OE_OUT, 2331 AR_GPIO_OE_OUT,
2302 (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), 2332 (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
@@ -2312,7 +2342,11 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
2312 if (gpio >= ah->caps.num_gpio_pins) 2342 if (gpio >= ah->caps.num_gpio_pins)
2313 return 0xffffffff; 2343 return 0xffffffff;
2314 2344
2315 if (AR_SREV_9300_20_OR_LATER(ah)) 2345 if (AR_DEVID_7010(ah)) {
2346 u32 val;
2347 val = REG_READ(ah, AR7010_GPIO_IN);
2348 return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
2349 } else if (AR_SREV_9300_20_OR_LATER(ah))
2316 return MS_REG_READ(AR9300, gpio) != 0; 2350 return MS_REG_READ(AR9300, gpio) != 0;
2317 else if (AR_SREV_9271(ah)) 2351 else if (AR_SREV_9271(ah))
2318 return MS_REG_READ(AR9271, gpio) != 0; 2352 return MS_REG_READ(AR9271, gpio) != 0;
@@ -2332,10 +2366,16 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
2332{ 2366{
2333 u32 gpio_shift; 2367 u32 gpio_shift;
2334 2368
2335 ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); 2369 if (AR_DEVID_7010(ah)) {
2370 gpio_shift = gpio;
2371 REG_RMW(ah, AR7010_GPIO_OE,
2372 (AR7010_GPIO_OE_AS_OUTPUT << gpio_shift),
2373 (AR7010_GPIO_OE_MASK << gpio_shift));
2374 return;
2375 }
2336 2376
2377 ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
2337 gpio_shift = 2 * gpio; 2378 gpio_shift = 2 * gpio;
2338
2339 REG_RMW(ah, 2379 REG_RMW(ah,
2340 AR_GPIO_OE_OUT, 2380 AR_GPIO_OE_OUT,
2341 (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), 2381 (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
@@ -2345,6 +2385,13 @@ EXPORT_SYMBOL(ath9k_hw_cfg_output);
2345 2385
2346void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) 2386void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
2347{ 2387{
2388 if (AR_DEVID_7010(ah)) {
2389 val = val ? 0 : 1;
2390 REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio),
2391 AR_GPIO_BIT(gpio));
2392 return;
2393 }
2394
2348 if (AR_SREV_9271(ah)) 2395 if (AR_SREV_9271(ah))
2349 val = ~val; 2396 val = ~val;
2350 2397
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 5ecbfcf7470a..bb99e2e1f943 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -235,6 +235,7 @@ struct ath9k_ops_config {
235 int ack_6mb; 235 int ack_6mb;
236 u32 cwm_ignore_extcca; 236 u32 cwm_ignore_extcca;
237 u8 pcie_powersave_enable; 237 u8 pcie_powersave_enable;
238 bool pcieSerDesWrite;
238 u8 pcie_clock_req; 239 u8 pcie_clock_req;
239 u32 pcie_waen; 240 u32 pcie_waen;
240 u8 analog_shiftreg; 241 u8 analog_shiftreg;
@@ -819,6 +820,12 @@ struct ath_hw {
819 820
820 u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; 821 u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
821 u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; 822 u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
823 /*
824 * Store the permanent value of Reg 0x4004in WARegVal
825 * so we dont have to R/M/W. We should not be reading
826 * this register when in sleep states.
827 */
828 u32 WARegVal;
822}; 829};
823 830
824static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) 831static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
@@ -852,11 +859,9 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
852 859
853/* Key Cache Management */ 860/* Key Cache Management */
854bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); 861bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
855bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac);
856bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, 862bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
857 const struct ath9k_keyval *k, 863 const struct ath9k_keyval *k,
858 const u8 *mac); 864 const u8 *mac);
859bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry);
860 865
861/* GPIO / RFKILL / Antennae */ 866/* GPIO / RFKILL / Antennae */
862void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); 867void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 514a4014c198..8700e3dc53cf 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -33,6 +33,10 @@ int modparam_nohwcrypt;
33module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); 33module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
34MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); 34MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
35 35
36int led_blink = 1;
37module_param_named(blink, led_blink, int, 0444);
38MODULE_PARM_DESC(blink, "Enable LED blink on activity");
39
36/* We use the hw_value as an index into our private channel structure */ 40/* We use the hw_value as an index into our private channel structure */
37 41
38#define CHAN2G(_freq, _idx) { \ 42#define CHAN2G(_freq, _idx) { \
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index c8de50fa6378..efbf53534ade 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -268,7 +268,6 @@ void ath_paprd_calibrate(struct work_struct *work)
268 int time_left; 268 int time_left;
269 int i; 269 int i;
270 270
271 ath9k_ps_wakeup(sc);
272 skb = alloc_skb(len, GFP_KERNEL); 271 skb = alloc_skb(len, GFP_KERNEL);
273 if (!skb) 272 if (!skb)
274 return; 273 return;
@@ -289,6 +288,7 @@ void ath_paprd_calibrate(struct work_struct *work)
289 qnum = sc->tx.hwq_map[WME_AC_BE]; 288 qnum = sc->tx.hwq_map[WME_AC_BE];
290 txctl.txq = &sc->tx.txq[qnum]; 289 txctl.txq = &sc->tx.txq[qnum];
291 290
291 ath9k_ps_wakeup(sc);
292 ar9003_paprd_init_table(ah); 292 ar9003_paprd_init_table(ah);
293 for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { 293 for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
294 if (!(ah->caps.tx_chainmask & BIT(chain))) 294 if (!(ah->caps.tx_chainmask & BIT(chain)))
@@ -310,13 +310,13 @@ void ath_paprd_calibrate(struct work_struct *work)
310 break; 310 break;
311 311
312 time_left = wait_for_completion_timeout(&sc->paprd_complete, 312 time_left = wait_for_completion_timeout(&sc->paprd_complete,
313 100); 313 msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
314 if (!time_left) { 314 if (!time_left) {
315 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 315 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
316 "Timeout waiting for paprd training on " 316 "Timeout waiting for paprd training on "
317 "TX chain %d\n", 317 "TX chain %d\n",
318 chain); 318 chain);
319 break; 319 goto fail_paprd;
320 } 320 }
321 321
322 if (!ar9003_paprd_is_done(ah)) 322 if (!ar9003_paprd_is_done(ah))
@@ -334,6 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work)
334 ath_paprd_activate(sc); 334 ath_paprd_activate(sc);
335 } 335 }
336 336
337fail_paprd:
337 ath9k_ps_restore(sc); 338 ath9k_ps_restore(sc);
338} 339}
339 340
@@ -451,6 +452,10 @@ static void ath_start_ani(struct ath_common *common)
451{ 452{
452 struct ath_hw *ah = common->ah; 453 struct ath_hw *ah = common->ah;
453 unsigned long timestamp = jiffies_to_msecs(jiffies); 454 unsigned long timestamp = jiffies_to_msecs(jiffies);
455 struct ath_softc *sc = (struct ath_softc *) common->priv;
456
457 if (!(sc->sc_flags & SC_OP_ANI_RUN))
458 return;
454 459
455 common->ani.longcal_timer = timestamp; 460 common->ani.longcal_timer = timestamp;
456 common->ani.shortcal_timer = timestamp; 461 common->ani.shortcal_timer = timestamp;
@@ -766,11 +771,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
766 /* Reset rssi stats */ 771 /* Reset rssi stats */
767 sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; 772 sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
768 773
774 sc->sc_flags |= SC_OP_ANI_RUN;
769 ath_start_ani(common); 775 ath_start_ani(common);
770 } else { 776 } else {
771 ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); 777 ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
772 common->curaid = 0; 778 common->curaid = 0;
773 /* Stop ANI */ 779 /* Stop ANI */
780 sc->sc_flags &= ~SC_OP_ANI_RUN;
774 del_timer_sync(&common->ani.timer); 781 del_timer_sync(&common->ani.timer);
775 } 782 }
776} 783}
@@ -1241,7 +1248,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
1241 1248
1242 aphy->state = ATH_WIPHY_INACTIVE; 1249 aphy->state = ATH_WIPHY_INACTIVE;
1243 1250
1244 cancel_delayed_work_sync(&sc->ath_led_blink_work); 1251 if (led_blink)
1252 cancel_delayed_work_sync(&sc->ath_led_blink_work);
1253
1245 cancel_delayed_work_sync(&sc->tx_complete_work); 1254 cancel_delayed_work_sync(&sc->tx_complete_work);
1246 cancel_work_sync(&sc->paprd_work); 1255 cancel_work_sync(&sc->paprd_work);
1247 1256
@@ -1374,8 +1383,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
1374 1383
1375 if (vif->type == NL80211_IFTYPE_AP || 1384 if (vif->type == NL80211_IFTYPE_AP ||
1376 vif->type == NL80211_IFTYPE_ADHOC || 1385 vif->type == NL80211_IFTYPE_ADHOC ||
1377 vif->type == NL80211_IFTYPE_MONITOR) 1386 vif->type == NL80211_IFTYPE_MONITOR) {
1387 sc->sc_flags |= SC_OP_ANI_RUN;
1378 ath_start_ani(common); 1388 ath_start_ani(common);
1389 }
1379 1390
1380out: 1391out:
1381 mutex_unlock(&sc->mutex); 1392 mutex_unlock(&sc->mutex);
@@ -1396,6 +1407,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
1396 mutex_lock(&sc->mutex); 1407 mutex_lock(&sc->mutex);
1397 1408
1398 /* Stop ANI */ 1409 /* Stop ANI */
1410 sc->sc_flags &= ~SC_OP_ANI_RUN;
1399 del_timer_sync(&common->ani.timer); 1411 del_timer_sync(&common->ani.timer);
1400 1412
1401 /* Reclaim beacon resources */ 1413 /* Reclaim beacon resources */
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 3e3ccef438db..633e3d949ec0 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -704,6 +704,11 @@
704#define AR_WA_BIT7 (1 << 7) 704#define AR_WA_BIT7 (1 << 7)
705#define AR_WA_BIT23 (1 << 23) 705#define AR_WA_BIT23 (1 << 23)
706#define AR_WA_D3_L1_DISABLE (1 << 14) 706#define AR_WA_D3_L1_DISABLE (1 << 14)
707#define AR_WA_D3_TO_L1_DISABLE_REAL (1 << 16)
708#define AR_WA_ASPM_TIMER_BASED_DISABLE (1 << 17)
709#define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
710#define AR_WA_ANALOG_SHIFT (1 << 20)
711#define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */
707#define AR9285_WA_DEFAULT 0x004a050b 712#define AR9285_WA_DEFAULT 0x004a050b
708#define AR9280_WA_DEFAULT 0x0040073b 713#define AR9280_WA_DEFAULT 0x0040073b
709#define AR_WA_DEFAULT 0x0000073f 714#define AR_WA_DEFAULT 0x0000073f
@@ -877,6 +882,7 @@
877#define AR_SREV_9271_11(_ah) \ 882#define AR_SREV_9271_11(_ah) \
878 (AR_SREV_9271(_ah) && \ 883 (AR_SREV_9271(_ah) && \
879 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) 884 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
885
880#define AR_SREV_9300(_ah) \ 886#define AR_SREV_9300(_ah) \
881 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) 887 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
882#define AR_SREV_9300_20(_ah) \ 888#define AR_SREV_9300_20(_ah) \
@@ -891,6 +897,10 @@
891 (AR_SREV_9285_12_OR_LATER(_ah) && \ 897 (AR_SREV_9285_12_OR_LATER(_ah) && \
892 ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) 898 ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
893 899
900#define AR_DEVID_7010(_ah) \
901 (((_ah)->hw_version.devid == 0x7010) || \
902 ((_ah)->hw_version.devid == 0x9018))
903
894#define AR_RADIO_SREV_MAJOR 0xf0 904#define AR_RADIO_SREV_MAJOR 0xf0
895#define AR_RAD5133_SREV_MAJOR 0xc0 905#define AR_RAD5133_SREV_MAJOR 0xc0
896#define AR_RAD2133_SREV_MAJOR 0xd0 906#define AR_RAD2133_SREV_MAJOR 0xd0
@@ -988,6 +998,7 @@ enum {
988#define AR9287_NUM_GPIO 11 998#define AR9287_NUM_GPIO 11
989#define AR9271_NUM_GPIO 16 999#define AR9271_NUM_GPIO 16
990#define AR9300_NUM_GPIO 17 1000#define AR9300_NUM_GPIO 17
1001#define AR7010_NUM_GPIO 16
991 1002
992#define AR_GPIO_IN_OUT 0x4048 1003#define AR_GPIO_IN_OUT 0x4048
993#define AR_GPIO_IN_VAL 0x0FFFC000 1004#define AR_GPIO_IN_VAL 0x0FFFC000
@@ -1002,6 +1013,8 @@ enum {
1002#define AR9271_GPIO_IN_VAL_S 16 1013#define AR9271_GPIO_IN_VAL_S 16
1003#define AR9300_GPIO_IN_VAL 0x0001FFFF 1014#define AR9300_GPIO_IN_VAL 0x0001FFFF
1004#define AR9300_GPIO_IN_VAL_S 0 1015#define AR9300_GPIO_IN_VAL_S 0
1016#define AR7010_GPIO_IN_VAL 0x0000FFFF
1017#define AR7010_GPIO_IN_VAL_S 0
1005 1018
1006#define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c) 1019#define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)
1007#define AR_GPIO_OE_OUT_DRV 0x3 1020#define AR_GPIO_OE_OUT_DRV 0x3
@@ -1010,6 +1023,21 @@ enum {
1010#define AR_GPIO_OE_OUT_DRV_HI 0x2 1023#define AR_GPIO_OE_OUT_DRV_HI 0x2
1011#define AR_GPIO_OE_OUT_DRV_ALL 0x3 1024#define AR_GPIO_OE_OUT_DRV_ALL 0x3
1012 1025
1026#define AR7010_GPIO_OE 0x52000
1027#define AR7010_GPIO_OE_MASK 0x1
1028#define AR7010_GPIO_OE_AS_OUTPUT 0x0
1029#define AR7010_GPIO_OE_AS_INPUT 0x1
1030#define AR7010_GPIO_IN 0x52004
1031#define AR7010_GPIO_OUT 0x52008
1032#define AR7010_GPIO_SET 0x5200C
1033#define AR7010_GPIO_CLEAR 0x52010
1034#define AR7010_GPIO_INT 0x52014
1035#define AR7010_GPIO_INT_TYPE 0x52018
1036#define AR7010_GPIO_INT_POLARITY 0x5201C
1037#define AR7010_GPIO_PENDING 0x52020
1038#define AR7010_GPIO_INT_MASK 0x52024
1039#define AR7010_GPIO_FUNCTION 0x52028
1040
1013#define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050) 1041#define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050)
1014#define AR_GPIO_INTR_POL_VAL 0x0001FFFF 1042#define AR_GPIO_INTR_POL_VAL 0x0001FFFF
1015#define AR_GPIO_INTR_POL_VAL_S 0 1043#define AR_GPIO_INTR_POL_VAL_S 0
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 20221b8c04fd..c3681a1dc941 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -328,6 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
328 u32 ba[WME_BA_BMP_SIZE >> 5]; 328 u32 ba[WME_BA_BMP_SIZE >> 5];
329 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; 329 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
330 bool rc_update = true; 330 bool rc_update = true;
331 struct ieee80211_tx_rate rates[4];
331 332
332 skb = bf->bf_mpdu; 333 skb = bf->bf_mpdu;
333 hdr = (struct ieee80211_hdr *)skb->data; 334 hdr = (struct ieee80211_hdr *)skb->data;
@@ -335,6 +336,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
335 tx_info = IEEE80211_SKB_CB(skb); 336 tx_info = IEEE80211_SKB_CB(skb);
336 hw = bf->aphy->hw; 337 hw = bf->aphy->hw;
337 338
339 memcpy(rates, tx_info->control.rates, sizeof(rates));
340
338 rcu_read_lock(); 341 rcu_read_lock();
339 342
340 /* XXX: use ieee80211_find_sta! */ 343 /* XXX: use ieee80211_find_sta! */
@@ -375,6 +378,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
375 txfail = txpending = 0; 378 txfail = txpending = 0;
376 bf_next = bf->bf_next; 379 bf_next = bf->bf_next;
377 380
381 skb = bf->bf_mpdu;
382 tx_info = IEEE80211_SKB_CB(skb);
383
378 if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { 384 if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
379 /* transmit completion, subframe is 385 /* transmit completion, subframe is
380 * acked by block ack */ 386 * acked by block ack */
@@ -428,6 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
428 spin_unlock_bh(&txq->axq_lock); 434 spin_unlock_bh(&txq->axq_lock);
429 435
430 if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { 436 if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
437 memcpy(tx_info->control.rates, rates, sizeof(rates));
431 ath_tx_rc_status(bf, ts, nbad, txok, true); 438 ath_tx_rc_status(bf, ts, nbad, txok, true);
432 rc_update = false; 439 rc_update = false;
433 } else { 440 } else {
@@ -1644,6 +1651,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1644 } 1651 }
1645 1652
1646 bf->bf_state.bfs_paprd = txctl->paprd; 1653 bf->bf_state.bfs_paprd = txctl->paprd;
1654 if (txctl->paprd)
1655 bf->bf_state.bfs_paprd_timestamp = jiffies;
1647 bf->bf_flags = setup_tx_flags(skb, use_ldpc); 1656 bf->bf_flags = setup_tx_flags(skb, use_ldpc);
1648 1657
1649 bf->bf_keytype = get_hw_crypto_keytype(skb); 1658 bf->bf_keytype = get_hw_crypto_keytype(skb);
@@ -1944,8 +1953,12 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
1944 dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); 1953 dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
1945 1954
1946 if (bf->bf_state.bfs_paprd) { 1955 if (bf->bf_state.bfs_paprd) {
1947 sc->paprd_txok = txok; 1956 if (time_after(jiffies,
1948 complete(&sc->paprd_complete); 1957 bf->bf_state.bfs_paprd_timestamp +
1958 msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
1959 dev_kfree_skb_any(skb);
1960 else
1961 complete(&sc->paprd_complete);
1949 } else { 1962 } else {
1950 ath_tx_complete(sc, skb, bf->aphy, tx_flags); 1963 ath_tx_complete(sc, skb, bf->aphy, tx_flags);
1951 ath_debug_stat_tx(sc, txq, bf, ts); 1964 ath_debug_stat_tx(sc, txq, bf, ts);
@@ -2027,7 +2040,7 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
2027 tx_info->status.rates[i].idx = -1; 2040 tx_info->status.rates[i].idx = -1;
2028 } 2041 }
2029 2042
2030 tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; 2043 tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
2031} 2044}
2032 2045
2033static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) 2046static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
@@ -2138,7 +2151,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2138 * This frame is sent out as a single frame. 2151 * This frame is sent out as a single frame.
2139 * Use hardware retry status for this frame. 2152 * Use hardware retry status for this frame.
2140 */ 2153 */
2141 bf->bf_retries = ts.ts_longretry;
2142 if (ts.ts_status & ATH9K_TXERR_XRETRY) 2154 if (ts.ts_status & ATH9K_TXERR_XRETRY)
2143 bf->bf_state.bf_type |= BUF_XRETRY; 2155 bf->bf_state.bf_type |= BUF_XRETRY;
2144 ath_tx_rc_status(bf, &ts, 0, txok, true); 2156 ath_tx_rc_status(bf, &ts, 0, txok, true);
@@ -2268,7 +2280,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2268 } 2280 }
2269 2281
2270 if (!bf_isampdu(bf)) { 2282 if (!bf_isampdu(bf)) {
2271 bf->bf_retries = txs.ts_longretry;
2272 if (txs.ts_status & ATH9K_TXERR_XRETRY) 2283 if (txs.ts_status & ATH9K_TXERR_XRETRY)
2273 bf->bf_state.bf_type |= BUF_XRETRY; 2284 bf->bf_state.bf_type |= BUF_XRETRY;
2274 ath_tx_rc_status(bf, &txs, 0, txok, true); 2285 ath_tx_rc_status(bf, &txs, 0, txok, true);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 7965b70efbab..8e243798ae93 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1804,7 +1804,7 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
1804 dma_reason[2], dma_reason[3], 1804 dma_reason[2], dma_reason[3],
1805 dma_reason[4], dma_reason[5]); 1805 dma_reason[4], dma_reason[5]);
1806 b43err(dev->wl, "This device does not support DMA " 1806 b43err(dev->wl, "This device does not support DMA "
1807 "on your system. Please use PIO instead.\n"); 1807 "on your system. It will now be switched to PIO.\n");
1808 /* Fall back to PIO transfers if we get fatal DMA errors! */ 1808 /* Fall back to PIO transfers if we get fatal DMA errors! */
1809 dev->use_pio = 1; 1809 dev->use_pio = 1;
1810 b43_controller_restart(dev, "DMA error"); 1810 b43_controller_restart(dev, "DMA error");
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
index 4e56b7bbcebd..45933cf8e8c2 100644
--- a/drivers/net/wireless/b43/sdio.c
+++ b/drivers/net/wireless/b43/sdio.c
@@ -182,6 +182,7 @@ static void b43_sdio_remove(struct sdio_func *func)
182 182
183static const struct sdio_device_id b43_sdio_ids[] = { 183static const struct sdio_device_id b43_sdio_ids[] = {
184 { SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */ 184 { SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
185 { SDIO_DEVICE(0x0092, 0x0004) }, /* C-guys, Inc. EW-CG1102GC */
185 { }, 186 { },
186}; 187};
187 188
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 231dbd77f5f5..9cadaa296fac 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -688,7 +688,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
688 struct ap_data *ap = data; 688 struct ap_data *ap = data;
689 struct net_device *dev = ap->local->dev; 689 struct net_device *dev = ap->local->dev;
690 struct ieee80211_hdr *hdr; 690 struct ieee80211_hdr *hdr;
691 u16 fc, status; 691 u16 status;
692 __le16 *pos; 692 __le16 *pos;
693 struct sta_info *sta = NULL; 693 struct sta_info *sta = NULL;
694 char *txt = NULL; 694 char *txt = NULL;
@@ -699,7 +699,6 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
699 } 699 }
700 700
701 hdr = (struct ieee80211_hdr *) skb->data; 701 hdr = (struct ieee80211_hdr *) skb->data;
702 fc = le16_to_cpu(hdr->frame_control);
703 if ((!ieee80211_is_assoc_resp(hdr->frame_control) && 702 if ((!ieee80211_is_assoc_resp(hdr->frame_control) &&
704 !ieee80211_is_reassoc_resp(hdr->frame_control)) || 703 !ieee80211_is_reassoc_resp(hdr->frame_control)) ||
705 skb->len < IEEE80211_MGMT_HDR_LEN + 4) { 704 skb->len < IEEE80211_MGMT_HDR_LEN + 4) {
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index eb57d1ea361f..eaee84b55887 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -741,9 +741,7 @@ void hostap_set_multicast_list_queue(struct work_struct *work)
741 local_info_t *local = 741 local_info_t *local =
742 container_of(work, local_info_t, set_multicast_list_queue); 742 container_of(work, local_info_t, set_multicast_list_queue);
743 struct net_device *dev = local->dev; 743 struct net_device *dev = local->dev;
744 struct hostap_interface *iface;
745 744
746 iface = netdev_priv(dev);
747 if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, 745 if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
748 local->is_promisc)) { 746 local->is_promisc)) {
749 printk(KERN_INFO "%s: %sabling promiscuous mode failed\n", 747 printk(KERN_INFO "%s: %sabling promiscuous mode failed\n",
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 7c7235385513..728bb858ba97 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,6 +1,6 @@
1obj-$(CONFIG_IWLWIFI) += iwlcore.o 1obj-$(CONFIG_IWLWIFI) += iwlcore.o
2iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o 2iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
3iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o 3iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o
4iwlcore-objs += iwl-scan.o iwl-led.o 4iwlcore-objs += iwl-scan.o iwl-led.o
5iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o 5iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
6iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o 6iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
@@ -11,7 +11,7 @@ CFLAGS_iwl-devtrace.o := -I$(src)
11obj-$(CONFIG_IWLAGN) += iwlagn.o 11obj-$(CONFIG_IWLAGN) += iwlagn.o
12iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o 12iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
13iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o 13iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
14iwlagn-objs += iwl-agn-lib.o 14iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
15iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o 15iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
16 16
17iwlagn-$(CONFIG_IWL4965) += iwl-4965.o 17iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index dba91e0233b6..1daf159914ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -157,6 +157,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
157 BIT(IWL_CALIB_TX_IQ) | 157 BIT(IWL_CALIB_TX_IQ) |
158 BIT(IWL_CALIB_TX_IQ_PERD) | 158 BIT(IWL_CALIB_TX_IQ_PERD) |
159 BIT(IWL_CALIB_BASE_BAND); 159 BIT(IWL_CALIB_BASE_BAND);
160 if (priv->cfg->need_dc_calib)
161 priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
160 162
161 priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; 163 priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
162 164
@@ -215,6 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = {
215 .set_ct_kill = iwl1000_set_ct_threshold, 217 .set_ct_kill = iwl1000_set_ct_threshold,
216 }, 218 },
217 .manage_ibss_station = iwlagn_manage_ibss_station, 219 .manage_ibss_station = iwlagn_manage_ibss_station,
220 .update_bcast_station = iwl_update_bcast_station,
218 .debugfs_ops = { 221 .debugfs_ops = {
219 .rx_stats_read = iwl_ucode_rx_stats_read, 222 .rx_stats_read = iwl_ucode_rx_stats_read,
220 .tx_stats_read = iwl_ucode_tx_stats_read, 223 .tx_stats_read = iwl_ucode_tx_stats_read,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 93d513e14186..a07310fefcf2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -406,6 +406,11 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv,
406 unsigned int plcp_msec; 406 unsigned int plcp_msec;
407 unsigned long plcp_received_jiffies; 407 unsigned long plcp_received_jiffies;
408 408
409 if (priv->cfg->plcp_delta_threshold ==
410 IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
411 IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
412 return rc;
413 }
409 memcpy(&current_stat, pkt->u.raw, sizeof(struct 414 memcpy(&current_stat, pkt->u.raw, sizeof(struct
410 iwl3945_notif_statistics)); 415 iwl3945_notif_statistics));
411 /* 416 /*
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 83e6a42ca2da..1dd3bc4c107e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1580,7 +1580,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
1580 u32 R4; 1580 u32 R4;
1581 1581
1582 if (test_bit(STATUS_TEMPERATURE, &priv->status) && 1582 if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
1583 (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) { 1583 (priv->_agn.statistics.flag &
1584 STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
1584 IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n"); 1585 IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
1585 R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]); 1586 R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
1586 R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]); 1587 R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
@@ -1604,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
1604 if (!test_bit(STATUS_TEMPERATURE, &priv->status)) 1605 if (!test_bit(STATUS_TEMPERATURE, &priv->status))
1605 vt = sign_extend(R4, 23); 1606 vt = sign_extend(R4, 23);
1606 else 1607 else
1607 vt = sign_extend( 1608 vt = sign_extend(le32_to_cpu(
1608 le32_to_cpu(priv->statistics.general.temperature), 23); 1609 priv->_agn.statistics.general.temperature), 23);
1609 1610
1610 IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); 1611 IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
1611 1612
@@ -1785,6 +1786,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1785{ 1786{
1786 unsigned long flags; 1787 unsigned long flags;
1787 u16 ra_tid; 1788 u16 ra_tid;
1789 int ret;
1788 1790
1789 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || 1791 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
1790 (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues 1792 (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -1800,7 +1802,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1800 ra_tid = BUILD_RAxTID(sta_id, tid); 1802 ra_tid = BUILD_RAxTID(sta_id, tid);
1801 1803
1802 /* Modify device's station table to Tx this TID */ 1804 /* Modify device's station table to Tx this TID */
1803 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); 1805 ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
1806 if (ret)
1807 return ret;
1804 1808
1805 spin_lock_irqsave(&priv->lock, flags); 1809 spin_lock_irqsave(&priv->lock, flags);
1806 1810
@@ -2276,6 +2280,7 @@ static struct iwl_lib_ops iwl4965_lib = {
2276 .set_ct_kill = iwl4965_set_ct_threshold, 2280 .set_ct_kill = iwl4965_set_ct_threshold,
2277 }, 2281 },
2278 .manage_ibss_station = iwlagn_manage_ibss_station, 2282 .manage_ibss_station = iwlagn_manage_ibss_station,
2283 .update_bcast_station = iwl_update_bcast_station,
2279 .debugfs_ops = { 2284 .debugfs_ops = {
2280 .rx_stats_read = iwl_ucode_rx_stats_read, 2285 .rx_stats_read = iwl_ucode_rx_stats_read,
2281 .tx_stats_read = iwl_ucode_tx_stats_read, 2286 .tx_stats_read = iwl_ucode_tx_stats_read,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 32710a801cb0..b8f3e20f2c80 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -249,10 +249,11 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
249 /* Set initial calibration set */ 249 /* Set initial calibration set */
250 priv->hw_params.sens = &iwl5150_sensitivity; 250 priv->hw_params.sens = &iwl5150_sensitivity;
251 priv->hw_params.calib_init_cfg = 251 priv->hw_params.calib_init_cfg =
252 BIT(IWL_CALIB_DC) |
253 BIT(IWL_CALIB_LO) | 252 BIT(IWL_CALIB_LO) |
254 BIT(IWL_CALIB_TX_IQ) | 253 BIT(IWL_CALIB_TX_IQ) |
255 BIT(IWL_CALIB_BASE_BAND); 254 BIT(IWL_CALIB_BASE_BAND);
255 if (priv->cfg->need_dc_calib)
256 priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
256 257
257 priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; 258 priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
258 259
@@ -264,7 +265,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
264 u32 vt = 0; 265 u32 vt = 0;
265 s32 offset = iwl_temp_calib_to_offset(priv); 266 s32 offset = iwl_temp_calib_to_offset(priv);
266 267
267 vt = le32_to_cpu(priv->statistics.general.temperature); 268 vt = le32_to_cpu(priv->_agn.statistics.general.temperature);
268 vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; 269 vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
269 /* now vt hold the temperature in Kelvin */ 270 /* now vt hold the temperature in Kelvin */
270 priv->temperature = KELVIN_TO_CELSIUS(vt); 271 priv->temperature = KELVIN_TO_CELSIUS(vt);
@@ -392,6 +393,7 @@ static struct iwl_lib_ops iwl5000_lib = {
392 .set_ct_kill = iwl5000_set_ct_threshold, 393 .set_ct_kill = iwl5000_set_ct_threshold,
393 }, 394 },
394 .manage_ibss_station = iwlagn_manage_ibss_station, 395 .manage_ibss_station = iwlagn_manage_ibss_station,
396 .update_bcast_station = iwl_update_bcast_station,
395 .debugfs_ops = { 397 .debugfs_ops = {
396 .rx_stats_read = iwl_ucode_rx_stats_read, 398 .rx_stats_read = iwl_ucode_rx_stats_read,
397 .tx_stats_read = iwl_ucode_tx_stats_read, 399 .tx_stats_read = iwl_ucode_tx_stats_read,
@@ -454,6 +456,7 @@ static struct iwl_lib_ops iwl5150_lib = {
454 .set_ct_kill = iwl5150_set_ct_threshold, 456 .set_ct_kill = iwl5150_set_ct_threshold,
455 }, 457 },
456 .manage_ibss_station = iwlagn_manage_ibss_station, 458 .manage_ibss_station = iwlagn_manage_ibss_station,
459 .update_bcast_station = iwl_update_bcast_station,
457 .debugfs_ops = { 460 .debugfs_ops = {
458 .rx_stats_read = iwl_ucode_rx_stats_read, 461 .rx_stats_read = iwl_ucode_rx_stats_read,
459 .tx_stats_read = iwl_ucode_tx_stats_read, 462 .tx_stats_read = iwl_ucode_tx_stats_read,
@@ -660,6 +663,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
660 .ucode_tracing = true, 663 .ucode_tracing = true,
661 .sensitivity_calib_by_driver = true, 664 .sensitivity_calib_by_driver = true,
662 .chain_noise_calib_by_driver = true, 665 .chain_noise_calib_by_driver = true,
666 .need_dc_calib = true,
663}; 667};
664 668
665struct iwl_cfg iwl5150_abg_cfg = { 669struct iwl_cfg iwl5150_abg_cfg = {
@@ -689,6 +693,7 @@ struct iwl_cfg iwl5150_abg_cfg = {
689 .ucode_tracing = true, 693 .ucode_tracing = true,
690 .sensitivity_calib_by_driver = true, 694 .sensitivity_calib_by_driver = true,
691 .chain_noise_calib_by_driver = true, 695 .chain_noise_calib_by_driver = true,
696 .need_dc_calib = true,
692}; 697};
693 698
694MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); 699MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index afdeec56b13f..8577664da77c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -84,9 +84,10 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
84} 84}
85 85
86/* Indicate calibration version to uCode. */ 86/* Indicate calibration version to uCode. */
87static void iwl6050_set_calib_version(struct iwl_priv *priv) 87static void iwl6000_set_calib_version(struct iwl_priv *priv)
88{ 88{
89 if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) 89 if (priv->cfg->need_dc_calib &&
90 (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6))
90 iwl_set_bit(priv, CSR_GP_DRIVER_REG, 91 iwl_set_bit(priv, CSR_GP_DRIVER_REG,
91 CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); 92 CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
92} 93}
@@ -186,53 +187,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
186 BIT(IWL_CALIB_LO) | 187 BIT(IWL_CALIB_LO) |
187 BIT(IWL_CALIB_TX_IQ) | 188 BIT(IWL_CALIB_TX_IQ) |
188 BIT(IWL_CALIB_BASE_BAND); 189 BIT(IWL_CALIB_BASE_BAND);
189 190 if (priv->cfg->need_dc_calib)
190 priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; 191 priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
191
192 return 0;
193}
194
195static int iwl6050_hw_set_hw_params(struct iwl_priv *priv)
196{
197 if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
198 priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
199 priv->cfg->num_of_queues =
200 priv->cfg->mod_params->num_of_queues;
201
202 priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
203 priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
204 priv->hw_params.scd_bc_tbls_size =
205 priv->cfg->num_of_queues *
206 sizeof(struct iwlagn_scd_bc_tbl);
207 priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
208 priv->hw_params.max_stations = IWL5000_STATION_COUNT;
209 priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
210
211 priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
212 priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
213
214 priv->hw_params.max_bsm_size = 0;
215 priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
216 BIT(IEEE80211_BAND_5GHZ);
217 priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
218
219 priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
220 priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
221 priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
222 priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
223
224 if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
225 priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
226
227 /* Set initial sensitivity parameters */
228 /* Set initial calibration set */
229 priv->hw_params.sens = &iwl6000_sensitivity;
230 priv->hw_params.calib_init_cfg =
231 BIT(IWL_CALIB_XTAL) |
232 BIT(IWL_CALIB_DC) |
233 BIT(IWL_CALIB_LO) |
234 BIT(IWL_CALIB_TX_IQ) |
235 BIT(IWL_CALIB_BASE_BAND);
236 192
237 priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; 193 priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
238 194
@@ -359,8 +315,10 @@ static struct iwl_lib_ops iwl6000_lib = {
359 .temp_ops = { 315 .temp_ops = {
360 .temperature = iwlagn_temperature, 316 .temperature = iwlagn_temperature,
361 .set_ct_kill = iwl6000_set_ct_threshold, 317 .set_ct_kill = iwl6000_set_ct_threshold,
318 .set_calib_version = iwl6000_set_calib_version,
362 }, 319 },
363 .manage_ibss_station = iwlagn_manage_ibss_station, 320 .manage_ibss_station = iwlagn_manage_ibss_station,
321 .update_bcast_station = iwl_update_bcast_station,
364 .debugfs_ops = { 322 .debugfs_ops = {
365 .rx_stats_read = iwl_ucode_rx_stats_read, 323 .rx_stats_read = iwl_ucode_rx_stats_read,
366 .tx_stats_read = iwl_ucode_tx_stats_read, 324 .tx_stats_read = iwl_ucode_tx_stats_read,
@@ -397,79 +355,6 @@ static const struct iwl_ops iwl6000g2b_ops = {
397 .led = &iwlagn_led_ops, 355 .led = &iwlagn_led_ops,
398}; 356};
399 357
400static struct iwl_lib_ops iwl6050_lib = {
401 .set_hw_params = iwl6050_hw_set_hw_params,
402 .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
403 .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
404 .txq_set_sched = iwlagn_txq_set_sched,
405 .txq_agg_enable = iwlagn_txq_agg_enable,
406 .txq_agg_disable = iwlagn_txq_agg_disable,
407 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
408 .txq_free_tfd = iwl_hw_txq_free_tfd,
409 .txq_init = iwl_hw_tx_queue_init,
410 .rx_handler_setup = iwlagn_rx_handler_setup,
411 .setup_deferred_work = iwlagn_setup_deferred_work,
412 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
413 .load_ucode = iwlagn_load_ucode,
414 .dump_nic_event_log = iwl_dump_nic_event_log,
415 .dump_nic_error_log = iwl_dump_nic_error_log,
416 .dump_csr = iwl_dump_csr,
417 .dump_fh = iwl_dump_fh,
418 .init_alive_start = iwlagn_init_alive_start,
419 .alive_notify = iwlagn_alive_notify,
420 .send_tx_power = iwlagn_send_tx_power,
421 .update_chain_flags = iwl_update_chain_flags,
422 .set_channel_switch = iwl6000_hw_channel_switch,
423 .apm_ops = {
424 .init = iwl_apm_init,
425 .stop = iwl_apm_stop,
426 .config = iwl6000_nic_config,
427 .set_pwr_src = iwl_set_pwr_src,
428 },
429 .eeprom_ops = {
430 .regulatory_bands = {
431 EEPROM_REG_BAND_1_CHANNELS,
432 EEPROM_REG_BAND_2_CHANNELS,
433 EEPROM_REG_BAND_3_CHANNELS,
434 EEPROM_REG_BAND_4_CHANNELS,
435 EEPROM_REG_BAND_5_CHANNELS,
436 EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
437 EEPROM_REG_BAND_52_HT40_CHANNELS
438 },
439 .verify_signature = iwlcore_eeprom_verify_signature,
440 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
441 .release_semaphore = iwlcore_eeprom_release_semaphore,
442 .calib_version = iwlagn_eeprom_calib_version,
443 .query_addr = iwlagn_eeprom_query_addr,
444 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
445 },
446 .post_associate = iwl_post_associate,
447 .isr = iwl_isr_ict,
448 .config_ap = iwl_config_ap,
449 .temp_ops = {
450 .temperature = iwlagn_temperature,
451 .set_ct_kill = iwl6000_set_ct_threshold,
452 .set_calib_version = iwl6050_set_calib_version,
453 },
454 .manage_ibss_station = iwlagn_manage_ibss_station,
455 .debugfs_ops = {
456 .rx_stats_read = iwl_ucode_rx_stats_read,
457 .tx_stats_read = iwl_ucode_tx_stats_read,
458 .general_stats_read = iwl_ucode_general_stats_read,
459 },
460 .recover_from_tx_stall = iwl_bg_monitor_recover,
461 .check_plcp_health = iwl_good_plcp_health,
462 .check_ack_health = iwl_good_ack_health,
463};
464
465static const struct iwl_ops iwl6050_ops = {
466 .lib = &iwl6050_lib,
467 .hcmd = &iwlagn_hcmd,
468 .utils = &iwlagn_hcmd_utils,
469 .led = &iwlagn_led_ops,
470};
471
472
473struct iwl_cfg iwl6000g2a_2agn_cfg = { 358struct iwl_cfg iwl6000g2a_2agn_cfg = {
474 .name = "6000 Series 2x2 AGN Gen2a", 359 .name = "6000 Series 2x2 AGN Gen2a",
475 .fw_name_pre = IWL6000G2A_FW_PRE, 360 .fw_name_pre = IWL6000G2A_FW_PRE,
@@ -505,6 +390,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
505 .ucode_tracing = true, 390 .ucode_tracing = true,
506 .sensitivity_calib_by_driver = true, 391 .sensitivity_calib_by_driver = true,
507 .chain_noise_calib_by_driver = true, 392 .chain_noise_calib_by_driver = true,
393 .need_dc_calib = true,
508}; 394};
509 395
510struct iwl_cfg iwl6000g2a_2abg_cfg = { 396struct iwl_cfg iwl6000g2a_2abg_cfg = {
@@ -537,6 +423,9 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {
537 .chain_noise_scale = 1000, 423 .chain_noise_scale = 1000,
538 .monitor_recover_period = IWL_MONITORING_PERIOD, 424 .monitor_recover_period = IWL_MONITORING_PERIOD,
539 .max_event_log_size = 512, 425 .max_event_log_size = 512,
426 .sensitivity_calib_by_driver = true,
427 .chain_noise_calib_by_driver = true,
428 .need_dc_calib = true,
540}; 429};
541 430
542struct iwl_cfg iwl6000g2a_2bg_cfg = { 431struct iwl_cfg iwl6000g2a_2bg_cfg = {
@@ -569,6 +458,9 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {
569 .chain_noise_scale = 1000, 458 .chain_noise_scale = 1000,
570 .monitor_recover_period = IWL_MONITORING_PERIOD, 459 .monitor_recover_period = IWL_MONITORING_PERIOD,
571 .max_event_log_size = 512, 460 .max_event_log_size = 512,
461 .sensitivity_calib_by_driver = true,
462 .chain_noise_calib_by_driver = true,
463 .need_dc_calib = true,
572}; 464};
573 465
574struct iwl_cfg iwl6000g2b_2agn_cfg = { 466struct iwl_cfg iwl6000g2b_2agn_cfg = {
@@ -603,6 +495,9 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
603 .chain_noise_scale = 1000, 495 .chain_noise_scale = 1000,
604 .monitor_recover_period = IWL_MONITORING_PERIOD, 496 .monitor_recover_period = IWL_MONITORING_PERIOD,
605 .max_event_log_size = 512, 497 .max_event_log_size = 512,
498 .sensitivity_calib_by_driver = true,
499 .chain_noise_calib_by_driver = true,
500 .need_dc_calib = true,
606}; 501};
607 502
608struct iwl_cfg iwl6000g2b_2abg_cfg = { 503struct iwl_cfg iwl6000g2b_2abg_cfg = {
@@ -635,6 +530,9 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
635 .chain_noise_scale = 1000, 530 .chain_noise_scale = 1000,
636 .monitor_recover_period = IWL_MONITORING_PERIOD, 531 .monitor_recover_period = IWL_MONITORING_PERIOD,
637 .max_event_log_size = 512, 532 .max_event_log_size = 512,
533 .sensitivity_calib_by_driver = true,
534 .chain_noise_calib_by_driver = true,
535 .need_dc_calib = true,
638}; 536};
639 537
640struct iwl_cfg iwl6000g2b_2bgn_cfg = { 538struct iwl_cfg iwl6000g2b_2bgn_cfg = {
@@ -669,6 +567,9 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
669 .chain_noise_scale = 1000, 567 .chain_noise_scale = 1000,
670 .monitor_recover_period = IWL_MONITORING_PERIOD, 568 .monitor_recover_period = IWL_MONITORING_PERIOD,
671 .max_event_log_size = 512, 569 .max_event_log_size = 512,
570 .sensitivity_calib_by_driver = true,
571 .chain_noise_calib_by_driver = true,
572 .need_dc_calib = true,
672}; 573};
673 574
674struct iwl_cfg iwl6000g2b_2bg_cfg = { 575struct iwl_cfg iwl6000g2b_2bg_cfg = {
@@ -701,6 +602,9 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
701 .chain_noise_scale = 1000, 602 .chain_noise_scale = 1000,
702 .monitor_recover_period = IWL_MONITORING_PERIOD, 603 .monitor_recover_period = IWL_MONITORING_PERIOD,
703 .max_event_log_size = 512, 604 .max_event_log_size = 512,
605 .sensitivity_calib_by_driver = true,
606 .chain_noise_calib_by_driver = true,
607 .need_dc_calib = true,
704}; 608};
705 609
706struct iwl_cfg iwl6000g2b_bgn_cfg = { 610struct iwl_cfg iwl6000g2b_bgn_cfg = {
@@ -735,6 +639,9 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
735 .chain_noise_scale = 1000, 639 .chain_noise_scale = 1000,
736 .monitor_recover_period = IWL_MONITORING_PERIOD, 640 .monitor_recover_period = IWL_MONITORING_PERIOD,
737 .max_event_log_size = 512, 641 .max_event_log_size = 512,
642 .sensitivity_calib_by_driver = true,
643 .chain_noise_calib_by_driver = true,
644 .need_dc_calib = true,
738}; 645};
739 646
740struct iwl_cfg iwl6000g2b_bg_cfg = { 647struct iwl_cfg iwl6000g2b_bg_cfg = {
@@ -767,6 +674,9 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
767 .chain_noise_scale = 1000, 674 .chain_noise_scale = 1000,
768 .monitor_recover_period = IWL_MONITORING_PERIOD, 675 .monitor_recover_period = IWL_MONITORING_PERIOD,
769 .max_event_log_size = 512, 676 .max_event_log_size = 512,
677 .sensitivity_calib_by_driver = true,
678 .chain_noise_calib_by_driver = true,
679 .need_dc_calib = true,
770}; 680};
771 681
772/* 682/*
@@ -885,7 +795,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
885 .ucode_api_max = IWL6050_UCODE_API_MAX, 795 .ucode_api_max = IWL6050_UCODE_API_MAX,
886 .ucode_api_min = IWL6050_UCODE_API_MIN, 796 .ucode_api_min = IWL6050_UCODE_API_MIN,
887 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, 797 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
888 .ops = &iwl6050_ops, 798 .ops = &iwl6000_ops,
889 .eeprom_size = OTP_LOW_IMAGE_SIZE, 799 .eeprom_size = OTP_LOW_IMAGE_SIZE,
890 .eeprom_ver = EEPROM_6050_EEPROM_VERSION, 800 .eeprom_ver = EEPROM_6050_EEPROM_VERSION,
891 .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, 801 .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
@@ -914,6 +824,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
914 .ucode_tracing = true, 824 .ucode_tracing = true,
915 .sensitivity_calib_by_driver = true, 825 .sensitivity_calib_by_driver = true,
916 .chain_noise_calib_by_driver = true, 826 .chain_noise_calib_by_driver = true,
827 .need_dc_calib = true,
917}; 828};
918 829
919struct iwl_cfg iwl6050_2abg_cfg = { 830struct iwl_cfg iwl6050_2abg_cfg = {
@@ -922,7 +833,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
922 .ucode_api_max = IWL6050_UCODE_API_MAX, 833 .ucode_api_max = IWL6050_UCODE_API_MAX,
923 .ucode_api_min = IWL6050_UCODE_API_MIN, 834 .ucode_api_min = IWL6050_UCODE_API_MIN,
924 .sku = IWL_SKU_A|IWL_SKU_G, 835 .sku = IWL_SKU_A|IWL_SKU_G,
925 .ops = &iwl6050_ops, 836 .ops = &iwl6000_ops,
926 .eeprom_size = OTP_LOW_IMAGE_SIZE, 837 .eeprom_size = OTP_LOW_IMAGE_SIZE,
927 .eeprom_ver = EEPROM_6050_EEPROM_VERSION, 838 .eeprom_ver = EEPROM_6050_EEPROM_VERSION,
928 .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, 839 .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
@@ -949,6 +860,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
949 .ucode_tracing = true, 860 .ucode_tracing = true,
950 .sensitivity_calib_by_driver = true, 861 .sensitivity_calib_by_driver = true,
951 .chain_noise_calib_by_driver = true, 862 .chain_noise_calib_by_driver = true,
863 .need_dc_calib = true,
952}; 864};
953 865
954struct iwl_cfg iwl6000_3agn_cfg = { 866struct iwl_cfg iwl6000_3agn_cfg = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index 22fa947e8756..eb052b05e790 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -96,17 +96,16 @@ int iwl_send_calib_results(struct iwl_priv *priv)
96 hcmd.len = priv->calib_results[i].buf_len; 96 hcmd.len = priv->calib_results[i].buf_len;
97 hcmd.data = priv->calib_results[i].buf; 97 hcmd.data = priv->calib_results[i].buf;
98 ret = iwl_send_cmd_sync(priv, &hcmd); 98 ret = iwl_send_cmd_sync(priv, &hcmd);
99 if (ret) 99 if (ret) {
100 goto err; 100 IWL_ERR(priv, "Error %d iteration %d\n",
101 ret, i);
102 break;
103 }
101 } 104 }
102 } 105 }
103 106
104 return 0;
105err:
106 IWL_ERR(priv, "Error %d iteration %d\n", ret, i);
107 return ret; 107 return ret;
108} 108}
109EXPORT_SYMBOL(iwl_send_calib_results);
110 109
111int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) 110int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
112{ 111{
@@ -121,7 +120,6 @@ int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
121 memcpy(res->buf, buf, len); 120 memcpy(res->buf, buf, len);
122 return 0; 121 return 0;
123} 122}
124EXPORT_SYMBOL(iwl_calib_set);
125 123
126void iwl_calib_free_results(struct iwl_priv *priv) 124void iwl_calib_free_results(struct iwl_priv *priv)
127{ 125{
@@ -133,7 +131,6 @@ void iwl_calib_free_results(struct iwl_priv *priv)
133 priv->calib_results[i].buf_len = 0; 131 priv->calib_results[i].buf_len = 0;
134 } 132 }
135} 133}
136EXPORT_SYMBOL(iwl_calib_free_results);
137 134
138/***************************************************************************** 135/*****************************************************************************
139 * RUNTIME calibrations framework 136 * RUNTIME calibrations framework
@@ -533,7 +530,6 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
533 ret |= iwl_sensitivity_write(priv); 530 ret |= iwl_sensitivity_write(priv);
534 IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); 531 IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
535} 532}
536EXPORT_SYMBOL(iwl_init_sensitivity);
537 533
538void iwl_sensitivity_calibration(struct iwl_priv *priv, 534void iwl_sensitivity_calibration(struct iwl_priv *priv,
539 struct iwl_notif_statistics *resp) 535 struct iwl_notif_statistics *resp)
@@ -639,7 +635,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
639 iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); 635 iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
640 iwl_sensitivity_write(priv); 636 iwl_sensitivity_write(priv);
641} 637}
642EXPORT_SYMBOL(iwl_sensitivity_calibration);
643 638
644static inline u8 find_first_chain(u8 mask) 639static inline u8 find_first_chain(u8 mask)
645{ 640{
@@ -848,10 +843,10 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
848 843
849 if (active_chains != priv->hw_params.valid_rx_ant && 844 if (active_chains != priv->hw_params.valid_rx_ant &&
850 active_chains != priv->chain_noise_data.active_chains) 845 active_chains != priv->chain_noise_data.active_chains)
851 IWL_WARN(priv, 846 IWL_DEBUG_CALIB(priv,
852 "Detected that not all antennas are connected! " 847 "Detected that not all antennas are connected! "
853 "Connected: %#x, valid: %#x.\n", 848 "Connected: %#x, valid: %#x.\n",
854 active_chains, priv->hw_params.valid_rx_ant); 849 active_chains, priv->hw_params.valid_rx_ant);
855 850
856 /* Save for use within RXON, TX, SCAN commands, etc. */ 851 /* Save for use within RXON, TX, SCAN commands, etc. */
857 priv->chain_noise_data.active_chains = active_chains; 852 priv->chain_noise_data.active_chains = active_chains;
@@ -897,8 +892,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
897 data->state = IWL_CHAIN_NOISE_DONE; 892 data->state = IWL_CHAIN_NOISE_DONE;
898 iwl_power_update_mode(priv, false); 893 iwl_power_update_mode(priv, false);
899} 894}
900EXPORT_SYMBOL(iwl_chain_noise_calibration);
901
902 895
903void iwl_reset_run_time_calib(struct iwl_priv *priv) 896void iwl_reset_run_time_calib(struct iwl_priv *priv)
904{ 897{
@@ -915,5 +908,3 @@ void iwl_reset_run_time_calib(struct iwl_priv *priv)
915 * periodically after association */ 908 * periodically after association */
916 iwl_send_statistics_request(priv, CMD_ASYNC, true); 909 iwl_send_statistics_request(priv, CMD_ASYNC, true);
917} 910}
918EXPORT_SYMBOL(iwl_reset_run_time_calib);
919
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
index 3d08dc8af143..75d6bfcbc607 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
@@ -33,17 +33,17 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
33 int p = 0; 33 int p = 0;
34 34
35 p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", 35 p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
36 le32_to_cpu(priv->statistics.flag)); 36 le32_to_cpu(priv->_agn.statistics.flag));
37 if (le32_to_cpu(priv->statistics.flag) & 37 if (le32_to_cpu(priv->_agn.statistics.flag) &
38 UCODE_STATISTICS_CLEAR_MSK) 38 UCODE_STATISTICS_CLEAR_MSK)
39 p += scnprintf(buf + p, bufsz - p, 39 p += scnprintf(buf + p, bufsz - p,
40 "\tStatistics have been cleared\n"); 40 "\tStatistics have been cleared\n");
41 p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", 41 p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
42 (le32_to_cpu(priv->statistics.flag) & 42 (le32_to_cpu(priv->_agn.statistics.flag) &
43 UCODE_STATISTICS_FREQUENCY_MSK) 43 UCODE_STATISTICS_FREQUENCY_MSK)
44 ? "2.4 GHz" : "5.2 GHz"); 44 ? "2.4 GHz" : "5.2 GHz");
45 p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", 45 p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
46 (le32_to_cpu(priv->statistics.flag) & 46 (le32_to_cpu(priv->_agn.statistics.flag) &
47 UCODE_STATISTICS_NARROW_BAND_MSK) 47 UCODE_STATISTICS_NARROW_BAND_MSK)
48 ? "enabled" : "disabled"); 48 ? "enabled" : "disabled");
49 return p; 49 return p;
@@ -79,22 +79,22 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
79 * the last statistics notification from uCode 79 * the last statistics notification from uCode
80 * might not reflect the current uCode activity 80 * might not reflect the current uCode activity
81 */ 81 */
82 ofdm = &priv->statistics.rx.ofdm; 82 ofdm = &priv->_agn.statistics.rx.ofdm;
83 cck = &priv->statistics.rx.cck; 83 cck = &priv->_agn.statistics.rx.cck;
84 general = &priv->statistics.rx.general; 84 general = &priv->_agn.statistics.rx.general;
85 ht = &priv->statistics.rx.ofdm_ht; 85 ht = &priv->_agn.statistics.rx.ofdm_ht;
86 accum_ofdm = &priv->accum_statistics.rx.ofdm; 86 accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm;
87 accum_cck = &priv->accum_statistics.rx.cck; 87 accum_cck = &priv->_agn.accum_statistics.rx.cck;
88 accum_general = &priv->accum_statistics.rx.general; 88 accum_general = &priv->_agn.accum_statistics.rx.general;
89 accum_ht = &priv->accum_statistics.rx.ofdm_ht; 89 accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht;
90 delta_ofdm = &priv->delta_statistics.rx.ofdm; 90 delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm;
91 delta_cck = &priv->delta_statistics.rx.cck; 91 delta_cck = &priv->_agn.delta_statistics.rx.cck;
92 delta_general = &priv->delta_statistics.rx.general; 92 delta_general = &priv->_agn.delta_statistics.rx.general;
93 delta_ht = &priv->delta_statistics.rx.ofdm_ht; 93 delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht;
94 max_ofdm = &priv->max_delta.rx.ofdm; 94 max_ofdm = &priv->_agn.max_delta.rx.ofdm;
95 max_cck = &priv->max_delta.rx.cck; 95 max_cck = &priv->_agn.max_delta.rx.cck;
96 max_general = &priv->max_delta.rx.general; 96 max_general = &priv->_agn.max_delta.rx.general;
97 max_ht = &priv->max_delta.rx.ofdm_ht; 97 max_ht = &priv->_agn.max_delta.rx.ofdm_ht;
98 98
99 pos += iwl_statistics_flag(priv, buf, bufsz); 99 pos += iwl_statistics_flag(priv, buf, bufsz);
100 pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" 100 pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
@@ -560,10 +560,10 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
560 * the last statistics notification from uCode 560 * the last statistics notification from uCode
561 * might not reflect the current uCode activity 561 * might not reflect the current uCode activity
562 */ 562 */
563 tx = &priv->statistics.tx; 563 tx = &priv->_agn.statistics.tx;
564 accum_tx = &priv->accum_statistics.tx; 564 accum_tx = &priv->_agn.accum_statistics.tx;
565 delta_tx = &priv->delta_statistics.tx; 565 delta_tx = &priv->_agn.delta_statistics.tx;
566 max_tx = &priv->max_delta.tx; 566 max_tx = &priv->_agn.max_delta.tx;
567 pos += iwl_statistics_flag(priv, buf, bufsz); 567 pos += iwl_statistics_flag(priv, buf, bufsz);
568 pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" 568 pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
569 "acumulative delta max\n", 569 "acumulative delta max\n",
@@ -777,18 +777,18 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
777 * the last statistics notification from uCode 777 * the last statistics notification from uCode
778 * might not reflect the current uCode activity 778 * might not reflect the current uCode activity
779 */ 779 */
780 general = &priv->statistics.general; 780 general = &priv->_agn.statistics.general;
781 dbg = &priv->statistics.general.dbg; 781 dbg = &priv->_agn.statistics.general.dbg;
782 div = &priv->statistics.general.div; 782 div = &priv->_agn.statistics.general.div;
783 accum_general = &priv->accum_statistics.general; 783 accum_general = &priv->_agn.accum_statistics.general;
784 delta_general = &priv->delta_statistics.general; 784 delta_general = &priv->_agn.delta_statistics.general;
785 max_general = &priv->max_delta.general; 785 max_general = &priv->_agn.max_delta.general;
786 accum_dbg = &priv->accum_statistics.general.dbg; 786 accum_dbg = &priv->_agn.accum_statistics.general.dbg;
787 delta_dbg = &priv->delta_statistics.general.dbg; 787 delta_dbg = &priv->_agn.delta_statistics.general.dbg;
788 max_dbg = &priv->max_delta.general.dbg; 788 max_dbg = &priv->_agn.max_delta.general.dbg;
789 accum_div = &priv->accum_statistics.general.div; 789 accum_div = &priv->_agn.accum_statistics.general.div;
790 delta_div = &priv->delta_statistics.general.div; 790 delta_div = &priv->_agn.delta_statistics.general.div;
791 max_div = &priv->max_delta.general.div; 791 max_div = &priv->_agn.max_delta.general.div;
792 pos += iwl_statistics_flag(priv, buf, bufsz); 792 pos += iwl_statistics_flag(priv, buf, bufsz);
793 pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" 793 pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
794 "acumulative delta max\n", 794 "acumulative delta max\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 3f765ba15cb8..f06d1feedf81 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -214,11 +214,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
214static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, 214static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
215 __le32 *tx_flags) 215 __le32 *tx_flags)
216{ 216{
217 if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || 217 *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
218 (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
219 *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
220 else
221 *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
222} 218}
223 219
224/* Calc max signal level (dBm) among 3 possible receivers */ 220/* Calc max signal level (dBm) among 3 possible receivers */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 0e7b0661d61d..5f1e7d802cbf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -361,7 +361,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
361void iwlagn_temperature(struct iwl_priv *priv) 361void iwlagn_temperature(struct iwl_priv *priv)
362{ 362{
363 /* store temperature from statistics (in Celsius) */ 363 /* store temperature from statistics (in Celsius) */
364 priv->temperature = le32_to_cpu(priv->statistics.general.temperature); 364 priv->temperature =
365 le32_to_cpu(priv->_agn.statistics.general.temperature);
365 iwl_tt_handler(priv); 366 iwl_tt_handler(priv);
366} 367}
367 368
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 40933a5de027..35c86d22b14b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -324,18 +324,11 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
324 struct iwl_lq_sta *lq_data, 324 struct iwl_lq_sta *lq_data,
325 struct ieee80211_sta *sta) 325 struct ieee80211_sta *sta)
326{ 326{
327 if ((tid < TID_MAX_LOAD_COUNT) && 327 if (tid < TID_MAX_LOAD_COUNT)
328 !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) { 328 rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
329 if (priv->cfg->use_rts_for_ht) { 329 else
330 /* 330 IWL_ERR(priv, "tid exceeds max load count: %d/%d\n",
331 * switch to RTS/CTS if it is the prefer protection 331 tid, TID_MAX_LOAD_COUNT);
332 * method for HT traffic
333 */
334 IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
335 priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
336 iwlcore_commit_rxon(priv);
337 }
338 }
339} 332}
340 333
341static inline int get_num_of_ant_from_rate(u32 rate_n_flags) 334static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
new file mode 100644
index 000000000000..d54edc326f81
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -0,0 +1,284 @@
1/******************************************************************************
2 *
3 * GPL LICENSE SUMMARY
4 *
5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19 * USA
20 *
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *
28 *****************************************************************************/
29
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/sched.h>
34
35#include "iwl-dev.h"
36#include "iwl-core.h"
37#include "iwl-calib.h"
38#include "iwl-sta.h"
39#include "iwl-io.h"
40#include "iwl-helpers.h"
41#include "iwl-agn-hw.h"
42#include "iwl-agn.h"
43
44void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
45 struct iwl_rx_mem_buffer *rxb)
46
47{
48 struct iwl_rx_packet *pkt = rxb_addr(rxb);
49 struct iwl_missed_beacon_notif *missed_beacon;
50
51 missed_beacon = &pkt->u.missed_beacon;
52 if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
53 priv->missed_beacon_threshold) {
54 IWL_DEBUG_CALIB(priv,
55 "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
56 le32_to_cpu(missed_beacon->consecutive_missed_beacons),
57 le32_to_cpu(missed_beacon->total_missed_becons),
58 le32_to_cpu(missed_beacon->num_recvd_beacons),
59 le32_to_cpu(missed_beacon->num_expected_beacons));
60 if (!test_bit(STATUS_SCANNING, &priv->status))
61 iwl_init_sensitivity(priv);
62 }
63}
64
65/* Calculate noise level, based on measurements during network silence just
66 * before arriving beacon. This measurement can be done only if we know
67 * exactly when to expect beacons, therefore only when we're associated. */
68static void iwl_rx_calc_noise(struct iwl_priv *priv)
69{
70 struct statistics_rx_non_phy *rx_info
71 = &(priv->_agn.statistics.rx.general);
72 int num_active_rx = 0;
73 int total_silence = 0;
74 int bcn_silence_a =
75 le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
76 int bcn_silence_b =
77 le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
78 int bcn_silence_c =
79 le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
80 int last_rx_noise;
81
82 if (bcn_silence_a) {
83 total_silence += bcn_silence_a;
84 num_active_rx++;
85 }
86 if (bcn_silence_b) {
87 total_silence += bcn_silence_b;
88 num_active_rx++;
89 }
90 if (bcn_silence_c) {
91 total_silence += bcn_silence_c;
92 num_active_rx++;
93 }
94
95 /* Average among active antennas */
96 if (num_active_rx)
97 last_rx_noise = (total_silence / num_active_rx) - 107;
98 else
99 last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
100
101 IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
102 bcn_silence_a, bcn_silence_b, bcn_silence_c,
103 last_rx_noise);
104}
105
106#ifdef CONFIG_IWLWIFI_DEBUGFS
107/*
108 * based on the assumption of all statistics counter are in DWORD
109 * FIXME: This function is for debugging, do not deal with
110 * the case of counters roll-over.
111 */
112static void iwl_accumulative_statistics(struct iwl_priv *priv,
113 __le32 *stats)
114{
115 int i;
116 __le32 *prev_stats;
117 u32 *accum_stats;
118 u32 *delta, *max_delta;
119
120 prev_stats = (__le32 *)&priv->_agn.statistics;
121 accum_stats = (u32 *)&priv->_agn.accum_statistics;
122 delta = (u32 *)&priv->_agn.delta_statistics;
123 max_delta = (u32 *)&priv->_agn.max_delta;
124
125 for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
126 i += sizeof(__le32), stats++, prev_stats++, delta++,
127 max_delta++, accum_stats++) {
128 if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
129 *delta = (le32_to_cpu(*stats) -
130 le32_to_cpu(*prev_stats));
131 *accum_stats += *delta;
132 if (*delta > *max_delta)
133 *max_delta = *delta;
134 }
135 }
136
137 /* reset accumulative statistics for "no-counter" type statistics */
138 priv->_agn.accum_statistics.general.temperature =
139 priv->_agn.statistics.general.temperature;
140 priv->_agn.accum_statistics.general.temperature_m =
141 priv->_agn.statistics.general.temperature_m;
142 priv->_agn.accum_statistics.general.ttl_timestamp =
143 priv->_agn.statistics.general.ttl_timestamp;
144 priv->_agn.accum_statistics.tx.tx_power.ant_a =
145 priv->_agn.statistics.tx.tx_power.ant_a;
146 priv->_agn.accum_statistics.tx.tx_power.ant_b =
147 priv->_agn.statistics.tx.tx_power.ant_b;
148 priv->_agn.accum_statistics.tx.tx_power.ant_c =
149 priv->_agn.statistics.tx.tx_power.ant_c;
150}
151#endif
152
153#define REG_RECALIB_PERIOD (60)
154
155/**
156 * iwl_good_plcp_health - checks for plcp error.
157 *
158 * When the plcp error is exceeding the thresholds, reset the radio
159 * to improve the throughput.
160 */
161bool iwl_good_plcp_health(struct iwl_priv *priv,
162 struct iwl_rx_packet *pkt)
163{
164 bool rc = true;
165 int combined_plcp_delta;
166 unsigned int plcp_msec;
167 unsigned long plcp_received_jiffies;
168
169 if (priv->cfg->plcp_delta_threshold ==
170 IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
171 IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
172 return rc;
173 }
174
175 /*
176 * check for plcp_err and trigger radio reset if it exceeds
177 * the plcp error threshold plcp_delta.
178 */
179 plcp_received_jiffies = jiffies;
180 plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
181 (long) priv->plcp_jiffies);
182 priv->plcp_jiffies = plcp_received_jiffies;
183 /*
184 * check to make sure plcp_msec is not 0 to prevent division
185 * by zero.
186 */
187 if (plcp_msec) {
188 combined_plcp_delta =
189 (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
190 le32_to_cpu(priv->_agn.statistics.rx.ofdm.plcp_err)) +
191 (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
192 le32_to_cpu(priv->_agn.statistics.rx.ofdm_ht.plcp_err));
193
194 if ((combined_plcp_delta > 0) &&
195 ((combined_plcp_delta * 100) / plcp_msec) >
196 priv->cfg->plcp_delta_threshold) {
197 /*
198 * if plcp_err exceed the threshold,
199 * the following data is printed in csv format:
200 * Text: plcp_err exceeded %d,
201 * Received ofdm.plcp_err,
202 * Current ofdm.plcp_err,
203 * Received ofdm_ht.plcp_err,
204 * Current ofdm_ht.plcp_err,
205 * combined_plcp_delta,
206 * plcp_msec
207 */
208 IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
209 "%u, %u, %u, %u, %d, %u mSecs\n",
210 priv->cfg->plcp_delta_threshold,
211 le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
212 le32_to_cpu(
213 priv->_agn.statistics.rx.ofdm.plcp_err),
214 le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
215 le32_to_cpu(
216 priv->_agn.statistics.rx.ofdm_ht.plcp_err),
217 combined_plcp_delta, plcp_msec);
218 rc = false;
219 }
220 }
221 return rc;
222}
223
224void iwl_rx_statistics(struct iwl_priv *priv,
225 struct iwl_rx_mem_buffer *rxb)
226{
227 int change;
228 struct iwl_rx_packet *pkt = rxb_addr(rxb);
229
230
231 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
232 (int)sizeof(priv->_agn.statistics),
233 le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
234
235 change = ((priv->_agn.statistics.general.temperature !=
236 pkt->u.stats.general.temperature) ||
237 ((priv->_agn.statistics.flag &
238 STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
239 (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
240
241#ifdef CONFIG_IWLWIFI_DEBUGFS
242 iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
243#endif
244 iwl_recover_from_statistics(priv, pkt);
245
246 memcpy(&priv->_agn.statistics, &pkt->u.stats,
247 sizeof(priv->_agn.statistics));
248
249 set_bit(STATUS_STATISTICS, &priv->status);
250
251 /* Reschedule the statistics timer to occur in
252 * REG_RECALIB_PERIOD seconds to ensure we get a
253 * thermal update even if the uCode doesn't give
254 * us one */
255 mod_timer(&priv->statistics_periodic, jiffies +
256 msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
257
258 if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
259 (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
260 iwl_rx_calc_noise(priv);
261 queue_work(priv->workqueue, &priv->run_time_calib_work);
262 }
263 if (priv->cfg->ops->lib->temp_ops.temperature && change)
264 priv->cfg->ops->lib->temp_ops.temperature(priv);
265}
266
267void iwl_reply_statistics(struct iwl_priv *priv,
268 struct iwl_rx_mem_buffer *rxb)
269{
270 struct iwl_rx_packet *pkt = rxb_addr(rxb);
271
272 if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
273#ifdef CONFIG_IWLWIFI_DEBUGFS
274 memset(&priv->_agn.accum_statistics, 0,
275 sizeof(struct iwl_notif_statistics));
276 memset(&priv->_agn.delta_statistics, 0,
277 sizeof(struct iwl_notif_statistics));
278 memset(&priv->_agn.max_delta, 0,
279 sizeof(struct iwl_notif_statistics));
280#endif
281 IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
282 }
283 iwl_rx_statistics(priv, rxb);
284}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 84df7fca750d..2573234e4db1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -233,6 +233,7 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
233{ 233{
234 unsigned long flags; 234 unsigned long flags;
235 u16 ra_tid; 235 u16 ra_tid;
236 int ret;
236 237
237 if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || 238 if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
238 (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues 239 (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -248,7 +249,9 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
248 ra_tid = BUILD_RAxTID(sta_id, tid); 249 ra_tid = BUILD_RAxTID(sta_id, tid);
249 250
250 /* Modify device's station table to Tx this TID */ 251 /* Modify device's station table to Tx this TID */
251 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); 252 ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
253 if (ret)
254 return ret;
252 255
253 spin_lock_irqsave(&priv->lock, flags); 256 spin_lock_irqsave(&priv->lock, flags);
254 257
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index d857f8496f69..3368cfd25a99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1461,13 +1461,13 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
1461 1461
1462 actual_ack_cnt_delta = 1462 actual_ack_cnt_delta =
1463 le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - 1463 le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
1464 le32_to_cpu(priv->statistics.tx.actual_ack_cnt); 1464 le32_to_cpu(priv->_agn.statistics.tx.actual_ack_cnt);
1465 expected_ack_cnt_delta = 1465 expected_ack_cnt_delta =
1466 le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - 1466 le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
1467 le32_to_cpu(priv->statistics.tx.expected_ack_cnt); 1467 le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt);
1468 ba_timeout_delta = 1468 ba_timeout_delta =
1469 le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - 1469 le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
1470 le32_to_cpu(priv->statistics.tx.agg.ba_timeout); 1470 le32_to_cpu(priv->_agn.statistics.tx.agg.ba_timeout);
1471 if ((priv->_agn.agg_tids_count > 0) && 1471 if ((priv->_agn.agg_tids_count > 0) &&
1472 (expected_ack_cnt_delta > 0) && 1472 (expected_ack_cnt_delta > 0) &&
1473 (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) 1473 (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
@@ -1484,10 +1484,10 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
1484 * DEBUG is not, these will just compile out. 1484 * DEBUG is not, these will just compile out.
1485 */ 1485 */
1486 IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", 1486 IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
1487 priv->delta_statistics.tx.rx_detected_cnt); 1487 priv->_agn.delta_statistics.tx.rx_detected_cnt);
1488 IWL_DEBUG_RADIO(priv, 1488 IWL_DEBUG_RADIO(priv,
1489 "ack_or_ba_timeout_collision delta = %d\n", 1489 "ack_or_ba_timeout_collision delta = %d\n",
1490 priv->delta_statistics.tx. 1490 priv->_agn.delta_statistics.tx.
1491 ack_or_ba_timeout_collision); 1491 ack_or_ba_timeout_collision);
1492#endif 1492#endif
1493 IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", 1493 IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
@@ -2310,9 +2310,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
2310 trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, 2310 trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
2311 blink1, blink2, ilink1, ilink2); 2311 blink1, blink2, ilink1, ilink2);
2312 2312
2313 IWL_ERR(priv, "Desc Time " 2313 IWL_ERR(priv, "Desc Time "
2314 "data1 data2 line\n"); 2314 "data1 data2 line\n");
2315 IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", 2315 IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
2316 desc_lookup(desc), desc, time, data1, data2, line); 2316 desc_lookup(desc), desc, time, data1, data2, line);
2317 IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); 2317 IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n");
2318 IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", 2318 IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
@@ -2935,9 +2935,9 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
2935 } 2935 }
2936 2936
2937 if (priv->start_calib) { 2937 if (priv->start_calib) {
2938 iwl_chain_noise_calibration(priv, &priv->statistics); 2938 iwl_chain_noise_calibration(priv, &priv->_agn.statistics);
2939 2939
2940 iwl_sensitivity_calibration(priv, &priv->statistics); 2940 iwl_sensitivity_calibration(priv, &priv->_agn.statistics);
2941 } 2941 }
2942 2942
2943 mutex_unlock(&priv->mutex); 2943 mutex_unlock(&priv->mutex);
@@ -3368,13 +3368,32 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3368 return ret; 3368 return ret;
3369} 3369}
3370 3370
3371/*
3372 * switch to RTS/CTS for TX
3373 */
3374static void iwl_enable_rts_cts(struct iwl_priv *priv)
3375{
3376
3377 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3378 return;
3379
3380 priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
3381 if (!test_bit(STATUS_SCANNING, &priv->status)) {
3382 IWL_DEBUG_INFO(priv, "use RTS/CTS protection\n");
3383 iwlcore_commit_rxon(priv);
3384 } else {
3385 /* scanning, defer the request until scan completed */
3386 IWL_DEBUG_INFO(priv, "defer setting RTS/CTS protection\n");
3387 }
3388}
3389
3371static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, 3390static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3372 struct ieee80211_vif *vif, 3391 struct ieee80211_vif *vif,
3373 enum ieee80211_ampdu_mlme_action action, 3392 enum ieee80211_ampdu_mlme_action action,
3374 struct ieee80211_sta *sta, u16 tid, u16 *ssn) 3393 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
3375{ 3394{
3376 struct iwl_priv *priv = hw->priv; 3395 struct iwl_priv *priv = hw->priv;
3377 int ret; 3396 int ret = -EINVAL;
3378 3397
3379 IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", 3398 IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
3380 sta->addr, tid); 3399 sta->addr, tid);
@@ -3382,17 +3401,19 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3382 if (!(priv->cfg->sku & IWL_SKU_N)) 3401 if (!(priv->cfg->sku & IWL_SKU_N))
3383 return -EACCES; 3402 return -EACCES;
3384 3403
3404 mutex_lock(&priv->mutex);
3405
3385 switch (action) { 3406 switch (action) {
3386 case IEEE80211_AMPDU_RX_START: 3407 case IEEE80211_AMPDU_RX_START:
3387 IWL_DEBUG_HT(priv, "start Rx\n"); 3408 IWL_DEBUG_HT(priv, "start Rx\n");
3388 return iwl_sta_rx_agg_start(priv, sta, tid, *ssn); 3409 ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
3410 break;
3389 case IEEE80211_AMPDU_RX_STOP: 3411 case IEEE80211_AMPDU_RX_STOP:
3390 IWL_DEBUG_HT(priv, "stop Rx\n"); 3412 IWL_DEBUG_HT(priv, "stop Rx\n");
3391 ret = iwl_sta_rx_agg_stop(priv, sta, tid); 3413 ret = iwl_sta_rx_agg_stop(priv, sta, tid);
3392 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3414 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3393 return 0; 3415 ret = 0;
3394 else 3416 break;
3395 return ret;
3396 case IEEE80211_AMPDU_TX_START: 3417 case IEEE80211_AMPDU_TX_START:
3397 IWL_DEBUG_HT(priv, "start Tx\n"); 3418 IWL_DEBUG_HT(priv, "start Tx\n");
3398 ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); 3419 ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
@@ -3401,7 +3422,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3401 IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", 3422 IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
3402 priv->_agn.agg_tids_count); 3423 priv->_agn.agg_tids_count);
3403 } 3424 }
3404 return ret; 3425 break;
3405 case IEEE80211_AMPDU_TX_STOP: 3426 case IEEE80211_AMPDU_TX_STOP:
3406 IWL_DEBUG_HT(priv, "stop Tx\n"); 3427 IWL_DEBUG_HT(priv, "stop Tx\n");
3407 ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); 3428 ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
@@ -3411,18 +3432,22 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3411 priv->_agn.agg_tids_count); 3432 priv->_agn.agg_tids_count);
3412 } 3433 }
3413 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3434 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3414 return 0; 3435 ret = 0;
3415 else 3436 break;
3416 return ret;
3417 case IEEE80211_AMPDU_TX_OPERATIONAL: 3437 case IEEE80211_AMPDU_TX_OPERATIONAL:
3418 /* do nothing */ 3438 if (priv->cfg->use_rts_for_ht) {
3419 return -EOPNOTSUPP; 3439 /*
3420 default: 3440 * switch to RTS/CTS if it is the prefer protection
3421 IWL_DEBUG_HT(priv, "unknown\n"); 3441 * method for HT traffic
3422 return -EINVAL; 3442 */
3443 iwl_enable_rts_cts(priv);
3444 }
3445 ret = 0;
3423 break; 3446 break;
3424 } 3447 }
3425 return 0; 3448 mutex_unlock(&priv->mutex);
3449
3450 return ret;
3426} 3451}
3427 3452
3428static void iwl_mac_sta_notify(struct ieee80211_hw *hw, 3453static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 5c32777b0a49..be9d298cae2c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -201,6 +201,16 @@ static inline bool iwl_is_tx_success(u32 status)
201 (status == TX_STATUS_DIRECT_DONE); 201 (status == TX_STATUS_DIRECT_DONE);
202} 202}
203 203
204/* rx */
205void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
206 struct iwl_rx_mem_buffer *rxb);
207bool iwl_good_plcp_health(struct iwl_priv *priv,
208 struct iwl_rx_packet *pkt);
209void iwl_rx_statistics(struct iwl_priv *priv,
210 struct iwl_rx_mem_buffer *rxb);
211void iwl_reply_statistics(struct iwl_priv *priv,
212 struct iwl_rx_mem_buffer *rxb);
213
204/* scan */ 214/* scan */
205void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); 215void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
206 216
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 28b1098334f7..acf8e980b1fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1399,18 +1399,27 @@ struct iwl_rx_mpdu_res_start {
1399 1399
1400/* REPLY_TX Tx flags field */ 1400/* REPLY_TX Tx flags field */
1401 1401
1402/* 1: Use RTS/CTS protocol or CTS-to-self if spec allows it 1402/*
1403 * 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
1403 * before this frame. if CTS-to-self required check 1404 * before this frame. if CTS-to-self required check
1404 * RXON_FLG_SELF_CTS_EN status. */ 1405 * RXON_FLG_SELF_CTS_EN status.
1405#define TX_CMD_FLG_RTS_CTS_MSK cpu_to_le32(1 << 0) 1406 * unused in 3945/4965, used in 5000 series and after
1407 */
1408#define TX_CMD_FLG_PROT_REQUIRE_MSK cpu_to_le32(1 << 0)
1406 1409
1407/* 1: Use Request-To-Send protocol before this frame. 1410/*
1408 * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ 1411 * 1: Use Request-To-Send protocol before this frame.
1412 * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK.
1413 * used in 3945/4965, unused in 5000 series and after
1414 */
1409#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1) 1415#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
1410 1416
1411/* 1: Transmit Clear-To-Send to self before this frame. 1417/*
1418 * 1: Transmit Clear-To-Send to self before this frame.
1412 * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames. 1419 * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
1413 * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */ 1420 * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK.
1421 * used in 3945/4965, unused in 5000 series and after
1422 */
1414#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2) 1423#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
1415 1424
1416/* 1: Expect ACK from receiving station 1425/* 1: Expect ACK from receiving station
@@ -1430,8 +1439,11 @@ struct iwl_rx_mpdu_res_start {
1430 * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */ 1439 * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */
1431#define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6) 1440#define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6)
1432 1441
1433/* 1: Frame requires full Tx-Op protection. 1442/*
1434 * Set this if either RTS or CTS Tx Flag gets set. */ 1443 * 1: Frame requires full Tx-Op protection.
1444 * Set this if either RTS or CTS Tx Flag gets set.
1445 * used in 3945/4965, unused in 5000 series and after
1446 */
1435#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7) 1447#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
1436 1448
1437/* Tx antenna selection field; used only for 3945, reserved (0) for 4965. 1449/* Tx antenna selection field; used only for 3945, reserved (0) for 4965.
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 62c50bc0089a..a56fb466d0b6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1331,7 +1331,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
1331 changed_flags, *total_flags); 1331 changed_flags, *total_flags);
1332 1332
1333 CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); 1333 CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
1334 CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK);
1335 CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); 1334 CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
1336 CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); 1335 CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
1337 1336
@@ -1346,6 +1345,12 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
1346 1345
1347 mutex_unlock(&priv->mutex); 1346 mutex_unlock(&priv->mutex);
1348 1347
1348 /*
1349 * Receiving all multicast frames is always enabled by the
1350 * default flags setup in iwl_connection_init_rx_config()
1351 * since we currently do not support programming multicast
1352 * filters into the device.
1353 */
1349 *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | 1354 *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
1350 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; 1355 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
1351} 1356}
@@ -2105,6 +2110,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
2105 iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); 2110 iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
2106 spin_unlock_irqrestore(&priv->lock, flags); 2111 spin_unlock_irqrestore(&priv->lock, flags);
2107 2112
2113 if (priv->cfg->ops->lib->update_bcast_station)
2114 ret = priv->cfg->ops->lib->update_bcast_station(priv);
2115
2108 set_ch_out: 2116 set_ch_out:
2109 /* The list of supported rates and rate mask can be different 2117 /* The list of supported rates and rate mask can be different
2110 * for each band; since the band may have changed, reset 2118 * for each band; since the band may have changed, reset
@@ -2837,6 +2845,7 @@ int iwl_pci_resume(struct pci_dev *pdev)
2837{ 2845{
2838 struct iwl_priv *priv = pci_get_drvdata(pdev); 2846 struct iwl_priv *priv = pci_get_drvdata(pdev);
2839 int ret; 2847 int ret;
2848 bool hw_rfkill = false;
2840 2849
2841 /* 2850 /*
2842 * We disable the RETRY_TIMEOUT register (0x41) to keep 2851 * We disable the RETRY_TIMEOUT register (0x41) to keep
@@ -2851,6 +2860,17 @@ int iwl_pci_resume(struct pci_dev *pdev)
2851 pci_restore_state(pdev); 2860 pci_restore_state(pdev);
2852 iwl_enable_interrupts(priv); 2861 iwl_enable_interrupts(priv);
2853 2862
2863 if (!(iwl_read32(priv, CSR_GP_CNTRL) &
2864 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
2865 hw_rfkill = true;
2866
2867 if (hw_rfkill)
2868 set_bit(STATUS_RF_KILL_HW, &priv->status);
2869 else
2870 clear_bit(STATUS_RF_KILL_HW, &priv->status);
2871
2872 wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill);
2873
2854 return 0; 2874 return 0;
2855} 2875}
2856EXPORT_SYMBOL(iwl_pci_resume); 2876EXPORT_SYMBOL(iwl_pci_resume);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 76288c56a7d7..15930e064022 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -196,6 +196,7 @@ struct iwl_lib_ops {
196 /* station management */ 196 /* station management */
197 int (*manage_ibss_station)(struct iwl_priv *priv, 197 int (*manage_ibss_station)(struct iwl_priv *priv,
198 struct ieee80211_vif *vif, bool add); 198 struct ieee80211_vif *vif, bool add);
199 int (*update_bcast_station)(struct iwl_priv *priv);
199 /* recover from tx queue stall */ 200 /* recover from tx queue stall */
200 void (*recover_from_tx_stall)(unsigned long data); 201 void (*recover_from_tx_stall)(unsigned long data);
201 /* check for plcp health */ 202 /* check for plcp health */
@@ -330,6 +331,7 @@ struct iwl_cfg {
330 const bool chain_noise_calib_by_driver; 331 const bool chain_noise_calib_by_driver;
331 u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; 332 u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
332 u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; 333 u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
334 const bool need_dc_calib;
333}; 335};
334 336
335/*************************** 337/***************************
@@ -455,20 +457,10 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
455int iwl_rx_queue_space(const struct iwl_rx_queue *q); 457int iwl_rx_queue_space(const struct iwl_rx_queue *q);
456void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); 458void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
457/* Handlers */ 459/* Handlers */
458void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
459 struct iwl_rx_mem_buffer *rxb);
460void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, 460void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
461 struct iwl_rx_mem_buffer *rxb); 461 struct iwl_rx_mem_buffer *rxb);
462bool iwl_good_plcp_health(struct iwl_priv *priv,
463 struct iwl_rx_packet *pkt);
464bool iwl_good_ack_health(struct iwl_priv *priv,
465 struct iwl_rx_packet *pkt);
466void iwl_recover_from_statistics(struct iwl_priv *priv, 462void iwl_recover_from_statistics(struct iwl_priv *priv,
467 struct iwl_rx_packet *pkt); 463 struct iwl_rx_packet *pkt);
468void iwl_rx_statistics(struct iwl_priv *priv,
469 struct iwl_rx_mem_buffer *rxb);
470void iwl_reply_statistics(struct iwl_priv *priv,
471 struct iwl_rx_mem_buffer *rxb);
472void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); 464void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
473void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); 465void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
474 466
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index cee3d12eb383..7d9ffc1575de 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -1430,10 +1430,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
1430 return -EFAULT; 1430 return -EFAULT;
1431 if (sscanf(buf, "%d", &plcp) != 1) 1431 if (sscanf(buf, "%d", &plcp) != 1)
1432 return -EINVAL; 1432 return -EINVAL;
1433 if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || 1433 if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
1434 (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) 1434 (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
1435 priv->cfg->plcp_delta_threshold = 1435 priv->cfg->plcp_delta_threshold =
1436 IWL_MAX_PLCP_ERR_THRESHOLD_DEF; 1436 IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
1437 else 1437 else
1438 priv->cfg->plcp_delta_threshold = plcp; 1438 priv->cfg->plcp_delta_threshold = plcp;
1439 return count; 1439 return count;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 338b5177029d..728752aa1bb5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1036,11 +1036,12 @@ struct iwl_event_log {
1036 * This is the threshold value of plcp error rate per 100mSecs. It is 1036 * This is the threshold value of plcp error rate per 100mSecs. It is
1037 * used to set and check for the validity of plcp_delta. 1037 * used to set and check for the validity of plcp_delta.
1038 */ 1038 */
1039#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0) 1039#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (1)
1040#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50) 1040#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
1041#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) 1041#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
1042#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200) 1042#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
1043#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) 1043#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
1044#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0)
1044 1045
1045#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) 1046#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
1046#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) 1047#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
@@ -1224,13 +1225,6 @@ struct iwl_priv {
1224 struct iwl_power_mgr power_data; 1225 struct iwl_power_mgr power_data;
1225 struct iwl_tt_mgmt thermal_throttle; 1226 struct iwl_tt_mgmt thermal_throttle;
1226 1227
1227 struct iwl_notif_statistics statistics;
1228#ifdef CONFIG_IWLWIFI_DEBUGFS
1229 struct iwl_notif_statistics accum_statistics;
1230 struct iwl_notif_statistics delta_statistics;
1231 struct iwl_notif_statistics max_delta;
1232#endif
1233
1234 /* context information */ 1228 /* context information */
1235 u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ 1229 u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
1236 1230
@@ -1323,6 +1317,13 @@ struct iwl_priv {
1323 1317
1324 u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; 1318 u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
1325 u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; 1319 u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
1320
1321 struct iwl_notif_statistics statistics;
1322#ifdef CONFIG_IWLWIFI_DEBUGFS
1323 struct iwl_notif_statistics accum_statistics;
1324 struct iwl_notif_statistics delta_statistics;
1325 struct iwl_notif_statistics max_delta;
1326#endif
1326 } _agn; 1327 } _agn;
1327#endif 1328#endif
1328 }; 1329 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index ee11452519e6..a45d02e555cf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -629,6 +629,9 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
629 calib_ver < priv->cfg->eeprom_calib_ver) 629 calib_ver < priv->cfg->eeprom_calib_ver)
630 goto err; 630 goto err;
631 631
632 IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
633 eeprom_ver, calib_ver);
634
632 return 0; 635 return 0;
633err: 636err:
634 IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", 637 IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 86a353765796..b437f317b979 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -205,26 +205,6 @@ err_bd:
205} 205}
206EXPORT_SYMBOL(iwl_rx_queue_alloc); 206EXPORT_SYMBOL(iwl_rx_queue_alloc);
207 207
208void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
209 struct iwl_rx_mem_buffer *rxb)
210
211{
212 struct iwl_rx_packet *pkt = rxb_addr(rxb);
213 struct iwl_missed_beacon_notif *missed_beacon;
214
215 missed_beacon = &pkt->u.missed_beacon;
216 if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
217 priv->missed_beacon_threshold) {
218 IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
219 le32_to_cpu(missed_beacon->consecutive_missed_beacons),
220 le32_to_cpu(missed_beacon->total_missed_becons),
221 le32_to_cpu(missed_beacon->num_recvd_beacons),
222 le32_to_cpu(missed_beacon->num_expected_beacons));
223 if (!test_bit(STATUS_SCANNING, &priv->status))
224 iwl_init_sensitivity(priv);
225 }
226}
227EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
228 208
229void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, 209void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
230 struct iwl_rx_mem_buffer *rxb) 210 struct iwl_rx_mem_buffer *rxb)
@@ -243,161 +223,6 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
243} 223}
244EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); 224EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
245 225
246
247
248/* Calculate noise level, based on measurements during network silence just
249 * before arriving beacon. This measurement can be done only if we know
250 * exactly when to expect beacons, therefore only when we're associated. */
251static void iwl_rx_calc_noise(struct iwl_priv *priv)
252{
253 struct statistics_rx_non_phy *rx_info
254 = &(priv->statistics.rx.general);
255 int num_active_rx = 0;
256 int total_silence = 0;
257 int bcn_silence_a =
258 le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
259 int bcn_silence_b =
260 le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
261 int bcn_silence_c =
262 le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
263 int last_rx_noise;
264
265 if (bcn_silence_a) {
266 total_silence += bcn_silence_a;
267 num_active_rx++;
268 }
269 if (bcn_silence_b) {
270 total_silence += bcn_silence_b;
271 num_active_rx++;
272 }
273 if (bcn_silence_c) {
274 total_silence += bcn_silence_c;
275 num_active_rx++;
276 }
277
278 /* Average among active antennas */
279 if (num_active_rx)
280 last_rx_noise = (total_silence / num_active_rx) - 107;
281 else
282 last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
283
284 IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
285 bcn_silence_a, bcn_silence_b, bcn_silence_c,
286 last_rx_noise);
287}
288
289#ifdef CONFIG_IWLWIFI_DEBUGFS
290/*
291 * based on the assumption of all statistics counter are in DWORD
292 * FIXME: This function is for debugging, do not deal with
293 * the case of counters roll-over.
294 */
295static void iwl_accumulative_statistics(struct iwl_priv *priv,
296 __le32 *stats)
297{
298 int i;
299 __le32 *prev_stats;
300 u32 *accum_stats;
301 u32 *delta, *max_delta;
302
303 prev_stats = (__le32 *)&priv->statistics;
304 accum_stats = (u32 *)&priv->accum_statistics;
305 delta = (u32 *)&priv->delta_statistics;
306 max_delta = (u32 *)&priv->max_delta;
307
308 for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
309 i += sizeof(__le32), stats++, prev_stats++, delta++,
310 max_delta++, accum_stats++) {
311 if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
312 *delta = (le32_to_cpu(*stats) -
313 le32_to_cpu(*prev_stats));
314 *accum_stats += *delta;
315 if (*delta > *max_delta)
316 *max_delta = *delta;
317 }
318 }
319
320 /* reset accumulative statistics for "no-counter" type statistics */
321 priv->accum_statistics.general.temperature =
322 priv->statistics.general.temperature;
323 priv->accum_statistics.general.temperature_m =
324 priv->statistics.general.temperature_m;
325 priv->accum_statistics.general.ttl_timestamp =
326 priv->statistics.general.ttl_timestamp;
327 priv->accum_statistics.tx.tx_power.ant_a =
328 priv->statistics.tx.tx_power.ant_a;
329 priv->accum_statistics.tx.tx_power.ant_b =
330 priv->statistics.tx.tx_power.ant_b;
331 priv->accum_statistics.tx.tx_power.ant_c =
332 priv->statistics.tx.tx_power.ant_c;
333}
334#endif
335
336#define REG_RECALIB_PERIOD (60)
337
338/**
339 * iwl_good_plcp_health - checks for plcp error.
340 *
341 * When the plcp error is exceeding the thresholds, reset the radio
342 * to improve the throughput.
343 */
344bool iwl_good_plcp_health(struct iwl_priv *priv,
345 struct iwl_rx_packet *pkt)
346{
347 bool rc = true;
348 int combined_plcp_delta;
349 unsigned int plcp_msec;
350 unsigned long plcp_received_jiffies;
351
352 /*
353 * check for plcp_err and trigger radio reset if it exceeds
354 * the plcp error threshold plcp_delta.
355 */
356 plcp_received_jiffies = jiffies;
357 plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
358 (long) priv->plcp_jiffies);
359 priv->plcp_jiffies = plcp_received_jiffies;
360 /*
361 * check to make sure plcp_msec is not 0 to prevent division
362 * by zero.
363 */
364 if (plcp_msec) {
365 combined_plcp_delta =
366 (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
367 le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
368 (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
369 le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
370
371 if ((combined_plcp_delta > 0) &&
372 ((combined_plcp_delta * 100) / plcp_msec) >
373 priv->cfg->plcp_delta_threshold) {
374 /*
375 * if plcp_err exceed the threshold,
376 * the following data is printed in csv format:
377 * Text: plcp_err exceeded %d,
378 * Received ofdm.plcp_err,
379 * Current ofdm.plcp_err,
380 * Received ofdm_ht.plcp_err,
381 * Current ofdm_ht.plcp_err,
382 * combined_plcp_delta,
383 * plcp_msec
384 */
385 IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
386 "%u, %u, %u, %u, %d, %u mSecs\n",
387 priv->cfg->plcp_delta_threshold,
388 le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
389 le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
390 le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
391 le32_to_cpu(
392 priv->statistics.rx.ofdm_ht.plcp_err),
393 combined_plcp_delta, plcp_msec);
394 rc = false;
395 }
396 }
397 return rc;
398}
399EXPORT_SYMBOL(iwl_good_plcp_health);
400
401void iwl_recover_from_statistics(struct iwl_priv *priv, 226void iwl_recover_from_statistics(struct iwl_priv *priv,
402 struct iwl_rx_packet *pkt) 227 struct iwl_rx_packet *pkt)
403{ 228{
@@ -431,69 +256,6 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
431} 256}
432EXPORT_SYMBOL(iwl_recover_from_statistics); 257EXPORT_SYMBOL(iwl_recover_from_statistics);
433 258
434void iwl_rx_statistics(struct iwl_priv *priv,
435 struct iwl_rx_mem_buffer *rxb)
436{
437 int change;
438 struct iwl_rx_packet *pkt = rxb_addr(rxb);
439
440
441 IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
442 (int)sizeof(priv->statistics),
443 le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
444
445 change = ((priv->statistics.general.temperature !=
446 pkt->u.stats.general.temperature) ||
447 ((priv->statistics.flag &
448 STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
449 (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
450
451#ifdef CONFIG_IWLWIFI_DEBUGFS
452 iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
453#endif
454 iwl_recover_from_statistics(priv, pkt);
455
456 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
457
458 set_bit(STATUS_STATISTICS, &priv->status);
459
460 /* Reschedule the statistics timer to occur in
461 * REG_RECALIB_PERIOD seconds to ensure we get a
462 * thermal update even if the uCode doesn't give
463 * us one */
464 mod_timer(&priv->statistics_periodic, jiffies +
465 msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
466
467 if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
468 (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
469 iwl_rx_calc_noise(priv);
470 queue_work(priv->workqueue, &priv->run_time_calib_work);
471 }
472 if (priv->cfg->ops->lib->temp_ops.temperature && change)
473 priv->cfg->ops->lib->temp_ops.temperature(priv);
474}
475EXPORT_SYMBOL(iwl_rx_statistics);
476
477void iwl_reply_statistics(struct iwl_priv *priv,
478 struct iwl_rx_mem_buffer *rxb)
479{
480 struct iwl_rx_packet *pkt = rxb_addr(rxb);
481
482 if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
483#ifdef CONFIG_IWLWIFI_DEBUGFS
484 memset(&priv->accum_statistics, 0,
485 sizeof(struct iwl_notif_statistics));
486 memset(&priv->delta_statistics, 0,
487 sizeof(struct iwl_notif_statistics));
488 memset(&priv->max_delta, 0,
489 sizeof(struct iwl_notif_statistics));
490#endif
491 IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
492 }
493 iwl_rx_statistics(priv, rxb);
494}
495EXPORT_SYMBOL(iwl_reply_statistics);
496
497/* 259/*
498 * returns non-zero if packet should be dropped 260 * returns non-zero if packet should be dropped
499 */ 261 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 798f93e0ff50..2a7c399fee1e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -537,6 +537,15 @@ void iwl_bg_scan_completed(struct work_struct *work)
537 /* Since setting the TXPOWER may have been deferred while 537 /* Since setting the TXPOWER may have been deferred while
538 * performing the scan, fire one off */ 538 * performing the scan, fire one off */
539 iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); 539 iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
540
541 /*
542 * Since setting the RXON may have been deferred while
543 * performing the scan, fire one off if needed
544 */
545 if (memcmp(&priv->active_rxon,
546 &priv->staging_rxon, sizeof(priv->staging_rxon)))
547 iwlcore_commit_rxon(priv);
548
540 out: 549 out:
541 mutex_unlock(&priv->mutex); 550 mutex_unlock(&priv->mutex);
542 551
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index d57df6c02db3..9511f03f07e0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -30,6 +30,7 @@
30#include <net/mac80211.h> 30#include <net/mac80211.h>
31#include <linux/etherdevice.h> 31#include <linux/etherdevice.h>
32#include <linux/sched.h> 32#include <linux/sched.h>
33#include <linux/lockdep.h>
33 34
34#include "iwl-dev.h" 35#include "iwl-dev.h"
35#include "iwl-core.h" 36#include "iwl-core.h"
@@ -54,18 +55,19 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
54 } 55 }
55} 56}
56 57
57static void iwl_process_add_sta_resp(struct iwl_priv *priv, 58static int iwl_process_add_sta_resp(struct iwl_priv *priv,
58 struct iwl_addsta_cmd *addsta, 59 struct iwl_addsta_cmd *addsta,
59 struct iwl_rx_packet *pkt, 60 struct iwl_rx_packet *pkt,
60 bool sync) 61 bool sync)
61{ 62{
62 u8 sta_id = addsta->sta.sta_id; 63 u8 sta_id = addsta->sta.sta_id;
63 unsigned long flags; 64 unsigned long flags;
65 int ret = -EIO;
64 66
65 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { 67 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
66 IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", 68 IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
67 pkt->hdr.flags); 69 pkt->hdr.flags);
68 return; 70 return ret;
69 } 71 }
70 72
71 IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", 73 IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
@@ -77,6 +79,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv,
77 case ADD_STA_SUCCESS_MSK: 79 case ADD_STA_SUCCESS_MSK:
78 IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); 80 IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
79 iwl_sta_ucode_activate(priv, sta_id); 81 iwl_sta_ucode_activate(priv, sta_id);
82 ret = 0;
80 break; 83 break;
81 case ADD_STA_NO_ROOM_IN_TABLE: 84 case ADD_STA_NO_ROOM_IN_TABLE:
82 IWL_ERR(priv, "Adding station %d failed, no room in table.\n", 85 IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
@@ -114,6 +117,8 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv,
114 STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", 117 STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
115 addsta->sta.addr); 118 addsta->sta.addr);
116 spin_unlock_irqrestore(&priv->sta_lock, flags); 119 spin_unlock_irqrestore(&priv->sta_lock, flags);
120
121 return ret;
117} 122}
118 123
119static void iwl_add_sta_callback(struct iwl_priv *priv, 124static void iwl_add_sta_callback(struct iwl_priv *priv,
@@ -145,8 +150,10 @@ int iwl_send_add_sta(struct iwl_priv *priv,
145 150
146 if (flags & CMD_ASYNC) 151 if (flags & CMD_ASYNC)
147 cmd.callback = iwl_add_sta_callback; 152 cmd.callback = iwl_add_sta_callback;
148 else 153 else {
149 cmd.flags |= CMD_WANT_SKB; 154 cmd.flags |= CMD_WANT_SKB;
155 might_sleep();
156 }
150 157
151 cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); 158 cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
152 ret = iwl_send_cmd(priv, &cmd); 159 ret = iwl_send_cmd(priv, &cmd);
@@ -156,7 +163,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
156 163
157 if (ret == 0) { 164 if (ret == 0) {
158 pkt = (struct iwl_rx_packet *)cmd.reply_page; 165 pkt = (struct iwl_rx_packet *)cmd.reply_page;
159 iwl_process_add_sta_resp(priv, sta, pkt, true); 166 ret = iwl_process_add_sta_resp(priv, sta, pkt, true);
160 } 167 }
161 iwl_free_pages(priv, cmd.reply_page); 168 iwl_free_pages(priv, cmd.reply_page);
162 169
@@ -831,7 +838,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
831{ 838{
832 unsigned long flags; 839 unsigned long flags;
833 __le16 key_flags = 0; 840 __le16 key_flags = 0;
834 int ret; 841 struct iwl_addsta_cmd sta_cmd;
842
843 lockdep_assert_held(&priv->mutex);
835 844
836 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; 845 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
837 846
@@ -871,11 +880,10 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
871 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; 880 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
872 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 881 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
873 882
874 ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); 883 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
875
876 spin_unlock_irqrestore(&priv->sta_lock, flags); 884 spin_unlock_irqrestore(&priv->sta_lock, flags);
877 885
878 return ret; 886 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
879} 887}
880 888
881static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, 889static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
@@ -884,7 +892,9 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
884{ 892{
885 unsigned long flags; 893 unsigned long flags;
886 __le16 key_flags = 0; 894 __le16 key_flags = 0;
887 int ret; 895 struct iwl_addsta_cmd sta_cmd;
896
897 lockdep_assert_held(&priv->mutex);
888 898
889 key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); 899 key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
890 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); 900 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
@@ -919,11 +929,10 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
919 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; 929 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
920 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 930 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
921 931
922 ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); 932 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
923
924 spin_unlock_irqrestore(&priv->sta_lock, flags); 933 spin_unlock_irqrestore(&priv->sta_lock, flags);
925 934
926 return ret; 935 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
927} 936}
928 937
929static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, 938static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
@@ -1013,9 +1022,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
1013 u8 sta_id) 1022 u8 sta_id)
1014{ 1023{
1015 unsigned long flags; 1024 unsigned long flags;
1016 int ret = 0;
1017 u16 key_flags; 1025 u16 key_flags;
1018 u8 keyidx; 1026 u8 keyidx;
1027 struct iwl_addsta_cmd sta_cmd;
1028
1029 lockdep_assert_held(&priv->mutex);
1019 1030
1020 priv->key_mapping_key--; 1031 priv->key_mapping_key--;
1021 1032
@@ -1062,9 +1073,10 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
1062 spin_unlock_irqrestore(&priv->sta_lock, flags); 1073 spin_unlock_irqrestore(&priv->sta_lock, flags);
1063 return 0; 1074 return 0;
1064 } 1075 }
1065 ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); 1076 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
1066 spin_unlock_irqrestore(&priv->sta_lock, flags); 1077 spin_unlock_irqrestore(&priv->sta_lock, flags);
1067 return ret; 1078
1079 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
1068} 1080}
1069EXPORT_SYMBOL(iwl_remove_dynamic_key); 1081EXPORT_SYMBOL(iwl_remove_dynamic_key);
1070 1082
@@ -1073,6 +1085,8 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
1073{ 1085{
1074 int ret; 1086 int ret;
1075 1087
1088 lockdep_assert_held(&priv->mutex);
1089
1076 priv->key_mapping_key++; 1090 priv->key_mapping_key++;
1077 keyconf->hw_key_idx = HW_KEY_DYNAMIC; 1091 keyconf->hw_key_idx = HW_KEY_DYNAMIC;
1078 1092
@@ -1245,6 +1259,36 @@ int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
1245} 1259}
1246EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); 1260EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
1247 1261
1262/**
1263 * iwl_update_bcast_station - update broadcast station's LQ command
1264 *
1265 * Only used by iwlagn. Placed here to have all bcast station management
1266 * code together.
1267 */
1268int iwl_update_bcast_station(struct iwl_priv *priv)
1269{
1270 unsigned long flags;
1271 struct iwl_link_quality_cmd *link_cmd;
1272 u8 sta_id = priv->hw_params.bcast_sta_id;
1273
1274 link_cmd = iwl_sta_alloc_lq(priv, sta_id);
1275 if (!link_cmd) {
1276 IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
1277 return -ENOMEM;
1278 }
1279
1280 spin_lock_irqsave(&priv->sta_lock, flags);
1281 if (priv->stations[sta_id].lq)
1282 kfree(priv->stations[sta_id].lq);
1283 else
1284 IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
1285 priv->stations[sta_id].lq = link_cmd;
1286 spin_unlock_irqrestore(&priv->sta_lock, flags);
1287
1288 return 0;
1289}
1290EXPORT_SYMBOL_GPL(iwl_update_bcast_station);
1291
1248void iwl_dealloc_bcast_station(struct iwl_priv *priv) 1292void iwl_dealloc_bcast_station(struct iwl_priv *priv)
1249{ 1293{
1250 unsigned long flags; 1294 unsigned long flags;
@@ -1268,17 +1312,22 @@ EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
1268/** 1312/**
1269 * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table 1313 * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
1270 */ 1314 */
1271void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) 1315int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
1272{ 1316{
1273 unsigned long flags; 1317 unsigned long flags;
1318 struct iwl_addsta_cmd sta_cmd;
1319
1320 lockdep_assert_held(&priv->mutex);
1274 1321
1275 /* Remove "disable" flag, to enable Tx for this TID */ 1322 /* Remove "disable" flag, to enable Tx for this TID */
1276 spin_lock_irqsave(&priv->sta_lock, flags); 1323 spin_lock_irqsave(&priv->sta_lock, flags);
1277 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; 1324 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
1278 priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); 1325 priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
1279 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1326 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1280 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); 1327 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
1281 spin_unlock_irqrestore(&priv->sta_lock, flags); 1328 spin_unlock_irqrestore(&priv->sta_lock, flags);
1329
1330 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
1282} 1331}
1283EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); 1332EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
1284 1333
@@ -1287,6 +1336,9 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
1287{ 1336{
1288 unsigned long flags; 1337 unsigned long flags;
1289 int sta_id; 1338 int sta_id;
1339 struct iwl_addsta_cmd sta_cmd;
1340
1341 lockdep_assert_held(&priv->mutex);
1290 1342
1291 sta_id = iwl_sta_id(sta); 1343 sta_id = iwl_sta_id(sta);
1292 if (sta_id == IWL_INVALID_STATION) 1344 if (sta_id == IWL_INVALID_STATION)
@@ -1298,10 +1350,10 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
1298 priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; 1350 priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
1299 priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); 1351 priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
1300 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1352 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1353 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
1301 spin_unlock_irqrestore(&priv->sta_lock, flags); 1354 spin_unlock_irqrestore(&priv->sta_lock, flags);
1302 1355
1303 return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 1356 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
1304 CMD_ASYNC);
1305} 1357}
1306EXPORT_SYMBOL(iwl_sta_rx_agg_start); 1358EXPORT_SYMBOL(iwl_sta_rx_agg_start);
1307 1359
@@ -1309,7 +1361,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
1309 int tid) 1361 int tid)
1310{ 1362{
1311 unsigned long flags; 1363 unsigned long flags;
1312 int sta_id, ret; 1364 int sta_id;
1365 struct iwl_addsta_cmd sta_cmd;
1366
1367 lockdep_assert_held(&priv->mutex);
1313 1368
1314 sta_id = iwl_sta_id(sta); 1369 sta_id = iwl_sta_id(sta);
1315 if (sta_id == IWL_INVALID_STATION) { 1370 if (sta_id == IWL_INVALID_STATION) {
@@ -1322,11 +1377,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
1322 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; 1377 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
1323 priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; 1378 priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
1324 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1379 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1325 ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); 1380 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
1326 spin_unlock_irqrestore(&priv->sta_lock, flags); 1381 spin_unlock_irqrestore(&priv->sta_lock, flags);
1327 1382
1328 return ret; 1383 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
1329
1330} 1384}
1331EXPORT_SYMBOL(iwl_sta_rx_agg_stop); 1385EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
1332 1386
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 5b1b1e461eb6..ba95b1a590a5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -60,6 +60,7 @@ void iwl_restore_stations(struct iwl_priv *priv);
60void iwl_clear_ucode_stations(struct iwl_priv *priv); 60void iwl_clear_ucode_stations(struct iwl_priv *priv);
61int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); 61int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
62void iwl_dealloc_bcast_station(struct iwl_priv *priv); 62void iwl_dealloc_bcast_station(struct iwl_priv *priv);
63int iwl_update_bcast_station(struct iwl_priv *priv);
63int iwl_get_free_ucode_key_index(struct iwl_priv *priv); 64int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
64int iwl_send_add_sta(struct iwl_priv *priv, 65int iwl_send_add_sta(struct iwl_priv *priv,
65 struct iwl_addsta_cmd *sta, u8 flags); 66 struct iwl_addsta_cmd *sta, u8 flags);
@@ -73,7 +74,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
73 const u8 *addr); 74 const u8 *addr);
74int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 75int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
75 struct ieee80211_sta *sta); 76 struct ieee80211_sta *sta);
76void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); 77int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
77int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, 78int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
78 int tid, u16 ssn); 79 int tid, u16 ssn);
79int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, 80int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 697fa6caaceb..8eb347106902 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1424,7 +1424,7 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
1424 iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32)); 1424 iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
1425 1425
1426 IWL_ERR(priv, 1426 IWL_ERR(priv,
1427 "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", 1427 "%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
1428 desc_lookup(desc), desc, time, blink1, blink2, 1428 desc_lookup(desc), desc, time, blink1, blink2,
1429 ilink1, ilink2, data1); 1429 ilink1, ilink2, data1);
1430 trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0, 1430 trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0,
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index 902e95f70f6e..60619678f4ec 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -670,20 +670,24 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
670} 670}
671 671
672static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, 672static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
673 enum tx_power_setting type, int dbm) 673 enum nl80211_tx_power_setting type, int mbm)
674{ 674{
675 struct iwm_priv *iwm = wiphy_to_iwm(wiphy); 675 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
676 int ret; 676 int ret;
677 677
678 switch (type) { 678 switch (type) {
679 case TX_POWER_AUTOMATIC: 679 case NL80211_TX_POWER_AUTOMATIC:
680 return 0; 680 return 0;
681 case TX_POWER_FIXED: 681 case NL80211_TX_POWER_FIXED:
682 if (mbm < 0 || (mbm % 100))
683 return -EOPNOTSUPP;
684
682 if (!test_bit(IWM_STATUS_READY, &iwm->status)) 685 if (!test_bit(IWM_STATUS_READY, &iwm->status))
683 return 0; 686 return 0;
684 687
685 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, 688 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
686 CFG_TX_PWR_LIMIT_USR, dbm * 2); 689 CFG_TX_PWR_LIMIT_USR,
690 MBM_TO_DBM(mbm) * 2);
687 if (ret < 0) 691 if (ret < 0)
688 return ret; 692 return ret;
689 693
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 45e870e33117..f7d01bfa2e4a 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -1,4 +1,3 @@
1libertas-y += assoc.o
2libertas-y += cfg.o 1libertas-y += cfg.o
3libertas-y += cmd.o 2libertas-y += cmd.o
4libertas-y += cmdresp.o 3libertas-y += cmdresp.o
@@ -6,9 +5,7 @@ libertas-y += debugfs.o
6libertas-y += ethtool.o 5libertas-y += ethtool.o
7libertas-y += main.o 6libertas-y += main.o
8libertas-y += rx.o 7libertas-y += rx.o
9libertas-y += scan.o
10libertas-y += tx.o 8libertas-y += tx.o
11libertas-y += wext.o
12libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o 9libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o
13 10
14usb8xxx-objs += if_usb.o 11usb8xxx-objs += if_usb.o
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
deleted file mode 100644
index aa06070e5eab..000000000000
--- a/drivers/net/wireless/libertas/assoc.c
+++ /dev/null
@@ -1,2264 +0,0 @@
1/* Copyright (C) 2006, Red Hat, Inc. */
2
3#include <linux/types.h>
4#include <linux/etherdevice.h>
5#include <linux/ieee80211.h>
6#include <linux/if_arp.h>
7#include <linux/slab.h>
8#include <net/lib80211.h>
9
10#include "assoc.h"
11#include "decl.h"
12#include "host.h"
13#include "scan.h"
14#include "cmd.h"
15
16static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
17 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
18static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
19 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
20
21/* The firmware needs the following bits masked out of the beacon-derived
22 * capability field when associating/joining to a BSS:
23 * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused)
24 */
25#define CAPINFO_MASK (~(0xda00))
26
27/**
28 * 802.11b/g supported bitrates (in 500Kb/s units)
29 */
30u8 lbs_bg_rates[MAX_RATES] =
31 { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
320x00, 0x00 };
33
34
35static int assoc_helper_wep_keys(struct lbs_private *priv,
36 struct assoc_request *assoc_req);
37
38/**
39 * @brief This function finds common rates between rates and card rates.
40 *
41 * It will fill common rates in rates as output if found.
42 *
43 * NOTE: Setting the MSB of the basic rates need to be taken
44 * care, either before or after calling this function
45 *
46 * @param priv A pointer to struct lbs_private structure
47 * @param rates the buffer which keeps input and output
48 * @param rates_size the size of rates buffer; new size of buffer on return,
49 * which will be less than or equal to original rates_size
50 *
51 * @return 0 on success, or -1 on error
52 */
53static int get_common_rates(struct lbs_private *priv,
54 u8 *rates,
55 u16 *rates_size)
56{
57 int i, j;
58 u8 intersection[MAX_RATES];
59 u16 intersection_size;
60 u16 num_rates = 0;
61
62 intersection_size = min_t(u16, *rates_size, ARRAY_SIZE(intersection));
63
64 /* Allow each rate from 'rates' that is supported by the hardware */
65 for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && lbs_bg_rates[i]; i++) {
66 for (j = 0; j < intersection_size && rates[j]; j++) {
67 if (rates[j] == lbs_bg_rates[i])
68 intersection[num_rates++] = rates[j];
69 }
70 }
71
72 lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
73 lbs_deb_hex(LBS_DEB_JOIN, "card rates ", lbs_bg_rates,
74 ARRAY_SIZE(lbs_bg_rates));
75 lbs_deb_hex(LBS_DEB_JOIN, "common rates", intersection, num_rates);
76 lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
77
78 if (!priv->enablehwauto) {
79 for (i = 0; i < num_rates; i++) {
80 if (intersection[i] == priv->cur_rate)
81 goto done;
82 }
83 lbs_pr_alert("Previously set fixed data rate %#x isn't "
84 "compatible with the network.\n", priv->cur_rate);
85 return -1;
86 }
87
88done:
89 memset(rates, 0, *rates_size);
90 *rates_size = num_rates;
91 memcpy(rates, intersection, num_rates);
92 return 0;
93}
94
95
96/**
97 * @brief Sets the MSB on basic rates as the firmware requires
98 *
99 * Scan through an array and set the MSB for basic data rates.
100 *
101 * @param rates buffer of data rates
102 * @param len size of buffer
103 */
104static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
105{
106 int i;
107
108 for (i = 0; i < len; i++) {
109 if (rates[i] == 0x02 || rates[i] == 0x04 ||
110 rates[i] == 0x0b || rates[i] == 0x16)
111 rates[i] |= 0x80;
112 }
113}
114
115
116static u8 iw_auth_to_ieee_auth(u8 auth)
117{
118 if (auth == IW_AUTH_ALG_OPEN_SYSTEM)
119 return 0x00;
120 else if (auth == IW_AUTH_ALG_SHARED_KEY)
121 return 0x01;
122 else if (auth == IW_AUTH_ALG_LEAP)
123 return 0x80;
124
125 lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth);
126 return 0;
127}
128
129/**
130 * @brief This function prepares the authenticate command. AUTHENTICATE only
131 * sets the authentication suite for future associations, as the firmware
132 * handles authentication internally during the ASSOCIATE command.
133 *
134 * @param priv A pointer to struct lbs_private structure
135 * @param bssid The peer BSSID with which to authenticate
136 * @param auth The authentication mode to use (from wireless.h)
137 *
138 * @return 0 or -1
139 */
140static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth)
141{
142 struct cmd_ds_802_11_authenticate cmd;
143 int ret = -1;
144
145 lbs_deb_enter(LBS_DEB_JOIN);
146
147 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
148 memcpy(cmd.bssid, bssid, ETH_ALEN);
149
150 cmd.authtype = iw_auth_to_ieee_auth(auth);
151
152 lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype);
153
154 ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
155
156 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
157 return ret;
158}
159
160
161int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
162 struct assoc_request *assoc)
163{
164 struct cmd_ds_802_11_set_wep cmd;
165 int ret = 0;
166
167 lbs_deb_enter(LBS_DEB_CMD);
168
169 memset(&cmd, 0, sizeof(cmd));
170 cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
171 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
172
173 cmd.action = cpu_to_le16(cmd_action);
174
175 if (cmd_action == CMD_ACT_ADD) {
176 int i;
177
178 /* default tx key index */
179 cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
180 CMD_WEP_KEY_INDEX_MASK);
181
182 /* Copy key types and material to host command structure */
183 for (i = 0; i < 4; i++) {
184 struct enc_key *pkey = &assoc->wep_keys[i];
185
186 switch (pkey->len) {
187 case KEY_LEN_WEP_40:
188 cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
189 memmove(cmd.keymaterial[i], pkey->key, pkey->len);
190 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
191 break;
192 case KEY_LEN_WEP_104:
193 cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
194 memmove(cmd.keymaterial[i], pkey->key, pkey->len);
195 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
196 break;
197 case 0:
198 break;
199 default:
200 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
201 i, pkey->len);
202 ret = -1;
203 goto done;
204 break;
205 }
206 }
207 } else if (cmd_action == CMD_ACT_REMOVE) {
208 /* ACT_REMOVE clears _all_ WEP keys */
209
210 /* default tx key index */
211 cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
212 CMD_WEP_KEY_INDEX_MASK);
213 lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
214 }
215
216 ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
217done:
218 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
219 return ret;
220}
221
222int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
223 uint16_t *enable)
224{
225 struct cmd_ds_802_11_enable_rsn cmd;
226 int ret;
227
228 lbs_deb_enter(LBS_DEB_CMD);
229
230 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
231 cmd.action = cpu_to_le16(cmd_action);
232
233 if (cmd_action == CMD_ACT_GET)
234 cmd.enable = 0;
235 else {
236 if (*enable)
237 cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
238 else
239 cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
240 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
241 }
242
243 ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
244 if (!ret && cmd_action == CMD_ACT_GET)
245 *enable = le16_to_cpu(cmd.enable);
246
247 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
248 return ret;
249}
250
251static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
252 struct enc_key *key)
253{
254 lbs_deb_enter(LBS_DEB_CMD);
255
256 if (key->flags & KEY_INFO_WPA_ENABLED)
257 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
258 if (key->flags & KEY_INFO_WPA_UNICAST)
259 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
260 if (key->flags & KEY_INFO_WPA_MCAST)
261 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
262
263 keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
264 keyparam->keytypeid = cpu_to_le16(key->type);
265 keyparam->keylen = cpu_to_le16(key->len);
266 memcpy(keyparam->key, key->key, key->len);
267
268 /* Length field doesn't include the {type,length} header */
269 keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
270 lbs_deb_leave(LBS_DEB_CMD);
271}
272
273int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
274 struct assoc_request *assoc)
275{
276 struct cmd_ds_802_11_key_material cmd;
277 int ret = 0;
278 int index = 0;
279
280 lbs_deb_enter(LBS_DEB_CMD);
281
282 cmd.action = cpu_to_le16(cmd_action);
283 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
284
285 if (cmd_action == CMD_ACT_GET) {
286 cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2);
287 } else {
288 memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
289
290 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
291 set_one_wpa_key(&cmd.keyParamSet[index],
292 &assoc->wpa_unicast_key);
293 index++;
294 }
295
296 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
297 set_one_wpa_key(&cmd.keyParamSet[index],
298 &assoc->wpa_mcast_key);
299 index++;
300 }
301
302 /* The common header and as many keys as we included */
303 cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
304 keyParamSet[index]));
305 }
306 ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
307 /* Copy the returned key to driver private data */
308 if (!ret && cmd_action == CMD_ACT_GET) {
309 void *buf_ptr = cmd.keyParamSet;
310 void *resp_end = &(&cmd)[1];
311
312 while (buf_ptr < resp_end) {
313 struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
314 struct enc_key *key;
315 uint16_t param_set_len = le16_to_cpu(keyparam->length);
316 uint16_t key_len = le16_to_cpu(keyparam->keylen);
317 uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
318 uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
319 void *end;
320
321 end = (void *)keyparam + sizeof(keyparam->type)
322 + sizeof(keyparam->length) + param_set_len;
323
324 /* Make sure we don't access past the end of the IEs */
325 if (end > resp_end)
326 break;
327
328 if (key_flags & KEY_INFO_WPA_UNICAST)
329 key = &priv->wpa_unicast_key;
330 else if (key_flags & KEY_INFO_WPA_MCAST)
331 key = &priv->wpa_mcast_key;
332 else
333 break;
334
335 /* Copy returned key into driver */
336 memset(key, 0, sizeof(struct enc_key));
337 if (key_len > sizeof(key->key))
338 break;
339 key->type = key_type;
340 key->flags = key_flags;
341 key->len = key_len;
342 memcpy(key->key, keyparam->key, key->len);
343
344 buf_ptr = end + 1;
345 }
346 }
347
348 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
349 return ret;
350}
351
352static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
353{
354/* Bit Rate
355* 15:13 Reserved
356* 12 54 Mbps
357* 11 48 Mbps
358* 10 36 Mbps
359* 9 24 Mbps
360* 8 18 Mbps
361* 7 12 Mbps
362* 6 9 Mbps
363* 5 6 Mbps
364* 4 Reserved
365* 3 11 Mbps
366* 2 5.5 Mbps
367* 1 2 Mbps
368* 0 1 Mbps
369**/
370
371 uint16_t ratemask;
372 int i = lbs_data_rate_to_fw_index(rate);
373 if (lower_rates_ok)
374 ratemask = (0x1fef >> (12 - i));
375 else
376 ratemask = (1 << i);
377 return cpu_to_le16(ratemask);
378}
379
380int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
381 uint16_t cmd_action)
382{
383 struct cmd_ds_802_11_rate_adapt_rateset cmd;
384 int ret;
385
386 lbs_deb_enter(LBS_DEB_CMD);
387
388 if (!priv->cur_rate && !priv->enablehwauto)
389 return -EINVAL;
390
391 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
392
393 cmd.action = cpu_to_le16(cmd_action);
394 cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
395 cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
396 ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
397 if (!ret && cmd_action == CMD_ACT_GET)
398 priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
399
400 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
401 return ret;
402}
403
404/**
405 * @brief Set the data rate
406 *
407 * @param priv A pointer to struct lbs_private structure
408 * @param rate The desired data rate, or 0 to clear a locked rate
409 *
410 * @return 0 on success, error on failure
411 */
412int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
413{
414 struct cmd_ds_802_11_data_rate cmd;
415 int ret = 0;
416
417 lbs_deb_enter(LBS_DEB_CMD);
418
419 memset(&cmd, 0, sizeof(cmd));
420 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
421
422 if (rate > 0) {
423 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
424 cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
425 if (cmd.rates[0] == 0) {
426 lbs_deb_cmd("DATA_RATE: invalid requested rate of"
427 " 0x%02X\n", rate);
428 ret = 0;
429 goto out;
430 }
431 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
432 } else {
433 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
434 lbs_deb_cmd("DATA_RATE: setting auto\n");
435 }
436
437 ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
438 if (ret)
439 goto out;
440
441 lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd));
442
443 /* FIXME: get actual rates FW can do if this command actually returns
444 * all data rates supported.
445 */
446 priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
447 lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
448
449out:
450 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
451 return ret;
452}
453
454
455int lbs_cmd_802_11_rssi(struct lbs_private *priv,
456 struct cmd_ds_command *cmd)
457{
458
459 lbs_deb_enter(LBS_DEB_CMD);
460 cmd->command = cpu_to_le16(CMD_802_11_RSSI);
461 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) +
462 sizeof(struct cmd_header));
463 cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
464
465 /* reset Beacon SNR/NF/RSSI values */
466 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
467 priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
468 priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
469 priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
470 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
471 priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
472
473 lbs_deb_leave(LBS_DEB_CMD);
474 return 0;
475}
476
477int lbs_ret_802_11_rssi(struct lbs_private *priv,
478 struct cmd_ds_command *resp)
479{
480 struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
481
482 lbs_deb_enter(LBS_DEB_CMD);
483
484 /* store the non average value */
485 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
486 priv->NF[TYPE_BEACON][TYPE_NOAVG] =
487 get_unaligned_le16(&rssirsp->noisefloor);
488
489 priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
490 priv->NF[TYPE_BEACON][TYPE_AVG] =
491 get_unaligned_le16(&rssirsp->avgnoisefloor);
492
493 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
494 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
495 priv->NF[TYPE_BEACON][TYPE_NOAVG]);
496
497 priv->RSSI[TYPE_BEACON][TYPE_AVG] =
498 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
499 priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
500
501 lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
502 priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
503 priv->RSSI[TYPE_BEACON][TYPE_AVG]);
504
505 lbs_deb_leave(LBS_DEB_CMD);
506 return 0;
507}
508
509
510int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
511 struct cmd_ds_command *cmd,
512 u16 cmd_action)
513{
514 struct cmd_ds_802_11_beacon_control
515 *bcn_ctrl = &cmd->params.bcn_ctrl;
516
517 lbs_deb_enter(LBS_DEB_CMD);
518 cmd->size =
519 cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
520 + sizeof(struct cmd_header));
521 cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
522
523 bcn_ctrl->action = cpu_to_le16(cmd_action);
524 bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
525 bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
526
527 lbs_deb_leave(LBS_DEB_CMD);
528 return 0;
529}
530
531int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
532 struct cmd_ds_command *resp)
533{
534 struct cmd_ds_802_11_beacon_control *bcn_ctrl =
535 &resp->params.bcn_ctrl;
536
537 lbs_deb_enter(LBS_DEB_CMD);
538
539 if (bcn_ctrl->action == CMD_ACT_GET) {
540 priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
541 priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
542 }
543
544 lbs_deb_enter(LBS_DEB_CMD);
545 return 0;
546}
547
548
549
550static int lbs_assoc_post(struct lbs_private *priv,
551 struct cmd_ds_802_11_associate_response *resp)
552{
553 int ret = 0;
554 union iwreq_data wrqu;
555 struct bss_descriptor *bss;
556 u16 status_code;
557
558 lbs_deb_enter(LBS_DEB_ASSOC);
559
560 if (!priv->in_progress_assoc_req) {
561 lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
562 ret = -1;
563 goto done;
564 }
565 bss = &priv->in_progress_assoc_req->bss;
566
567 /*
568 * Older FW versions map the IEEE 802.11 Status Code in the association
569 * response to the following values returned in resp->statuscode:
570 *
571 * IEEE Status Code Marvell Status Code
572 * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
573 * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
574 * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
575 * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
576 * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
577 * others -> 0x0003 ASSOC_RESULT_REFUSED
578 *
579 * Other response codes:
580 * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
581 * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
582 * association response from the AP)
583 */
584
585 status_code = le16_to_cpu(resp->statuscode);
586 if (priv->fwrelease < 0x09000000) {
587 switch (status_code) {
588 case 0x00:
589 break;
590 case 0x01:
591 lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
592 break;
593 case 0x02:
594 lbs_deb_assoc("ASSOC_RESP: internal timer "
595 "expired while waiting for the AP\n");
596 break;
597 case 0x03:
598 lbs_deb_assoc("ASSOC_RESP: association "
599 "refused by AP\n");
600 break;
601 case 0x04:
602 lbs_deb_assoc("ASSOC_RESP: authentication "
603 "refused by AP\n");
604 break;
605 default:
606 lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
607 " unknown\n", status_code);
608 break;
609 }
610 } else {
611 /* v9+ returns the AP's association response */
612 lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code);
613 }
614
615 if (status_code) {
616 lbs_mac_event_disconnected(priv);
617 ret = status_code;
618 goto done;
619 }
620
621 lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP",
622 (void *) (resp + sizeof (resp->hdr)),
623 le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr));
624
625 /* Send a Media Connected event, according to the Spec */
626 priv->connect_status = LBS_CONNECTED;
627
628 /* Update current SSID and BSSID */
629 memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
630 priv->curbssparams.ssid_len = bss->ssid_len;
631 memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
632
633 priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
634 priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
635
636 memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
637 memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
638 priv->nextSNRNF = 0;
639 priv->numSNRNF = 0;
640
641 netif_carrier_on(priv->dev);
642 if (!priv->tx_pending_len)
643 netif_wake_queue(priv->dev);
644
645 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
646 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
647 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
648
649done:
650 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
651 return ret;
652}
653
654/**
655 * @brief This function prepares an association-class command.
656 *
657 * @param priv A pointer to struct lbs_private structure
658 * @param assoc_req The association request describing the BSS to associate
659 * or reassociate with
660 * @param command The actual command, either CMD_802_11_ASSOCIATE or
661 * CMD_802_11_REASSOCIATE
662 *
663 * @return 0 or -1
664 */
665static int lbs_associate(struct lbs_private *priv,
666 struct assoc_request *assoc_req,
667 u16 command)
668{
669 struct cmd_ds_802_11_associate cmd;
670 int ret = 0;
671 struct bss_descriptor *bss = &assoc_req->bss;
672 u8 *pos = &(cmd.iebuf[0]);
673 u16 tmpcap, tmplen, tmpauth;
674 struct mrvl_ie_ssid_param_set *ssid;
675 struct mrvl_ie_ds_param_set *ds;
676 struct mrvl_ie_cf_param_set *cf;
677 struct mrvl_ie_rates_param_set *rates;
678 struct mrvl_ie_rsn_param_set *rsn;
679 struct mrvl_ie_auth_type *auth;
680
681 lbs_deb_enter(LBS_DEB_ASSOC);
682
683 BUG_ON((command != CMD_802_11_ASSOCIATE) &&
684 (command != CMD_802_11_REASSOCIATE));
685
686 memset(&cmd, 0, sizeof(cmd));
687 cmd.hdr.command = cpu_to_le16(command);
688
689 /* Fill in static fields */
690 memcpy(cmd.bssid, bss->bssid, ETH_ALEN);
691 cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
692
693 /* Capability info */
694 tmpcap = (bss->capability & CAPINFO_MASK);
695 if (bss->mode == IW_MODE_INFRA)
696 tmpcap |= WLAN_CAPABILITY_ESS;
697 cmd.capability = cpu_to_le16(tmpcap);
698 lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
699
700 /* SSID */
701 ssid = (struct mrvl_ie_ssid_param_set *) pos;
702 ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
703 tmplen = bss->ssid_len;
704 ssid->header.len = cpu_to_le16(tmplen);
705 memcpy(ssid->ssid, bss->ssid, tmplen);
706 pos += sizeof(ssid->header) + tmplen;
707
708 ds = (struct mrvl_ie_ds_param_set *) pos;
709 ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
710 ds->header.len = cpu_to_le16(1);
711 ds->channel = bss->phy.ds.channel;
712 pos += sizeof(ds->header) + 1;
713
714 cf = (struct mrvl_ie_cf_param_set *) pos;
715 cf->header.type = cpu_to_le16(TLV_TYPE_CF);
716 tmplen = sizeof(*cf) - sizeof (cf->header);
717 cf->header.len = cpu_to_le16(tmplen);
718 /* IE payload should be zeroed, firmware fills it in for us */
719 pos += sizeof(*cf);
720
721 rates = (struct mrvl_ie_rates_param_set *) pos;
722 rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
723 tmplen = min_t(u16, ARRAY_SIZE(bss->rates), MAX_RATES);
724 memcpy(&rates->rates, &bss->rates, tmplen);
725 if (get_common_rates(priv, rates->rates, &tmplen)) {
726 ret = -1;
727 goto done;
728 }
729 pos += sizeof(rates->header) + tmplen;
730 rates->header.len = cpu_to_le16(tmplen);
731 lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
732
733 /* Copy the infra. association rates into Current BSS state structure */
734 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
735 memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
736
737 /* Set MSB on basic rates as the firmware requires, but _after_
738 * copying to current bss rates.
739 */
740 lbs_set_basic_rate_flags(rates->rates, tmplen);
741
742 /* Firmware v9+ indicate authentication suites as a TLV */
743 if (priv->fwrelease >= 0x09000000) {
744 auth = (struct mrvl_ie_auth_type *) pos;
745 auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
746 auth->header.len = cpu_to_le16(2);
747 tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode);
748 auth->auth = cpu_to_le16(tmpauth);
749 pos += sizeof(auth->header) + 2;
750
751 lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
752 bss->bssid, priv->secinfo.auth_mode);
753 }
754
755 /* WPA/WPA2 IEs */
756 if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
757 rsn = (struct mrvl_ie_rsn_param_set *) pos;
758 /* WPA_IE or WPA2_IE */
759 rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
760 tmplen = (u16) assoc_req->wpa_ie[1];
761 rsn->header.len = cpu_to_le16(tmplen);
762 memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
763 lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn,
764 sizeof(rsn->header) + tmplen);
765 pos += sizeof(rsn->header) + tmplen;
766 }
767
768 cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) +
769 (u16)(pos - (u8 *) &cmd.iebuf));
770
771 /* update curbssparams */
772 priv->channel = bss->phy.ds.channel;
773
774 ret = lbs_cmd_with_response(priv, command, &cmd);
775 if (ret == 0) {
776 ret = lbs_assoc_post(priv,
777 (struct cmd_ds_802_11_associate_response *) &cmd);
778 }
779
780done:
781 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
782 return ret;
783}
784
785/**
786 * @brief Associate to a specific BSS discovered in a scan
787 *
788 * @param priv A pointer to struct lbs_private structure
789 * @param assoc_req The association request describing the BSS to associate with
790 *
791 * @return 0-success, otherwise fail
792 */
793static int lbs_try_associate(struct lbs_private *priv,
794 struct assoc_request *assoc_req)
795{
796 int ret;
797 u8 preamble = RADIO_PREAMBLE_LONG;
798
799 lbs_deb_enter(LBS_DEB_ASSOC);
800
801 /* FW v9 and higher indicate authentication suites as a TLV in the
802 * association command, not as a separate authentication command.
803 */
804 if (priv->fwrelease < 0x09000000) {
805 ret = lbs_set_authentication(priv, assoc_req->bss.bssid,
806 priv->secinfo.auth_mode);
807 if (ret)
808 goto out;
809 }
810
811 /* Use short preamble only when both the BSS and firmware support it */
812 if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
813 preamble = RADIO_PREAMBLE_SHORT;
814
815 ret = lbs_set_radio(priv, preamble, 1);
816 if (ret)
817 goto out;
818
819 ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE);
820 /* If the association fails with current auth mode, let's
821 * try by changing the auth mode
822 */
823 if ((priv->authtype_auto) &&
824 (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) &&
825 (assoc_req->secinfo.wep_enabled) &&
826 (priv->connect_status != LBS_CONNECTED)) {
827 if (priv->secinfo.auth_mode == IW_AUTH_ALG_OPEN_SYSTEM)
828 priv->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
829 else
830 priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
831 if (!assoc_helper_wep_keys(priv, assoc_req))
832 ret = lbs_associate(priv, assoc_req,
833 CMD_802_11_ASSOCIATE);
834 }
835
836 if (ret)
837 ret = -1;
838out:
839 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
840 return ret;
841}
842
843static int lbs_adhoc_post(struct lbs_private *priv,
844 struct cmd_ds_802_11_ad_hoc_result *resp)
845{
846 int ret = 0;
847 u16 command = le16_to_cpu(resp->hdr.command);
848 u16 result = le16_to_cpu(resp->hdr.result);
849 union iwreq_data wrqu;
850 struct bss_descriptor *bss;
851 DECLARE_SSID_BUF(ssid);
852
853 lbs_deb_enter(LBS_DEB_JOIN);
854
855 if (!priv->in_progress_assoc_req) {
856 lbs_deb_join("ADHOC_RESP: no in-progress association "
857 "request\n");
858 ret = -1;
859 goto done;
860 }
861 bss = &priv->in_progress_assoc_req->bss;
862
863 /*
864 * Join result code 0 --> SUCCESS
865 */
866 if (result) {
867 lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
868 if (priv->connect_status == LBS_CONNECTED)
869 lbs_mac_event_disconnected(priv);
870 ret = -1;
871 goto done;
872 }
873
874 /* Send a Media Connected event, according to the Spec */
875 priv->connect_status = LBS_CONNECTED;
876
877 if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
878 /* Update the created network descriptor with the new BSSID */
879 memcpy(bss->bssid, resp->bssid, ETH_ALEN);
880 }
881
882 /* Set the BSSID from the joined/started descriptor */
883 memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
884
885 /* Set the new SSID to current SSID */
886 memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
887 priv->curbssparams.ssid_len = bss->ssid_len;
888
889 netif_carrier_on(priv->dev);
890 if (!priv->tx_pending_len)
891 netif_wake_queue(priv->dev);
892
893 memset(&wrqu, 0, sizeof(wrqu));
894 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
895 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
896 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
897
898 lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
899 print_ssid(ssid, bss->ssid, bss->ssid_len),
900 priv->curbssparams.bssid,
901 priv->channel);
902
903done:
904 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
905 return ret;
906}
907
908/**
909 * @brief Join an adhoc network found in a previous scan
910 *
911 * @param priv A pointer to struct lbs_private structure
912 * @param assoc_req The association request describing the BSS to join
913 *
914 * @return 0 on success, error on failure
915 */
916static int lbs_adhoc_join(struct lbs_private *priv,
917 struct assoc_request *assoc_req)
918{
919 struct cmd_ds_802_11_ad_hoc_join cmd;
920 struct bss_descriptor *bss = &assoc_req->bss;
921 u8 preamble = RADIO_PREAMBLE_LONG;
922 DECLARE_SSID_BUF(ssid);
923 u16 ratesize = 0;
924 int ret = 0;
925
926 lbs_deb_enter(LBS_DEB_ASSOC);
927
928 lbs_deb_join("current SSID '%s', ssid length %u\n",
929 print_ssid(ssid, priv->curbssparams.ssid,
930 priv->curbssparams.ssid_len),
931 priv->curbssparams.ssid_len);
932 lbs_deb_join("requested ssid '%s', ssid length %u\n",
933 print_ssid(ssid, bss->ssid, bss->ssid_len),
934 bss->ssid_len);
935
936 /* check if the requested SSID is already joined */
937 if (priv->curbssparams.ssid_len &&
938 !lbs_ssid_cmp(priv->curbssparams.ssid,
939 priv->curbssparams.ssid_len,
940 bss->ssid, bss->ssid_len) &&
941 (priv->mode == IW_MODE_ADHOC) &&
942 (priv->connect_status == LBS_CONNECTED)) {
943 union iwreq_data wrqu;
944
945 lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
946 "current, not attempting to re-join");
947
948 /* Send the re-association event though, because the association
949 * request really was successful, even if just a null-op.
950 */
951 memset(&wrqu, 0, sizeof(wrqu));
952 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
953 ETH_ALEN);
954 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
955 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
956 goto out;
957 }
958
959 /* Use short preamble only when both the BSS and firmware support it */
960 if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
961 lbs_deb_join("AdhocJoin: Short preamble\n");
962 preamble = RADIO_PREAMBLE_SHORT;
963 }
964
965 ret = lbs_set_radio(priv, preamble, 1);
966 if (ret)
967 goto out;
968
969 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
970 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
971
972 priv->adhoccreate = 0;
973 priv->channel = bss->channel;
974
975 /* Build the join command */
976 memset(&cmd, 0, sizeof(cmd));
977 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
978
979 cmd.bss.type = CMD_BSS_TYPE_IBSS;
980 cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
981
982 memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
983 memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
984
985 memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set));
986
987 memcpy(&cmd.bss.ibss, &bss->ss.ibss,
988 sizeof(struct ieee_ie_ibss_param_set));
989
990 cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
991 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
992 bss->capability, CAPINFO_MASK);
993
994 /* information on BSSID descriptor passed to FW */
995 lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n",
996 cmd.bss.bssid, cmd.bss.ssid);
997
998 /* Only v8 and below support setting these */
999 if (priv->fwrelease < 0x09000000) {
1000 /* failtimeout */
1001 cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
1002 /* probedelay */
1003 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1004 }
1005
1006 /* Copy Data rates from the rates recorded in scan response */
1007 memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
1008 ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), ARRAY_SIZE (bss->rates));
1009 memcpy(cmd.bss.rates, bss->rates, ratesize);
1010 if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
1011 lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
1012 ret = -1;
1013 goto out;
1014 }
1015
1016 /* Copy the ad-hoc creation rates into Current BSS state structure */
1017 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1018 memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize);
1019
1020 /* Set MSB on basic rates as the firmware requires, but _after_
1021 * copying to current bss rates.
1022 */
1023 lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
1024
1025 cmd.bss.ibss.atimwindow = bss->atimwindow;
1026
1027 if (assoc_req->secinfo.wep_enabled) {
1028 u16 tmp = le16_to_cpu(cmd.bss.capability);
1029 tmp |= WLAN_CAPABILITY_PRIVACY;
1030 cmd.bss.capability = cpu_to_le16(tmp);
1031 }
1032
1033 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
1034 __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM);
1035
1036 /* wake up first */
1037 ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1038 CMD_ACT_SET, 0, 0,
1039 &local_ps_mode);
1040 if (ret) {
1041 ret = -1;
1042 goto out;
1043 }
1044 }
1045
1046 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
1047 if (ret == 0) {
1048 ret = lbs_adhoc_post(priv,
1049 (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
1050 }
1051
1052out:
1053 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1054 return ret;
1055}
1056
1057/**
1058 * @brief Start an Adhoc Network
1059 *
1060 * @param priv A pointer to struct lbs_private structure
1061 * @param assoc_req The association request describing the BSS to start
1062 *
1063 * @return 0 on success, error on failure
1064 */
1065static int lbs_adhoc_start(struct lbs_private *priv,
1066 struct assoc_request *assoc_req)
1067{
1068 struct cmd_ds_802_11_ad_hoc_start cmd;
1069 u8 preamble = RADIO_PREAMBLE_SHORT;
1070 size_t ratesize = 0;
1071 u16 tmpcap = 0;
1072 int ret = 0;
1073 DECLARE_SSID_BUF(ssid);
1074
1075 lbs_deb_enter(LBS_DEB_ASSOC);
1076
1077 ret = lbs_set_radio(priv, preamble, 1);
1078 if (ret)
1079 goto out;
1080
1081 /* Build the start command */
1082 memset(&cmd, 0, sizeof(cmd));
1083 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1084
1085 memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
1086
1087 lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
1088 print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
1089 assoc_req->ssid_len);
1090
1091 cmd.bsstype = CMD_BSS_TYPE_IBSS;
1092
1093 if (priv->beacon_period == 0)
1094 priv->beacon_period = MRVDRV_BEACON_INTERVAL;
1095 cmd.beaconperiod = cpu_to_le16(priv->beacon_period);
1096
1097 WARN_ON(!assoc_req->channel);
1098
1099 /* set Physical parameter set */
1100 cmd.ds.header.id = WLAN_EID_DS_PARAMS;
1101 cmd.ds.header.len = 1;
1102 cmd.ds.channel = assoc_req->channel;
1103
1104 /* set IBSS parameter set */
1105 cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS;
1106 cmd.ibss.header.len = 2;
1107 cmd.ibss.atimwindow = cpu_to_le16(0);
1108
1109 /* set capability info */
1110 tmpcap = WLAN_CAPABILITY_IBSS;
1111 if (assoc_req->secinfo.wep_enabled ||
1112 assoc_req->secinfo.WPAenabled ||
1113 assoc_req->secinfo.WPA2enabled) {
1114 lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n");
1115 tmpcap |= WLAN_CAPABILITY_PRIVACY;
1116 } else
1117 lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n");
1118
1119 cmd.capability = cpu_to_le16(tmpcap);
1120
1121 /* Only v8 and below support setting probe delay */
1122 if (priv->fwrelease < 0x09000000)
1123 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1124
1125 ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates));
1126 memcpy(cmd.rates, lbs_bg_rates, ratesize);
1127
1128 /* Copy the ad-hoc creating rates into Current BSS state structure */
1129 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1130 memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize);
1131
1132 /* Set MSB on basic rates as the firmware requires, but _after_
1133 * copying to current bss rates.
1134 */
1135 lbs_set_basic_rate_flags(cmd.rates, ratesize);
1136
1137 lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
1138 cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
1139
1140 lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
1141 assoc_req->channel, assoc_req->band);
1142
1143 priv->adhoccreate = 1;
1144 priv->mode = IW_MODE_ADHOC;
1145
1146 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
1147 if (ret == 0)
1148 ret = lbs_adhoc_post(priv,
1149 (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
1150
1151out:
1152 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1153 return ret;
1154}
1155
1156/**
1157 * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode
1158 *
1159 * @param priv A pointer to struct lbs_private structure
1160 * @return 0 on success, or an error
1161 */
1162int lbs_adhoc_stop(struct lbs_private *priv)
1163{
1164 struct cmd_ds_802_11_ad_hoc_stop cmd;
1165 int ret;
1166
1167 lbs_deb_enter(LBS_DEB_JOIN);
1168
1169 memset(&cmd, 0, sizeof (cmd));
1170 cmd.hdr.size = cpu_to_le16 (sizeof (cmd));
1171
1172 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
1173
1174 /* Clean up everything even if there was an error */
1175 lbs_mac_event_disconnected(priv);
1176
1177 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1178 return ret;
1179}
1180
1181static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
1182 struct bss_descriptor *match_bss)
1183{
1184 if (!secinfo->wep_enabled &&
1185 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1186 match_bss->wpa_ie[0] != WLAN_EID_GENERIC &&
1187 match_bss->rsn_ie[0] != WLAN_EID_RSN &&
1188 !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1189 return 1;
1190 else
1191 return 0;
1192}
1193
1194static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
1195 struct bss_descriptor *match_bss)
1196{
1197 if (secinfo->wep_enabled &&
1198 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1199 (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1200 return 1;
1201 else
1202 return 0;
1203}
1204
1205static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
1206 struct bss_descriptor *match_bss)
1207{
1208 if (!secinfo->wep_enabled && secinfo->WPAenabled &&
1209 (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
1210 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
1211 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
1212 )
1213 return 1;
1214 else
1215 return 0;
1216}
1217
1218static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
1219 struct bss_descriptor *match_bss)
1220{
1221 if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
1222 (match_bss->rsn_ie[0] == WLAN_EID_RSN)
1223 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
1224 (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
1225 )
1226 return 1;
1227 else
1228 return 0;
1229}
1230
1231static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
1232 struct bss_descriptor *match_bss)
1233{
1234 if (!secinfo->wep_enabled &&
1235 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1236 (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) &&
1237 (match_bss->rsn_ie[0] != WLAN_EID_RSN) &&
1238 (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1239 return 1;
1240 else
1241 return 0;
1242}
1243
1244/**
1245 * @brief Check if a scanned network compatible with the driver settings
1246 *
1247 * WEP WPA WPA2 ad-hoc encrypt Network
1248 * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
1249 * 0 0 0 0 NONE 0 0 0 yes No security
1250 * 1 0 0 0 NONE 1 0 0 yes Static WEP
1251 * 0 1 0 0 x 1x 1 x yes WPA
1252 * 0 0 1 0 x 1x x 1 yes WPA2
1253 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
1254 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
1255 *
1256 *
1257 * @param priv A pointer to struct lbs_private
1258 * @param index Index in scantable to check against current driver settings
1259 * @param mode Network mode: Infrastructure or IBSS
1260 *
1261 * @return Index in scantable, or error code if negative
1262 */
1263static int is_network_compatible(struct lbs_private *priv,
1264 struct bss_descriptor *bss, uint8_t mode)
1265{
1266 int matched = 0;
1267
1268 lbs_deb_enter(LBS_DEB_SCAN);
1269
1270 if (bss->mode != mode)
1271 goto done;
1272
1273 matched = match_bss_no_security(&priv->secinfo, bss);
1274 if (matched)
1275 goto done;
1276 matched = match_bss_static_wep(&priv->secinfo, bss);
1277 if (matched)
1278 goto done;
1279 matched = match_bss_wpa(&priv->secinfo, bss);
1280 if (matched) {
1281 lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
1282 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
1283 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
1284 priv->secinfo.wep_enabled ? "e" : "d",
1285 priv->secinfo.WPAenabled ? "e" : "d",
1286 priv->secinfo.WPA2enabled ? "e" : "d",
1287 (bss->capability & WLAN_CAPABILITY_PRIVACY));
1288 goto done;
1289 }
1290 matched = match_bss_wpa2(&priv->secinfo, bss);
1291 if (matched) {
1292 lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
1293 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
1294 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
1295 priv->secinfo.wep_enabled ? "e" : "d",
1296 priv->secinfo.WPAenabled ? "e" : "d",
1297 priv->secinfo.WPA2enabled ? "e" : "d",
1298 (bss->capability & WLAN_CAPABILITY_PRIVACY));
1299 goto done;
1300 }
1301 matched = match_bss_dynamic_wep(&priv->secinfo, bss);
1302 if (matched) {
1303 lbs_deb_scan("is_network_compatible() dynamic WEP: "
1304 "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
1305 bss->wpa_ie[0], bss->rsn_ie[0],
1306 (bss->capability & WLAN_CAPABILITY_PRIVACY));
1307 goto done;
1308 }
1309
1310 /* bss security settings don't match those configured on card */
1311 lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
1312 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
1313 bss->wpa_ie[0], bss->rsn_ie[0],
1314 priv->secinfo.wep_enabled ? "e" : "d",
1315 priv->secinfo.WPAenabled ? "e" : "d",
1316 priv->secinfo.WPA2enabled ? "e" : "d",
1317 (bss->capability & WLAN_CAPABILITY_PRIVACY));
1318
1319done:
1320 lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
1321 return matched;
1322}
1323
1324/**
1325 * @brief This function finds a specific compatible BSSID in the scan list
1326 *
1327 * Used in association code
1328 *
1329 * @param priv A pointer to struct lbs_private
1330 * @param bssid BSSID to find in the scan list
1331 * @param mode Network mode: Infrastructure or IBSS
1332 *
1333 * @return index in BSSID list, or error return code (< 0)
1334 */
1335static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
1336 uint8_t *bssid, uint8_t mode)
1337{
1338 struct bss_descriptor *iter_bss;
1339 struct bss_descriptor *found_bss = NULL;
1340
1341 lbs_deb_enter(LBS_DEB_SCAN);
1342
1343 if (!bssid)
1344 goto out;
1345
1346 lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
1347
1348 /* Look through the scan table for a compatible match. The loop will
1349 * continue past a matched bssid that is not compatible in case there
1350 * is an AP with multiple SSIDs assigned to the same BSSID
1351 */
1352 mutex_lock(&priv->lock);
1353 list_for_each_entry(iter_bss, &priv->network_list, list) {
1354 if (compare_ether_addr(iter_bss->bssid, bssid))
1355 continue; /* bssid doesn't match */
1356 switch (mode) {
1357 case IW_MODE_INFRA:
1358 case IW_MODE_ADHOC:
1359 if (!is_network_compatible(priv, iter_bss, mode))
1360 break;
1361 found_bss = iter_bss;
1362 break;
1363 default:
1364 found_bss = iter_bss;
1365 break;
1366 }
1367 }
1368 mutex_unlock(&priv->lock);
1369
1370out:
1371 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
1372 return found_bss;
1373}
1374
1375/**
1376 * @brief This function finds ssid in ssid list.
1377 *
1378 * Used in association code
1379 *
1380 * @param priv A pointer to struct lbs_private
1381 * @param ssid SSID to find in the list
1382 * @param bssid BSSID to qualify the SSID selection (if provided)
1383 * @param mode Network mode: Infrastructure or IBSS
1384 *
1385 * @return index in BSSID list
1386 */
1387static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
1388 uint8_t *ssid, uint8_t ssid_len,
1389 uint8_t *bssid, uint8_t mode,
1390 int channel)
1391{
1392 u32 bestrssi = 0;
1393 struct bss_descriptor *iter_bss = NULL;
1394 struct bss_descriptor *found_bss = NULL;
1395 struct bss_descriptor *tmp_oldest = NULL;
1396
1397 lbs_deb_enter(LBS_DEB_SCAN);
1398
1399 mutex_lock(&priv->lock);
1400
1401 list_for_each_entry(iter_bss, &priv->network_list, list) {
1402 if (!tmp_oldest ||
1403 (iter_bss->last_scanned < tmp_oldest->last_scanned))
1404 tmp_oldest = iter_bss;
1405
1406 if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
1407 ssid, ssid_len) != 0)
1408 continue; /* ssid doesn't match */
1409 if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
1410 continue; /* bssid doesn't match */
1411 if ((channel > 0) && (iter_bss->channel != channel))
1412 continue; /* channel doesn't match */
1413
1414 switch (mode) {
1415 case IW_MODE_INFRA:
1416 case IW_MODE_ADHOC:
1417 if (!is_network_compatible(priv, iter_bss, mode))
1418 break;
1419
1420 if (bssid) {
1421 /* Found requested BSSID */
1422 found_bss = iter_bss;
1423 goto out;
1424 }
1425
1426 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
1427 bestrssi = SCAN_RSSI(iter_bss->rssi);
1428 found_bss = iter_bss;
1429 }
1430 break;
1431 case IW_MODE_AUTO:
1432 default:
1433 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
1434 bestrssi = SCAN_RSSI(iter_bss->rssi);
1435 found_bss = iter_bss;
1436 }
1437 break;
1438 }
1439 }
1440
1441out:
1442 mutex_unlock(&priv->lock);
1443 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
1444 return found_bss;
1445}
1446
1447static int assoc_helper_essid(struct lbs_private *priv,
1448 struct assoc_request * assoc_req)
1449{
1450 int ret = 0;
1451 struct bss_descriptor * bss;
1452 int channel = -1;
1453 DECLARE_SSID_BUF(ssid);
1454
1455 lbs_deb_enter(LBS_DEB_ASSOC);
1456
1457 /* FIXME: take channel into account when picking SSIDs if a channel
1458 * is set.
1459 */
1460
1461 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
1462 channel = assoc_req->channel;
1463
1464 lbs_deb_assoc("SSID '%s' requested\n",
1465 print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len));
1466 if (assoc_req->mode == IW_MODE_INFRA) {
1467 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
1468 assoc_req->ssid_len);
1469
1470 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
1471 assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
1472 if (bss != NULL) {
1473 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
1474 ret = lbs_try_associate(priv, assoc_req);
1475 } else {
1476 lbs_deb_assoc("SSID not found; cannot associate\n");
1477 }
1478 } else if (assoc_req->mode == IW_MODE_ADHOC) {
1479 /* Scan for the network, do not save previous results. Stale
1480 * scan data will cause us to join a non-existant adhoc network
1481 */
1482 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
1483 assoc_req->ssid_len);
1484
1485 /* Search for the requested SSID in the scan table */
1486 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
1487 assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
1488 if (bss != NULL) {
1489 lbs_deb_assoc("SSID found, will join\n");
1490 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
1491 lbs_adhoc_join(priv, assoc_req);
1492 } else {
1493 /* else send START command */
1494 lbs_deb_assoc("SSID not found, creating adhoc network\n");
1495 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
1496 IEEE80211_MAX_SSID_LEN);
1497 assoc_req->bss.ssid_len = assoc_req->ssid_len;
1498 lbs_adhoc_start(priv, assoc_req);
1499 }
1500 }
1501
1502 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1503 return ret;
1504}
1505
1506
1507static int assoc_helper_bssid(struct lbs_private *priv,
1508 struct assoc_request * assoc_req)
1509{
1510 int ret = 0;
1511 struct bss_descriptor * bss;
1512
1513 lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid);
1514
1515 /* Search for index position in list for requested MAC */
1516 bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
1517 assoc_req->mode);
1518 if (bss == NULL) {
1519 lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, "
1520 "cannot associate.\n", assoc_req->bssid);
1521 goto out;
1522 }
1523
1524 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
1525 if (assoc_req->mode == IW_MODE_INFRA) {
1526 ret = lbs_try_associate(priv, assoc_req);
1527 lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n",
1528 ret);
1529 } else if (assoc_req->mode == IW_MODE_ADHOC) {
1530 lbs_adhoc_join(priv, assoc_req);
1531 }
1532
1533out:
1534 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1535 return ret;
1536}
1537
1538
1539static int assoc_helper_associate(struct lbs_private *priv,
1540 struct assoc_request * assoc_req)
1541{
1542 int ret = 0, done = 0;
1543
1544 lbs_deb_enter(LBS_DEB_ASSOC);
1545
1546 /* If we're given and 'any' BSSID, try associating based on SSID */
1547
1548 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
1549 if (compare_ether_addr(bssid_any, assoc_req->bssid) &&
1550 compare_ether_addr(bssid_off, assoc_req->bssid)) {
1551 ret = assoc_helper_bssid(priv, assoc_req);
1552 done = 1;
1553 }
1554 }
1555
1556 if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
1557 ret = assoc_helper_essid(priv, assoc_req);
1558 }
1559
1560 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1561 return ret;
1562}
1563
1564
1565static int assoc_helper_mode(struct lbs_private *priv,
1566 struct assoc_request * assoc_req)
1567{
1568 int ret = 0;
1569
1570 lbs_deb_enter(LBS_DEB_ASSOC);
1571
1572 if (assoc_req->mode == priv->mode)
1573 goto done;
1574
1575 if (assoc_req->mode == IW_MODE_INFRA) {
1576 if (priv->psstate != PS_STATE_FULL_POWER)
1577 lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
1578 priv->psmode = LBS802_11POWERMODECAM;
1579 }
1580
1581 priv->mode = assoc_req->mode;
1582 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE,
1583 assoc_req->mode == IW_MODE_ADHOC ? 2 : 1);
1584
1585done:
1586 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1587 return ret;
1588}
1589
1590static int assoc_helper_channel(struct lbs_private *priv,
1591 struct assoc_request * assoc_req)
1592{
1593 int ret = 0;
1594
1595 lbs_deb_enter(LBS_DEB_ASSOC);
1596
1597 ret = lbs_update_channel(priv);
1598 if (ret) {
1599 lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
1600 goto done;
1601 }
1602
1603 if (assoc_req->channel == priv->channel)
1604 goto done;
1605
1606 if (priv->mesh_dev) {
1607 /* Change mesh channel first; 21.p21 firmware won't let
1608 you change channel otherwise (even though it'll return
1609 an error to this */
1610 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
1611 assoc_req->channel);
1612 }
1613
1614 lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
1615 priv->channel, assoc_req->channel);
1616
1617 ret = lbs_set_channel(priv, assoc_req->channel);
1618 if (ret < 0)
1619 lbs_deb_assoc("ASSOC: channel: error setting channel.\n");
1620
1621 /* FIXME: shouldn't need to grab the channel _again_ after setting
1622 * it since the firmware is supposed to return the new channel, but
1623 * whatever... */
1624 ret = lbs_update_channel(priv);
1625 if (ret) {
1626 lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
1627 goto done;
1628 }
1629
1630 if (assoc_req->channel != priv->channel) {
1631 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
1632 assoc_req->channel);
1633 goto restore_mesh;
1634 }
1635
1636 if (assoc_req->secinfo.wep_enabled &&
1637 (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
1638 assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) {
1639 /* Make sure WEP keys are re-sent to firmware */
1640 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1641 }
1642
1643 /* Must restart/rejoin adhoc networks after channel change */
1644 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
1645
1646 restore_mesh:
1647 if (priv->mesh_dev)
1648 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
1649 priv->channel);
1650
1651 done:
1652 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1653 return ret;
1654}
1655
1656
1657static int assoc_helper_wep_keys(struct lbs_private *priv,
1658 struct assoc_request *assoc_req)
1659{
1660 int i;
1661 int ret = 0;
1662
1663 lbs_deb_enter(LBS_DEB_ASSOC);
1664
1665 /* Set or remove WEP keys */
1666 if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
1667 assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)
1668 ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req);
1669 else
1670 ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req);
1671
1672 if (ret)
1673 goto out;
1674
1675 /* enable/disable the MAC's WEP packet filter */
1676 if (assoc_req->secinfo.wep_enabled)
1677 priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
1678 else
1679 priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
1680
1681 lbs_set_mac_control(priv);
1682
1683 mutex_lock(&priv->lock);
1684
1685 /* Copy WEP keys into priv wep key fields */
1686 for (i = 0; i < 4; i++) {
1687 memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i],
1688 sizeof(struct enc_key));
1689 }
1690 priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
1691
1692 mutex_unlock(&priv->lock);
1693
1694out:
1695 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1696 return ret;
1697}
1698
1699static int assoc_helper_secinfo(struct lbs_private *priv,
1700 struct assoc_request * assoc_req)
1701{
1702 int ret = 0;
1703 uint16_t do_wpa;
1704 uint16_t rsn = 0;
1705
1706 lbs_deb_enter(LBS_DEB_ASSOC);
1707
1708 memcpy(&priv->secinfo, &assoc_req->secinfo,
1709 sizeof(struct lbs_802_11_security));
1710
1711 lbs_set_mac_control(priv);
1712
1713 /* If RSN is already enabled, don't try to enable it again, since
1714 * ENABLE_RSN resets internal state machines and will clobber the
1715 * 4-way WPA handshake.
1716 */
1717
1718 /* Get RSN enabled/disabled */
1719 ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn);
1720 if (ret) {
1721 lbs_deb_assoc("Failed to get RSN status: %d\n", ret);
1722 goto out;
1723 }
1724
1725 /* Don't re-enable RSN if it's already enabled */
1726 do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled;
1727 if (do_wpa == rsn)
1728 goto out;
1729
1730 /* Set RSN enabled/disabled */
1731 ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa);
1732
1733out:
1734 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1735 return ret;
1736}
1737
1738
1739static int assoc_helper_wpa_keys(struct lbs_private *priv,
1740 struct assoc_request * assoc_req)
1741{
1742 int ret = 0;
1743 unsigned int flags = assoc_req->flags;
1744
1745 lbs_deb_enter(LBS_DEB_ASSOC);
1746
1747 /* Work around older firmware bug where WPA unicast and multicast
1748 * keys must be set independently. Seen in SDIO parts with firmware
1749 * version 5.0.11p0.
1750 */
1751
1752 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
1753 clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
1754 ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
1755 assoc_req->flags = flags;
1756 }
1757
1758 if (ret)
1759 goto out;
1760
1761 memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key,
1762 sizeof(struct enc_key));
1763
1764 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
1765 clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
1766
1767 ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
1768 assoc_req->flags = flags;
1769
1770 memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key,
1771 sizeof(struct enc_key));
1772 }
1773
1774out:
1775 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1776 return ret;
1777}
1778
1779
1780static int assoc_helper_wpa_ie(struct lbs_private *priv,
1781 struct assoc_request * assoc_req)
1782{
1783 int ret = 0;
1784
1785 lbs_deb_enter(LBS_DEB_ASSOC);
1786
1787 if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
1788 memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
1789 priv->wpa_ie_len = assoc_req->wpa_ie_len;
1790 } else {
1791 memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN);
1792 priv->wpa_ie_len = 0;
1793 }
1794
1795 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1796 return ret;
1797}
1798
1799
1800static int should_deauth_infrastructure(struct lbs_private *priv,
1801 struct assoc_request * assoc_req)
1802{
1803 int ret = 0;
1804
1805 if (priv->connect_status != LBS_CONNECTED)
1806 return 0;
1807
1808 lbs_deb_enter(LBS_DEB_ASSOC);
1809 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
1810 lbs_deb_assoc("Deauthenticating due to new SSID\n");
1811 ret = 1;
1812 goto out;
1813 }
1814
1815 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
1816 if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
1817 lbs_deb_assoc("Deauthenticating due to new security\n");
1818 ret = 1;
1819 goto out;
1820 }
1821 }
1822
1823 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
1824 lbs_deb_assoc("Deauthenticating due to new BSSID\n");
1825 ret = 1;
1826 goto out;
1827 }
1828
1829 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
1830 lbs_deb_assoc("Deauthenticating due to channel switch\n");
1831 ret = 1;
1832 goto out;
1833 }
1834
1835 /* FIXME: deal with 'auto' mode somehow */
1836 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
1837 if (assoc_req->mode != IW_MODE_INFRA) {
1838 lbs_deb_assoc("Deauthenticating due to leaving "
1839 "infra mode\n");
1840 ret = 1;
1841 goto out;
1842 }
1843 }
1844
1845out:
1846 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1847 return ret;
1848}
1849
1850
1851static int should_stop_adhoc(struct lbs_private *priv,
1852 struct assoc_request * assoc_req)
1853{
1854 lbs_deb_enter(LBS_DEB_ASSOC);
1855
1856 if (priv->connect_status != LBS_CONNECTED)
1857 return 0;
1858
1859 if (lbs_ssid_cmp(priv->curbssparams.ssid,
1860 priv->curbssparams.ssid_len,
1861 assoc_req->ssid, assoc_req->ssid_len) != 0)
1862 return 1;
1863
1864 /* FIXME: deal with 'auto' mode somehow */
1865 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
1866 if (assoc_req->mode != IW_MODE_ADHOC)
1867 return 1;
1868 }
1869
1870 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
1871 if (assoc_req->channel != priv->channel)
1872 return 1;
1873 }
1874
1875 lbs_deb_leave(LBS_DEB_ASSOC);
1876 return 0;
1877}
1878
1879
1880/**
1881 * @brief This function finds the best SSID in the Scan List
1882 *
1883 * Search the scan table for the best SSID that also matches the current
1884 * adapter network preference (infrastructure or adhoc)
1885 *
1886 * @param priv A pointer to struct lbs_private
1887 *
1888 * @return index in BSSID list
1889 */
1890static struct bss_descriptor *lbs_find_best_ssid_in_list(
1891 struct lbs_private *priv, uint8_t mode)
1892{
1893 uint8_t bestrssi = 0;
1894 struct bss_descriptor *iter_bss;
1895 struct bss_descriptor *best_bss = NULL;
1896
1897 lbs_deb_enter(LBS_DEB_SCAN);
1898
1899 mutex_lock(&priv->lock);
1900
1901 list_for_each_entry(iter_bss, &priv->network_list, list) {
1902 switch (mode) {
1903 case IW_MODE_INFRA:
1904 case IW_MODE_ADHOC:
1905 if (!is_network_compatible(priv, iter_bss, mode))
1906 break;
1907 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
1908 break;
1909 bestrssi = SCAN_RSSI(iter_bss->rssi);
1910 best_bss = iter_bss;
1911 break;
1912 case IW_MODE_AUTO:
1913 default:
1914 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
1915 break;
1916 bestrssi = SCAN_RSSI(iter_bss->rssi);
1917 best_bss = iter_bss;
1918 break;
1919 }
1920 }
1921
1922 mutex_unlock(&priv->lock);
1923 lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
1924 return best_bss;
1925}
1926
1927/**
1928 * @brief Find the best AP
1929 *
1930 * Used from association worker.
1931 *
1932 * @param priv A pointer to struct lbs_private structure
1933 * @param pSSID A pointer to AP's ssid
1934 *
1935 * @return 0--success, otherwise--fail
1936 */
1937static int lbs_find_best_network_ssid(struct lbs_private *priv,
1938 uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
1939 uint8_t *out_mode)
1940{
1941 int ret = -1;
1942 struct bss_descriptor *found;
1943
1944 lbs_deb_enter(LBS_DEB_SCAN);
1945
1946 priv->scan_ssid_len = 0;
1947 lbs_scan_networks(priv, 1);
1948 if (priv->surpriseremoved)
1949 goto out;
1950
1951 found = lbs_find_best_ssid_in_list(priv, preferred_mode);
1952 if (found && (found->ssid_len > 0)) {
1953 memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN);
1954 *out_ssid_len = found->ssid_len;
1955 *out_mode = found->mode;
1956 ret = 0;
1957 }
1958
1959out:
1960 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
1961 return ret;
1962}
1963
1964
1965void lbs_association_worker(struct work_struct *work)
1966{
1967 struct lbs_private *priv = container_of(work, struct lbs_private,
1968 assoc_work.work);
1969 struct assoc_request * assoc_req = NULL;
1970 int ret = 0;
1971 int find_any_ssid = 0;
1972 DECLARE_SSID_BUF(ssid);
1973
1974 lbs_deb_enter(LBS_DEB_ASSOC);
1975
1976 mutex_lock(&priv->lock);
1977 assoc_req = priv->pending_assoc_req;
1978 priv->pending_assoc_req = NULL;
1979 priv->in_progress_assoc_req = assoc_req;
1980 mutex_unlock(&priv->lock);
1981
1982 if (!assoc_req)
1983 goto done;
1984
1985 lbs_deb_assoc(
1986 "Association Request:\n"
1987 " flags: 0x%08lx\n"
1988 " SSID: '%s'\n"
1989 " chann: %d\n"
1990 " band: %d\n"
1991 " mode: %d\n"
1992 " BSSID: %pM\n"
1993 " secinfo: %s%s%s\n"
1994 " auth_mode: %d\n",
1995 assoc_req->flags,
1996 print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
1997 assoc_req->channel, assoc_req->band, assoc_req->mode,
1998 assoc_req->bssid,
1999 assoc_req->secinfo.WPAenabled ? " WPA" : "",
2000 assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
2001 assoc_req->secinfo.wep_enabled ? " WEP" : "",
2002 assoc_req->secinfo.auth_mode);
2003
2004 /* If 'any' SSID was specified, find an SSID to associate with */
2005 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) &&
2006 !assoc_req->ssid_len)
2007 find_any_ssid = 1;
2008
2009 /* But don't use 'any' SSID if there's a valid locked BSSID to use */
2010 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
2011 if (compare_ether_addr(assoc_req->bssid, bssid_any) &&
2012 compare_ether_addr(assoc_req->bssid, bssid_off))
2013 find_any_ssid = 0;
2014 }
2015
2016 if (find_any_ssid) {
2017 u8 new_mode = assoc_req->mode;
2018
2019 ret = lbs_find_best_network_ssid(priv, assoc_req->ssid,
2020 &assoc_req->ssid_len, assoc_req->mode, &new_mode);
2021 if (ret) {
2022 lbs_deb_assoc("Could not find best network\n");
2023 ret = -ENETUNREACH;
2024 goto out;
2025 }
2026
2027 /* Ensure we switch to the mode of the AP */
2028 if (assoc_req->mode == IW_MODE_AUTO) {
2029 set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
2030 assoc_req->mode = new_mode;
2031 }
2032 }
2033
2034 /*
2035 * Check if the attributes being changing require deauthentication
2036 * from the currently associated infrastructure access point.
2037 */
2038 if (priv->mode == IW_MODE_INFRA) {
2039 if (should_deauth_infrastructure(priv, assoc_req)) {
2040 ret = lbs_cmd_80211_deauthenticate(priv,
2041 priv->curbssparams.bssid,
2042 WLAN_REASON_DEAUTH_LEAVING);
2043 if (ret) {
2044 lbs_deb_assoc("Deauthentication due to new "
2045 "configuration request failed: %d\n",
2046 ret);
2047 }
2048 }
2049 } else if (priv->mode == IW_MODE_ADHOC) {
2050 if (should_stop_adhoc(priv, assoc_req)) {
2051 ret = lbs_adhoc_stop(priv);
2052 if (ret) {
2053 lbs_deb_assoc("Teardown of AdHoc network due to "
2054 "new configuration request failed: %d\n",
2055 ret);
2056 }
2057
2058 }
2059 }
2060
2061 /* Send the various configuration bits to the firmware */
2062 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
2063 ret = assoc_helper_mode(priv, assoc_req);
2064 if (ret)
2065 goto out;
2066 }
2067
2068 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
2069 ret = assoc_helper_channel(priv, assoc_req);
2070 if (ret)
2071 goto out;
2072 }
2073
2074 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
2075 ret = assoc_helper_secinfo(priv, assoc_req);
2076 if (ret)
2077 goto out;
2078 }
2079
2080 if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
2081 ret = assoc_helper_wpa_ie(priv, assoc_req);
2082 if (ret)
2083 goto out;
2084 }
2085
2086 /*
2087 * v10 FW wants WPA keys to be set/cleared before WEP key operations,
2088 * otherwise it will fail to correctly associate to WEP networks.
2089 * Other firmware versions don't appear to care.
2090 */
2091 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) ||
2092 test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
2093 ret = assoc_helper_wpa_keys(priv, assoc_req);
2094 if (ret)
2095 goto out;
2096 }
2097
2098 if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) ||
2099 test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
2100 ret = assoc_helper_wep_keys(priv, assoc_req);
2101 if (ret)
2102 goto out;
2103 }
2104
2105
2106 /* SSID/BSSID should be the _last_ config option set, because they
2107 * trigger the association attempt.
2108 */
2109 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) ||
2110 test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
2111 int success = 1;
2112
2113 ret = assoc_helper_associate(priv, assoc_req);
2114 if (ret) {
2115 lbs_deb_assoc("ASSOC: association unsuccessful: %d\n",
2116 ret);
2117 success = 0;
2118 }
2119
2120 if (priv->connect_status != LBS_CONNECTED) {
2121 lbs_deb_assoc("ASSOC: association unsuccessful, "
2122 "not connected\n");
2123 success = 0;
2124 }
2125
2126 if (success) {
2127 lbs_deb_assoc("associated to %pM\n",
2128 priv->curbssparams.bssid);
2129 lbs_prepare_and_send_command(priv,
2130 CMD_802_11_RSSI,
2131 0, CMD_OPTION_WAITFORRSP, 0, NULL);
2132 } else {
2133 ret = -1;
2134 }
2135 }
2136
2137out:
2138 if (ret) {
2139 lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
2140 ret);
2141 }
2142
2143 mutex_lock(&priv->lock);
2144 priv->in_progress_assoc_req = NULL;
2145 mutex_unlock(&priv->lock);
2146 kfree(assoc_req);
2147
2148done:
2149 lbs_deb_leave(LBS_DEB_ASSOC);
2150}
2151
2152
2153/*
2154 * Caller MUST hold any necessary locks
2155 */
2156struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
2157{
2158 struct assoc_request * assoc_req;
2159
2160 lbs_deb_enter(LBS_DEB_ASSOC);
2161 if (!priv->pending_assoc_req) {
2162 priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
2163 GFP_KERNEL);
2164 if (!priv->pending_assoc_req) {
2165 lbs_pr_info("Not enough memory to allocate association"
2166 " request!\n");
2167 return NULL;
2168 }
2169 }
2170
2171 /* Copy current configuration attributes to the association request,
2172 * but don't overwrite any that are already set.
2173 */
2174 assoc_req = priv->pending_assoc_req;
2175 if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
2176 memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
2177 IEEE80211_MAX_SSID_LEN);
2178 assoc_req->ssid_len = priv->curbssparams.ssid_len;
2179 }
2180
2181 if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
2182 assoc_req->channel = priv->channel;
2183
2184 if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
2185 assoc_req->band = priv->curbssparams.band;
2186
2187 if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
2188 assoc_req->mode = priv->mode;
2189
2190 if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
2191 memcpy(&assoc_req->bssid, priv->curbssparams.bssid,
2192 ETH_ALEN);
2193 }
2194
2195 if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
2196 int i;
2197 for (i = 0; i < 4; i++) {
2198 memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i],
2199 sizeof(struct enc_key));
2200 }
2201 }
2202
2203 if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
2204 assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx;
2205
2206 if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
2207 memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key,
2208 sizeof(struct enc_key));
2209 }
2210
2211 if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
2212 memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key,
2213 sizeof(struct enc_key));
2214 }
2215
2216 if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
2217 memcpy(&assoc_req->secinfo, &priv->secinfo,
2218 sizeof(struct lbs_802_11_security));
2219 }
2220
2221 if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
2222 memcpy(&assoc_req->wpa_ie, &priv->wpa_ie,
2223 MAX_WPA_IE_LEN);
2224 assoc_req->wpa_ie_len = priv->wpa_ie_len;
2225 }
2226
2227 lbs_deb_leave(LBS_DEB_ASSOC);
2228 return assoc_req;
2229}
2230
2231
2232/**
2233 * @brief Deauthenticate from a specific BSS
2234 *
2235 * @param priv A pointer to struct lbs_private structure
2236 * @param bssid The specific BSS to deauthenticate from
2237 * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating
2238 *
2239 * @return 0 on success, error on failure
2240 */
2241int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN],
2242 u16 reason)
2243{
2244 struct cmd_ds_802_11_deauthenticate cmd;
2245 int ret;
2246
2247 lbs_deb_enter(LBS_DEB_JOIN);
2248
2249 memset(&cmd, 0, sizeof(cmd));
2250 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
2251 memcpy(cmd.macaddr, &bssid[0], ETH_ALEN);
2252 cmd.reasoncode = cpu_to_le16(reason);
2253
2254 ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
2255
2256 /* Clean up everything even if there was an error; can't assume that
2257 * we're still authenticated to the AP after trying to deauth.
2258 */
2259 lbs_mac_event_disconnected(priv);
2260
2261 lbs_deb_leave(LBS_DEB_JOIN);
2262 return ret;
2263}
2264
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
deleted file mode 100644
index 40621b789fc5..000000000000
--- a/drivers/net/wireless/libertas/assoc.h
+++ /dev/null
@@ -1,155 +0,0 @@
1/* Copyright (C) 2006, Red Hat, Inc. */
2
3#ifndef _LBS_ASSOC_H_
4#define _LBS_ASSOC_H_
5
6
7#include "defs.h"
8#include "host.h"
9
10
11struct lbs_private;
12
13/*
14 * In theory, the IE is limited to the IE length, 255,
15 * but in practice 64 bytes are enough.
16 */
17#define MAX_WPA_IE_LEN 64
18
19
20
21struct lbs_802_11_security {
22 u8 WPAenabled;
23 u8 WPA2enabled;
24 u8 wep_enabled;
25 u8 auth_mode;
26 u32 key_mgmt;
27};
28
29/** Current Basic Service Set State Structure */
30struct current_bss_params {
31 /** bssid */
32 u8 bssid[ETH_ALEN];
33 /** ssid */
34 u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
35 u8 ssid_len;
36
37 /** band */
38 u8 band;
39 /** channel is directly in priv->channel */
40 /** zero-terminated array of supported data rates */
41 u8 rates[MAX_RATES + 1];
42};
43
44/**
45 * @brief Structure used to store information for each beacon/probe response
46 */
47struct bss_descriptor {
48 u8 bssid[ETH_ALEN];
49
50 u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
51 u8 ssid_len;
52
53 u16 capability;
54 u32 rssi;
55 u32 channel;
56 u16 beaconperiod;
57 __le16 atimwindow;
58
59 /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
60 u8 mode;
61
62 /* zero-terminated array of supported data rates */
63 u8 rates[MAX_RATES + 1];
64
65 unsigned long last_scanned;
66
67 union ieee_phy_param_set phy;
68 union ieee_ss_param_set ss;
69
70 u8 wpa_ie[MAX_WPA_IE_LEN];
71 size_t wpa_ie_len;
72 u8 rsn_ie[MAX_WPA_IE_LEN];
73 size_t rsn_ie_len;
74
75 u8 mesh;
76
77 struct list_head list;
78};
79
80/** Association request
81 *
82 * Encapsulates all the options that describe a specific assocation request
83 * or configuration of the wireless card's radio, mode, and security settings.
84 */
85struct assoc_request {
86#define ASSOC_FLAG_SSID 1
87#define ASSOC_FLAG_CHANNEL 2
88#define ASSOC_FLAG_BAND 3
89#define ASSOC_FLAG_MODE 4
90#define ASSOC_FLAG_BSSID 5
91#define ASSOC_FLAG_WEP_KEYS 6
92#define ASSOC_FLAG_WEP_TX_KEYIDX 7
93#define ASSOC_FLAG_WPA_MCAST_KEY 8
94#define ASSOC_FLAG_WPA_UCAST_KEY 9
95#define ASSOC_FLAG_SECINFO 10
96#define ASSOC_FLAG_WPA_IE 11
97 unsigned long flags;
98
99 u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
100 u8 ssid_len;
101 u8 channel;
102 u8 band;
103 u8 mode;
104 u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
105
106 /** WEP keys */
107 struct enc_key wep_keys[4];
108 u16 wep_tx_keyidx;
109
110 /** WPA keys */
111 struct enc_key wpa_mcast_key;
112 struct enc_key wpa_unicast_key;
113
114 struct lbs_802_11_security secinfo;
115
116 /** WPA Information Elements*/
117 u8 wpa_ie[MAX_WPA_IE_LEN];
118 u8 wpa_ie_len;
119
120 /* BSS to associate with for infrastructure of Ad-Hoc join */
121 struct bss_descriptor bss;
122};
123
124
125extern u8 lbs_bg_rates[MAX_RATES];
126
127void lbs_association_worker(struct work_struct *work);
128struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
129
130int lbs_adhoc_stop(struct lbs_private *priv);
131
132int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
133 u8 bssid[ETH_ALEN], u16 reason);
134
135int lbs_cmd_802_11_rssi(struct lbs_private *priv,
136 struct cmd_ds_command *cmd);
137int lbs_ret_802_11_rssi(struct lbs_private *priv,
138 struct cmd_ds_command *resp);
139
140int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
141 struct cmd_ds_command *cmd,
142 u16 cmd_action);
143int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
144 struct cmd_ds_command *resp);
145
146int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
147 struct assoc_request *assoc);
148
149int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
150 uint16_t *enable);
151
152int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
153 struct assoc_request *assoc);
154
155#endif /* _LBS_ASSOC_H */
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 9d5d3ccf08c8..f36cc970ad1b 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -7,8 +7,12 @@
7 */ 7 */
8 8
9#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/if_arp.h>
11#include <linux/ieee80211.h>
10#include <net/cfg80211.h> 12#include <net/cfg80211.h>
13#include <asm/unaligned.h>
11 14
15#include "decl.h"
12#include "cfg.h" 16#include "cfg.h"
13#include "cmd.h" 17#include "cmd.h"
14 18
@@ -39,26 +43,27 @@ static struct ieee80211_channel lbs_2ghz_channels[] = {
39 CHAN2G(14, 2484, 0), 43 CHAN2G(14, 2484, 0),
40}; 44};
41 45
42#define RATETAB_ENT(_rate, _rateid, _flags) { \ 46#define RATETAB_ENT(_rate, _hw_value, _flags) { \
43 .bitrate = (_rate), \ 47 .bitrate = (_rate), \
44 .hw_value = (_rateid), \ 48 .hw_value = (_hw_value), \
45 .flags = (_flags), \ 49 .flags = (_flags), \
46} 50}
47 51
48 52
53/* Table 6 in section 3.2.1.1 */
49static struct ieee80211_rate lbs_rates[] = { 54static struct ieee80211_rate lbs_rates[] = {
50 RATETAB_ENT(10, 0x1, 0), 55 RATETAB_ENT(10, 0, 0),
51 RATETAB_ENT(20, 0x2, 0), 56 RATETAB_ENT(20, 1, 0),
52 RATETAB_ENT(55, 0x4, 0), 57 RATETAB_ENT(55, 2, 0),
53 RATETAB_ENT(110, 0x8, 0), 58 RATETAB_ENT(110, 3, 0),
54 RATETAB_ENT(60, 0x10, 0), 59 RATETAB_ENT(60, 9, 0),
55 RATETAB_ENT(90, 0x20, 0), 60 RATETAB_ENT(90, 6, 0),
56 RATETAB_ENT(120, 0x40, 0), 61 RATETAB_ENT(120, 7, 0),
57 RATETAB_ENT(180, 0x80, 0), 62 RATETAB_ENT(180, 8, 0),
58 RATETAB_ENT(240, 0x100, 0), 63 RATETAB_ENT(240, 9, 0),
59 RATETAB_ENT(360, 0x200, 0), 64 RATETAB_ENT(360, 10, 0),
60 RATETAB_ENT(480, 0x400, 0), 65 RATETAB_ENT(480, 11, 0),
61 RATETAB_ENT(540, 0x800, 0), 66 RATETAB_ENT(540, 12, 0),
62}; 67};
63 68
64static struct ieee80211_supported_band lbs_band_2ghz = { 69static struct ieee80211_supported_band lbs_band_2ghz = {
@@ -76,22 +81,639 @@ static const u32 cipher_suites[] = {
76 WLAN_CIPHER_SUITE_CCMP, 81 WLAN_CIPHER_SUITE_CCMP,
77}; 82};
78 83
84/* Time to stay on the channel */
85#define LBS_DWELL_PASSIVE 100
86#define LBS_DWELL_ACTIVE 40
79 87
80 88
89/***************************************************************************
90 * Misc utility functions
91 *
92 * TLVs are Marvell specific. They are very similar to IEs, they have the
93 * same structure: type, length, data*. The only difference: for IEs, the
94 * type and length are u8, but for TLVs they're __le16.
95 */
96
97/*
98 * Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1
99 * in the firmware spec
100 */
101static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type)
102{
103 int ret = -ENOTSUPP;
104
105 switch (auth_type) {
106 case NL80211_AUTHTYPE_OPEN_SYSTEM:
107 case NL80211_AUTHTYPE_SHARED_KEY:
108 ret = auth_type;
109 break;
110 case NL80211_AUTHTYPE_AUTOMATIC:
111 ret = NL80211_AUTHTYPE_OPEN_SYSTEM;
112 break;
113 case NL80211_AUTHTYPE_NETWORK_EAP:
114 ret = 0x80;
115 break;
116 default:
117 /* silence compiler */
118 break;
119 }
120 return ret;
121}
122
123
124/* Various firmware commands need the list of supported rates, but with
125 the hight-bit set for basic rates */
126static int lbs_add_rates(u8 *rates)
127{
128 size_t i;
129
130 for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) {
131 u8 rate = lbs_rates[i].bitrate / 5;
132 if (rate == 0x02 || rate == 0x04 ||
133 rate == 0x0b || rate == 0x16)
134 rate |= 0x80;
135 rates[i] = rate;
136 }
137 return ARRAY_SIZE(lbs_rates);
138}
139
140
141/***************************************************************************
142 * TLV utility functions
143 *
144 * TLVs are Marvell specific. They are very similar to IEs, they have the
145 * same structure: type, length, data*. The only difference: for IEs, the
146 * type and length are u8, but for TLVs they're __le16.
147 */
148
149
150/*
151 * Add ssid TLV
152 */
153#define LBS_MAX_SSID_TLV_SIZE \
154 (sizeof(struct mrvl_ie_header) \
155 + IEEE80211_MAX_SSID_LEN)
156
157static int lbs_add_ssid_tlv(u8 *tlv, const u8 *ssid, int ssid_len)
158{
159 struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv;
160
161 /*
162 * TLV-ID SSID 00 00
163 * length 06 00
164 * ssid 4d 4e 54 45 53 54
165 */
166 ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
167 ssid_tlv->header.len = cpu_to_le16(ssid_len);
168 memcpy(ssid_tlv->ssid, ssid, ssid_len);
169 return sizeof(ssid_tlv->header) + ssid_len;
170}
171
172
173/*
174 * Add channel list TLV (section 8.4.2)
175 *
176 * Actual channel data comes from priv->wdev->wiphy->channels.
177 */
178#define LBS_MAX_CHANNEL_LIST_TLV_SIZE \
179 (sizeof(struct mrvl_ie_header) \
180 + (LBS_SCAN_BEFORE_NAP * sizeof(struct chanscanparamset)))
181
182static int lbs_add_channel_list_tlv(struct lbs_private *priv, u8 *tlv,
183 int last_channel, int active_scan)
184{
185 int chanscanparamsize = sizeof(struct chanscanparamset) *
186 (last_channel - priv->scan_channel);
187
188 struct mrvl_ie_header *header = (void *) tlv;
189
190 /*
191 * TLV-ID CHANLIST 01 01
192 * length 0e 00
193 * channel 00 01 00 00 00 64 00
194 * radio type 00
195 * channel 01
196 * scan type 00
197 * min scan time 00 00
198 * max scan time 64 00
199 * channel 2 00 02 00 00 00 64 00
200 *
201 */
202
203 header->type = cpu_to_le16(TLV_TYPE_CHANLIST);
204 header->len = cpu_to_le16(chanscanparamsize);
205 tlv += sizeof(struct mrvl_ie_header);
206
207 /* lbs_deb_scan("scan: channels %d to %d\n", priv->scan_channel,
208 last_channel); */
209 memset(tlv, 0, chanscanparamsize);
210
211 while (priv->scan_channel < last_channel) {
212 struct chanscanparamset *param = (void *) tlv;
213
214 param->radiotype = CMD_SCAN_RADIO_TYPE_BG;
215 param->channumber =
216 priv->scan_req->channels[priv->scan_channel]->hw_value;
217 if (active_scan) {
218 param->maxscantime = cpu_to_le16(LBS_DWELL_ACTIVE);
219 } else {
220 param->chanscanmode.passivescan = 1;
221 param->maxscantime = cpu_to_le16(LBS_DWELL_PASSIVE);
222 }
223 tlv += sizeof(struct chanscanparamset);
224 priv->scan_channel++;
225 }
226 return sizeof(struct mrvl_ie_header) + chanscanparamsize;
227}
228
229
230/*
231 * Add rates TLV
232 *
233 * The rates are in lbs_bg_rates[], but for the 802.11b
234 * rates the high bit is set. We add this TLV only because
235 * there's a firmware which otherwise doesn't report all
236 * APs in range.
237 */
238#define LBS_MAX_RATES_TLV_SIZE \
239 (sizeof(struct mrvl_ie_header) \
240 + (ARRAY_SIZE(lbs_rates)))
241
242/* Adds a TLV with all rates the hardware supports */
243static int lbs_add_supported_rates_tlv(u8 *tlv)
244{
245 size_t i;
246 struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
247
248 /*
249 * TLV-ID RATES 01 00
250 * length 0e 00
251 * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c
252 */
253 rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
254 tlv += sizeof(rate_tlv->header);
255 i = lbs_add_rates(tlv);
256 tlv += i;
257 rate_tlv->header.len = cpu_to_le16(i);
258 return sizeof(rate_tlv->header) + i;
259}
260
261
262/*
263 * Adds a TLV with all rates the hardware *and* BSS supports.
264 */
265static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss)
266{
267 struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
268 const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
269 int n;
270
271 /*
272 * 01 00 TLV_TYPE_RATES
273 * 04 00 len
274 * 82 84 8b 96 rates
275 */
276 rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
277 tlv += sizeof(rate_tlv->header);
278
279 if (!rates_eid) {
280 /* Fallback: add basic 802.11b rates */
281 *tlv++ = 0x82;
282 *tlv++ = 0x84;
283 *tlv++ = 0x8b;
284 *tlv++ = 0x96;
285 n = 4;
286 } else {
287 int hw, ap;
288 u8 ap_max = rates_eid[1];
289 n = 0;
290 for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) {
291 u8 hw_rate = lbs_rates[hw].bitrate / 5;
292 for (ap = 0; ap < ap_max; ap++) {
293 if (hw_rate == (rates_eid[ap+2] & 0x7f)) {
294 *tlv++ = rates_eid[ap+2];
295 n++;
296 }
297 }
298 }
299 }
300
301 rate_tlv->header.len = cpu_to_le16(n);
302 return sizeof(rate_tlv->header) + n;
303}
304
305
306/*
307 * Add auth type TLV.
308 *
309 * This is only needed for newer firmware (V9 and up).
310 */
311#define LBS_MAX_AUTH_TYPE_TLV_SIZE \
312 sizeof(struct mrvl_ie_auth_type)
313
314static int lbs_add_auth_type_tlv(u8 *tlv, enum nl80211_auth_type auth_type)
315{
316 struct mrvl_ie_auth_type *auth = (void *) tlv;
317
318 /*
319 * 1f 01 TLV_TYPE_AUTH_TYPE
320 * 01 00 len
321 * 01 auth type
322 */
323 auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
324 auth->header.len = cpu_to_le16(sizeof(*auth)-sizeof(auth->header));
325 auth->auth = cpu_to_le16(lbs_auth_to_authtype(auth_type));
326 return sizeof(*auth);
327}
328
329
330/*
331 * Add channel (phy ds) TLV
332 */
333#define LBS_MAX_CHANNEL_TLV_SIZE \
334 sizeof(struct mrvl_ie_header)
335
336static int lbs_add_channel_tlv(u8 *tlv, u8 channel)
337{
338 struct mrvl_ie_ds_param_set *ds = (void *) tlv;
339
340 /*
341 * 03 00 TLV_TYPE_PHY_DS
342 * 01 00 len
343 * 06 channel
344 */
345 ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
346 ds->header.len = cpu_to_le16(sizeof(*ds)-sizeof(ds->header));
347 ds->channel = channel;
348 return sizeof(*ds);
349}
350
351
352/*
353 * Add (empty) CF param TLV of the form:
354 */
355#define LBS_MAX_CF_PARAM_TLV_SIZE \
356 sizeof(struct mrvl_ie_header)
357
358static int lbs_add_cf_param_tlv(u8 *tlv)
359{
360 struct mrvl_ie_cf_param_set *cf = (void *)tlv;
361
362 /*
363 * 04 00 TLV_TYPE_CF
364 * 06 00 len
365 * 00 cfpcnt
366 * 00 cfpperiod
367 * 00 00 cfpmaxduration
368 * 00 00 cfpdurationremaining
369 */
370 cf->header.type = cpu_to_le16(TLV_TYPE_CF);
371 cf->header.len = cpu_to_le16(sizeof(*cf)-sizeof(cf->header));
372 return sizeof(*cf);
373}
374
375/*
376 * Add WPA TLV
377 */
378#define LBS_MAX_WPA_TLV_SIZE \
379 (sizeof(struct mrvl_ie_header) \
380 + 128 /* TODO: I guessed the size */)
381
382static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len)
383{
384 size_t tlv_len;
385
386 /*
387 * We need just convert an IE to an TLV. IEs use u8 for the header,
388 * u8 type
389 * u8 len
390 * u8[] data
391 * but TLVs use __le16 instead:
392 * __le16 type
393 * __le16 len
394 * u8[] data
395 */
396 *tlv++ = *ie++;
397 *tlv++ = 0;
398 tlv_len = *tlv++ = *ie++;
399 *tlv++ = 0;
400 while (tlv_len--)
401 *tlv++ = *ie++;
402 /* the TLV is two bytes larger than the IE */
403 return ie_len + 2;
404}
405
406/***************************************************************************
407 * Set Channel
408 */
409
81static int lbs_cfg_set_channel(struct wiphy *wiphy, 410static int lbs_cfg_set_channel(struct wiphy *wiphy,
82 struct net_device *netdev, 411 struct net_device *netdev,
83 struct ieee80211_channel *chan, 412 struct ieee80211_channel *channel,
84 enum nl80211_channel_type channel_type) 413 enum nl80211_channel_type channel_type)
85{ 414{
86 struct lbs_private *priv = wiphy_priv(wiphy); 415 struct lbs_private *priv = wiphy_priv(wiphy);
87 int ret = -ENOTSUPP; 416 int ret = -ENOTSUPP;
88 417
89 lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type); 418 lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
419 channel->center_freq, channel_type);
90 420
91 if (channel_type != NL80211_CHAN_NO_HT) 421 if (channel_type != NL80211_CHAN_NO_HT)
92 goto out; 422 goto out;
93 423
94 ret = lbs_set_channel(priv, chan->hw_value); 424 ret = lbs_set_channel(priv, channel->hw_value);
425
426 out:
427 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
428 return ret;
429}
430
431
432
433/***************************************************************************
434 * Scanning
435 */
436
437/*
438 * When scanning, the firmware doesn't send a nul packet with the power-safe
439 * bit to the AP. So we cannot stay away from our current channel too long,
440 * otherwise we loose data. So take a "nap" while scanning every other
441 * while.
442 */
443#define LBS_SCAN_BEFORE_NAP 4
444
445
446/*
447 * When the firmware reports back a scan-result, it gives us an "u8 rssi",
448 * which isn't really an RSSI, as it becomes larger when moving away from
449 * the AP. Anyway, we need to convert that into mBm.
450 */
451#define LBS_SCAN_RSSI_TO_MBM(rssi) \
452 ((-(int)rssi + 3)*100)
453
454static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
455 struct cmd_header *resp)
456{
457 struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
458 int bsssize;
459 const u8 *pos;
460 u16 nr_sets;
461 const u8 *tsfdesc;
462 int tsfsize;
463 int i;
464 int ret = -EILSEQ;
465
466 lbs_deb_enter(LBS_DEB_CFG80211);
467
468 bsssize = get_unaligned_le16(&scanresp->bssdescriptsize);
469 nr_sets = le16_to_cpu(resp->size);
470
471 /*
472 * The general layout of the scan response is described in chapter
473 * 5.7.1. Basically we have a common part, then any number of BSS
474 * descriptor sections. Finally we have section with the same number
475 * of TSFs.
476 *
477 * cmd_ds_802_11_scan_rsp
478 * cmd_header
479 * pos_size
480 * nr_sets
481 * bssdesc 1
482 * bssid
483 * rssi
484 * timestamp
485 * intvl
486 * capa
487 * IEs
488 * bssdesc 2
489 * bssdesc n
490 * MrvlIEtypes_TsfFimestamp_t
491 * TSF for BSS 1
492 * TSF for BSS 2
493 * TSF for BSS n
494 */
495
496 pos = scanresp->bssdesc_and_tlvbuffer;
497
498 tsfdesc = pos + bsssize;
499 tsfsize = 4 + 8 * scanresp->nr_sets;
500
501 /* Validity check: we expect a Marvell-Local TLV */
502 i = get_unaligned_le16(tsfdesc);
503 tsfdesc += 2;
504 if (i != TLV_TYPE_TSFTIMESTAMP)
505 goto done;
506 /* Validity check: the TLV holds TSF values with 8 bytes each, so
507 * the size in the TLV must match the nr_sets value */
508 i = get_unaligned_le16(tsfdesc);
509 tsfdesc += 2;
510 if (i / 8 != scanresp->nr_sets)
511 goto done;
512
513 for (i = 0; i < scanresp->nr_sets; i++) {
514 const u8 *bssid;
515 const u8 *ie;
516 int left;
517 int ielen;
518 int rssi;
519 u16 intvl;
520 u16 capa;
521 int chan_no = -1;
522 const u8 *ssid = NULL;
523 u8 ssid_len = 0;
524 DECLARE_SSID_BUF(ssid_buf);
525
526 int len = get_unaligned_le16(pos);
527 pos += 2;
528
529 /* BSSID */
530 bssid = pos;
531 pos += ETH_ALEN;
532 /* RSSI */
533 rssi = *pos++;
534 /* Packet time stamp */
535 pos += 8;
536 /* Beacon interval */
537 intvl = get_unaligned_le16(pos);
538 pos += 2;
539 /* Capabilities */
540 capa = get_unaligned_le16(pos);
541 pos += 2;
542
543 /* To find out the channel, we must parse the IEs */
544 ie = pos;
545 /* 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon
546 interval, capabilities */
547 ielen = left = len - (6 + 1 + 8 + 2 + 2);
548 while (left >= 2) {
549 u8 id, elen;
550 id = *pos++;
551 elen = *pos++;
552 left -= 2;
553 if (elen > left || elen == 0)
554 goto done;
555 if (id == WLAN_EID_DS_PARAMS)
556 chan_no = *pos;
557 if (id == WLAN_EID_SSID) {
558 ssid = pos;
559 ssid_len = elen;
560 }
561 left -= elen;
562 pos += elen;
563 }
564
565 /* No channel, no luck */
566 if (chan_no != -1) {
567 struct wiphy *wiphy = priv->wdev->wiphy;
568 int freq = ieee80211_channel_to_frequency(chan_no);
569 struct ieee80211_channel *channel =
570 ieee80211_get_channel(wiphy, freq);
571
572 lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, "
573 "%d dBm\n",
574 bssid, capa, chan_no,
575 print_ssid(ssid_buf, ssid, ssid_len),
576 LBS_SCAN_RSSI_TO_MBM(rssi)/100);
577
578 if (channel ||
579 !(channel->flags & IEEE80211_CHAN_DISABLED))
580 cfg80211_inform_bss(wiphy, channel,
581 bssid, le64_to_cpu(*(__le64 *)tsfdesc),
582 capa, intvl, ie, ielen,
583 LBS_SCAN_RSSI_TO_MBM(rssi),
584 GFP_KERNEL);
585 }
586 tsfdesc += 8;
587 }
588 ret = 0;
589
590 done:
591 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
592 return ret;
593}
594
595
596/*
597 * Our scan command contains a TLV, consting of a SSID TLV, a channel list
598 * TLV and a rates TLV. Determine the maximum size of them:
599 */
600#define LBS_SCAN_MAX_CMD_SIZE \
601 (sizeof(struct cmd_ds_802_11_scan) \
602 + LBS_MAX_SSID_TLV_SIZE \
603 + LBS_MAX_CHANNEL_LIST_TLV_SIZE \
604 + LBS_MAX_RATES_TLV_SIZE)
605
606/*
607 * Assumes priv->scan_req is initialized and valid
608 * Assumes priv->scan_channel is initialized
609 */
610static void lbs_scan_worker(struct work_struct *work)
611{
612 struct lbs_private *priv =
613 container_of(work, struct lbs_private, scan_work.work);
614 struct cmd_ds_802_11_scan *scan_cmd;
615 u8 *tlv; /* pointer into our current, growing TLV storage area */
616 int last_channel;
617 int running, carrier;
618
619 lbs_deb_enter(LBS_DEB_SCAN);
620
621 scan_cmd = kzalloc(LBS_SCAN_MAX_CMD_SIZE, GFP_KERNEL);
622 if (scan_cmd == NULL)
623 goto out_no_scan_cmd;
624
625 /* prepare fixed part of scan command */
626 scan_cmd->bsstype = CMD_BSS_TYPE_ANY;
627
628 /* stop network while we're away from our main channel */
629 running = !netif_queue_stopped(priv->dev);
630 carrier = netif_carrier_ok(priv->dev);
631 if (running)
632 netif_stop_queue(priv->dev);
633 if (carrier)
634 netif_carrier_off(priv->dev);
635
636 /* prepare fixed part of scan command */
637 tlv = scan_cmd->tlvbuffer;
638
639 /* add SSID TLV */
640 if (priv->scan_req->n_ssids)
641 tlv += lbs_add_ssid_tlv(tlv,
642 priv->scan_req->ssids[0].ssid,
643 priv->scan_req->ssids[0].ssid_len);
644
645 /* add channel TLVs */
646 last_channel = priv->scan_channel + LBS_SCAN_BEFORE_NAP;
647 if (last_channel > priv->scan_req->n_channels)
648 last_channel = priv->scan_req->n_channels;
649 tlv += lbs_add_channel_list_tlv(priv, tlv, last_channel,
650 priv->scan_req->n_ssids);
651
652 /* add rates TLV */
653 tlv += lbs_add_supported_rates_tlv(tlv);
654
655 if (priv->scan_channel < priv->scan_req->n_channels) {
656 cancel_delayed_work(&priv->scan_work);
657 queue_delayed_work(priv->work_thread, &priv->scan_work,
658 msecs_to_jiffies(300));
659 }
660
661 /* This is the final data we are about to send */
662 scan_cmd->hdr.size = cpu_to_le16(tlv - (u8 *)scan_cmd);
663 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
664 sizeof(*scan_cmd));
665 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
666 tlv - scan_cmd->tlvbuffer);
667
668 __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
669 le16_to_cpu(scan_cmd->hdr.size),
670 lbs_ret_scan, 0);
671
672 if (priv->scan_channel >= priv->scan_req->n_channels) {
673 /* Mark scan done */
674 cfg80211_scan_done(priv->scan_req, false);
675 priv->scan_req = NULL;
676 }
677
678 /* Restart network */
679 if (carrier)
680 netif_carrier_on(priv->dev);
681 if (running && !priv->tx_pending_len)
682 netif_wake_queue(priv->dev);
683
684 kfree(scan_cmd);
685
686 out_no_scan_cmd:
687 lbs_deb_leave(LBS_DEB_SCAN);
688}
689
690
691static int lbs_cfg_scan(struct wiphy *wiphy,
692 struct net_device *dev,
693 struct cfg80211_scan_request *request)
694{
695 struct lbs_private *priv = wiphy_priv(wiphy);
696 int ret = 0;
697
698 lbs_deb_enter(LBS_DEB_CFG80211);
699
700 if (priv->scan_req || delayed_work_pending(&priv->scan_work)) {
701 /* old scan request not yet processed */
702 ret = -EAGAIN;
703 goto out;
704 }
705
706 lbs_deb_scan("scan: ssids %d, channels %d, ie_len %zd\n",
707 request->n_ssids, request->n_channels, request->ie_len);
708
709 priv->scan_channel = 0;
710 queue_delayed_work(priv->work_thread, &priv->scan_work,
711 msecs_to_jiffies(50));
712
713 if (priv->surpriseremoved)
714 ret = -EIO;
715
716 priv->scan_req = request;
95 717
96 out: 718 out:
97 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); 719 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -101,8 +723,1228 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy,
101 723
102 724
103 725
726/***************************************************************************
727 * Events
728 */
729
730void lbs_send_disconnect_notification(struct lbs_private *priv)
731{
732 lbs_deb_enter(LBS_DEB_CFG80211);
733
734 cfg80211_disconnected(priv->dev,
735 0,
736 NULL, 0,
737 GFP_KERNEL);
738
739 lbs_deb_leave(LBS_DEB_CFG80211);
740}
741
742void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
743{
744 lbs_deb_enter(LBS_DEB_CFG80211);
745
746 cfg80211_michael_mic_failure(priv->dev,
747 priv->assoc_bss,
748 event == MACREG_INT_CODE_MIC_ERR_MULTICAST ?
749 NL80211_KEYTYPE_GROUP :
750 NL80211_KEYTYPE_PAIRWISE,
751 -1,
752 NULL,
753 GFP_KERNEL);
754
755 lbs_deb_leave(LBS_DEB_CFG80211);
756}
757
758
759
760
761/***************************************************************************
762 * Connect/disconnect
763 */
764
765
766/*
767 * This removes all WEP keys
768 */
769static int lbs_remove_wep_keys(struct lbs_private *priv)
770{
771 struct cmd_ds_802_11_set_wep cmd;
772 int ret;
773
774 lbs_deb_enter(LBS_DEB_CFG80211);
775
776 memset(&cmd, 0, sizeof(cmd));
777 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
778 cmd.keyindex = cpu_to_le16(priv->wep_tx_key);
779 cmd.action = cpu_to_le16(CMD_ACT_REMOVE);
780
781 ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
782
783 lbs_deb_leave(LBS_DEB_CFG80211);
784 return ret;
785}
786
787/*
788 * Set WEP keys
789 */
790static int lbs_set_wep_keys(struct lbs_private *priv)
791{
792 struct cmd_ds_802_11_set_wep cmd;
793 int i;
794 int ret;
795
796 lbs_deb_enter(LBS_DEB_CFG80211);
797
798 /*
799 * command 13 00
800 * size 50 00
801 * sequence xx xx
802 * result 00 00
803 * action 02 00 ACT_ADD
804 * transmit key 00 00
805 * type for key 1 01 WEP40
806 * type for key 2 00
807 * type for key 3 00
808 * type for key 4 00
809 * key 1 39 39 39 39 39 00 00 00
810 * 00 00 00 00 00 00 00 00
811 * key 2 00 00 00 00 00 00 00 00
812 * 00 00 00 00 00 00 00 00
813 * key 3 00 00 00 00 00 00 00 00
814 * 00 00 00 00 00 00 00 00
815 * key 4 00 00 00 00 00 00 00 00
816 */
817 if (priv->wep_key_len[0] || priv->wep_key_len[1] ||
818 priv->wep_key_len[2] || priv->wep_key_len[3]) {
819 /* Only set wep keys if we have at least one of them */
820 memset(&cmd, 0, sizeof(cmd));
821 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
822 cmd.keyindex = cpu_to_le16(priv->wep_tx_key);
823 cmd.action = cpu_to_le16(CMD_ACT_ADD);
824
825 for (i = 0; i < 4; i++) {
826 switch (priv->wep_key_len[i]) {
827 case WLAN_KEY_LEN_WEP40:
828 cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
829 break;
830 case WLAN_KEY_LEN_WEP104:
831 cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
832 break;
833 default:
834 cmd.keytype[i] = 0;
835 break;
836 }
837 memcpy(cmd.keymaterial[i], priv->wep_key[i],
838 priv->wep_key_len[i]);
839 }
840
841 ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
842 } else {
843 /* Otherwise remove all wep keys */
844 ret = lbs_remove_wep_keys(priv);
845 }
846
847 lbs_deb_leave(LBS_DEB_CFG80211);
848 return ret;
849}
850
851
852/*
853 * Enable/Disable RSN status
854 */
855static int lbs_enable_rsn(struct lbs_private *priv, int enable)
856{
857 struct cmd_ds_802_11_enable_rsn cmd;
858 int ret;
859
860 lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", enable);
861
862 /*
863 * cmd 2f 00
864 * size 0c 00
865 * sequence xx xx
866 * result 00 00
867 * action 01 00 ACT_SET
868 * enable 01 00
869 */
870 memset(&cmd, 0, sizeof(cmd));
871 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
872 cmd.action = cpu_to_le16(CMD_ACT_SET);
873 cmd.enable = cpu_to_le16(enable);
874
875 ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
876
877 lbs_deb_leave(LBS_DEB_CFG80211);
878 return ret;
879}
880
881
882/*
883 * Set WPA/WPA key material
884 */
885
886/* like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we
887 * get rid of WEXT, this should go into host.h */
888
889struct cmd_key_material {
890 struct cmd_header hdr;
891
892 __le16 action;
893 struct MrvlIEtype_keyParamSet param;
894} __attribute__ ((packed));
895
896static int lbs_set_key_material(struct lbs_private *priv,
897 int key_type,
898 int key_info,
899 u8 *key, u16 key_len)
900{
901 struct cmd_key_material cmd;
902 int ret;
903
904 lbs_deb_enter(LBS_DEB_CFG80211);
905
906 /*
907 * Example for WPA (TKIP):
908 *
909 * cmd 5e 00
910 * size 34 00
911 * sequence xx xx
912 * result 00 00
913 * action 01 00
914 * TLV type 00 01 key param
915 * length 00 26
916 * key type 01 00 TKIP
917 * key info 06 00 UNICAST | ENABLED
918 * key len 20 00
919 * key 32 bytes
920 */
921 memset(&cmd, 0, sizeof(cmd));
922 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
923 cmd.action = cpu_to_le16(CMD_ACT_SET);
924 cmd.param.type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
925 cmd.param.length = cpu_to_le16(sizeof(cmd.param) - 4);
926 cmd.param.keytypeid = cpu_to_le16(key_type);
927 cmd.param.keyinfo = cpu_to_le16(key_info);
928 cmd.param.keylen = cpu_to_le16(key_len);
929 if (key && key_len)
930 memcpy(cmd.param.key, key, key_len);
931
932 ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
933
934 lbs_deb_leave(LBS_DEB_CFG80211);
935 return ret;
936}
937
938
939/*
940 * Sets the auth type (open, shared, etc) in the firmware. That
941 * we use CMD_802_11_AUTHENTICATE is misleading, this firmware
942 * command doesn't send an authentication frame at all, it just
943 * stores the auth_type.
944 */
945static int lbs_set_authtype(struct lbs_private *priv,
946 struct cfg80211_connect_params *sme)
947{
948 struct cmd_ds_802_11_authenticate cmd;
949 int ret;
950
951 lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", sme->auth_type);
952
953 /*
954 * cmd 11 00
955 * size 19 00
956 * sequence xx xx
957 * result 00 00
958 * BSS id 00 13 19 80 da 30
959 * auth type 00
960 * reserved 00 00 00 00 00 00 00 00 00 00
961 */
962 memset(&cmd, 0, sizeof(cmd));
963 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
964 if (sme->bssid)
965 memcpy(cmd.bssid, sme->bssid, ETH_ALEN);
966 /* convert auth_type */
967 ret = lbs_auth_to_authtype(sme->auth_type);
968 if (ret < 0)
969 goto done;
970
971 cmd.authtype = ret;
972 ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
973
974 done:
975 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
976 return ret;
977}
978
979
980/*
981 * Create association request
982 */
983#define LBS_ASSOC_MAX_CMD_SIZE \
984 (sizeof(struct cmd_ds_802_11_associate) \
985 - 512 /* cmd_ds_802_11_associate.iebuf */ \
986 + LBS_MAX_SSID_TLV_SIZE \
987 + LBS_MAX_CHANNEL_TLV_SIZE \
988 + LBS_MAX_CF_PARAM_TLV_SIZE \
989 + LBS_MAX_AUTH_TYPE_TLV_SIZE \
990 + LBS_MAX_WPA_TLV_SIZE)
991
992static int lbs_associate(struct lbs_private *priv,
993 struct cfg80211_bss *bss,
994 struct cfg80211_connect_params *sme)
995{
996 struct cmd_ds_802_11_associate_response *resp;
997 struct cmd_ds_802_11_associate *cmd = kzalloc(LBS_ASSOC_MAX_CMD_SIZE,
998 GFP_KERNEL);
999 const u8 *ssid_eid;
1000 size_t len, resp_ie_len;
1001 int status;
1002 int ret;
1003 u8 *pos = &(cmd->iebuf[0]);
1004
1005 lbs_deb_enter(LBS_DEB_CFG80211);
1006
1007 if (!cmd) {
1008 ret = -ENOMEM;
1009 goto done;
1010 }
1011
1012 /*
1013 * cmd 50 00
1014 * length 34 00
1015 * sequence xx xx
1016 * result 00 00
1017 * BSS id 00 13 19 80 da 30
1018 * capabilities 11 00
1019 * listen interval 0a 00
1020 * beacon interval 00 00
1021 * DTIM period 00
1022 * TLVs xx (up to 512 bytes)
1023 */
1024 cmd->hdr.command = cpu_to_le16(CMD_802_11_ASSOCIATE);
1025
1026 /* Fill in static fields */
1027 memcpy(cmd->bssid, bss->bssid, ETH_ALEN);
1028 cmd->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
1029 cmd->capability = cpu_to_le16(bss->capability);
1030
1031 /* add SSID TLV */
1032 ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
1033 if (ssid_eid)
1034 pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]);
1035 else
1036 lbs_deb_assoc("no SSID\n");
1037
1038 /* add DS param TLV */
1039 if (bss->channel)
1040 pos += lbs_add_channel_tlv(pos, bss->channel->hw_value);
1041 else
1042 lbs_deb_assoc("no channel\n");
1043
1044 /* add (empty) CF param TLV */
1045 pos += lbs_add_cf_param_tlv(pos);
1046
1047 /* add rates TLV */
1048 pos += lbs_add_common_rates_tlv(pos, bss);
1049
1050 /* add auth type TLV */
1051 if (priv->fwrelease >= 0x09000000)
1052 pos += lbs_add_auth_type_tlv(pos, sme->auth_type);
1053
1054 /* add WPA/WPA2 TLV */
1055 if (sme->ie && sme->ie_len)
1056 pos += lbs_add_wpa_tlv(pos, sme->ie, sme->ie_len);
1057
1058 len = (sizeof(*cmd) - sizeof(cmd->iebuf)) +
1059 (u16)(pos - (u8 *) &cmd->iebuf);
1060 cmd->hdr.size = cpu_to_le16(len);
1061
1062 /* store for later use */
1063 memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN);
1064
1065 ret = lbs_cmd_with_response(priv, CMD_802_11_ASSOCIATE, cmd);
1066 if (ret)
1067 goto done;
1068
1069
1070 /* generate connect message to cfg80211 */
1071
1072 resp = (void *) cmd; /* recast for easier field access */
1073 status = le16_to_cpu(resp->statuscode);
1074
1075 /* Convert statis code of old firmware */
1076 if (priv->fwrelease < 0x09000000)
1077 switch (status) {
1078 case 0:
1079 break;
1080 case 1:
1081 lbs_deb_assoc("invalid association parameters\n");
1082 status = WLAN_STATUS_CAPS_UNSUPPORTED;
1083 break;
1084 case 2:
1085 lbs_deb_assoc("timer expired while waiting for AP\n");
1086 status = WLAN_STATUS_AUTH_TIMEOUT;
1087 break;
1088 case 3:
1089 lbs_deb_assoc("association refused by AP\n");
1090 status = WLAN_STATUS_ASSOC_DENIED_UNSPEC;
1091 break;
1092 case 4:
1093 lbs_deb_assoc("authentication refused by AP\n");
1094 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1095 break;
1096 default:
1097 lbs_deb_assoc("association failure %d\n", status);
1098 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1099 }
1100
1101 lbs_deb_assoc("status %d, capability 0x%04x\n", status,
1102 le16_to_cpu(resp->capability));
1103
1104 resp_ie_len = le16_to_cpu(resp->hdr.size)
1105 - sizeof(resp->hdr)
1106 - 6;
1107 cfg80211_connect_result(priv->dev,
1108 priv->assoc_bss,
1109 sme->ie, sme->ie_len,
1110 resp->iebuf, resp_ie_len,
1111 status,
1112 GFP_KERNEL);
1113
1114 if (status == 0) {
1115 /* TODO: get rid of priv->connect_status */
1116 priv->connect_status = LBS_CONNECTED;
1117 netif_carrier_on(priv->dev);
1118 if (!priv->tx_pending_len)
1119 netif_tx_wake_all_queues(priv->dev);
1120 }
1121
1122
1123done:
1124 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1125 return ret;
1126}
1127
1128
1129
1130static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
1131 struct cfg80211_connect_params *sme)
1132{
1133 struct lbs_private *priv = wiphy_priv(wiphy);
1134 struct cfg80211_bss *bss = NULL;
1135 int ret = 0;
1136 u8 preamble = RADIO_PREAMBLE_SHORT;
1137
1138 lbs_deb_enter(LBS_DEB_CFG80211);
1139
1140 if (sme->bssid) {
1141 bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
1142 sme->ssid, sme->ssid_len,
1143 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
1144 } else {
1145 /*
1146 * Here we have an impedance mismatch. The firmware command
1147 * CMD_802_11_ASSOCIATE always needs a BSSID, it cannot
1148 * connect otherwise. However, for the connect-API of
1149 * cfg80211 the bssid is purely optional. We don't get one,
1150 * except the user specifies one on the "iw" command line.
1151 *
1152 * If we don't got one, we could initiate a scan and look
1153 * for the best matching cfg80211_bss entry.
1154 *
1155 * Or, better yet, net/wireless/sme.c get's rewritten into
1156 * something more generally useful.
1157 */
1158 lbs_pr_err("TODO: no BSS specified\n");
1159 ret = -ENOTSUPP;
1160 goto done;
1161 }
1162
1163
1164 if (!bss) {
1165 lbs_pr_err("assicate: bss %pM not in scan results\n",
1166 sme->bssid);
1167 ret = -ENOENT;
1168 goto done;
1169 }
1170 lbs_deb_assoc("trying %pM", sme->bssid);
1171 lbs_deb_assoc("cipher 0x%x, key index %d, key len %d\n",
1172 sme->crypto.cipher_group,
1173 sme->key_idx, sme->key_len);
1174
1175 /* As this is a new connection, clear locally stored WEP keys */
1176 priv->wep_tx_key = 0;
1177 memset(priv->wep_key, 0, sizeof(priv->wep_key));
1178 memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len));
1179
1180 /* set/remove WEP keys */
1181 switch (sme->crypto.cipher_group) {
1182 case WLAN_CIPHER_SUITE_WEP40:
1183 case WLAN_CIPHER_SUITE_WEP104:
1184 /* Store provided WEP keys in priv-> */
1185 priv->wep_tx_key = sme->key_idx;
1186 priv->wep_key_len[sme->key_idx] = sme->key_len;
1187 memcpy(priv->wep_key[sme->key_idx], sme->key, sme->key_len);
1188 /* Set WEP keys and WEP mode */
1189 lbs_set_wep_keys(priv);
1190 priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
1191 lbs_set_mac_control(priv);
1192 /* No RSN mode for WEP */
1193 lbs_enable_rsn(priv, 0);
1194 break;
1195 case 0: /* there's no WLAN_CIPHER_SUITE_NONE definition */
1196 /*
1197 * If we don't have no WEP, no WPA and no WPA2,
1198 * we remove all keys like in the WPA/WPA2 setup,
1199 * we just don't set RSN.
1200 *
1201 * Therefore: fall-throught
1202 */
1203 case WLAN_CIPHER_SUITE_TKIP:
1204 case WLAN_CIPHER_SUITE_CCMP:
1205 /* Remove WEP keys and WEP mode */
1206 lbs_remove_wep_keys(priv);
1207 priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
1208 lbs_set_mac_control(priv);
1209
1210 /* clear the WPA/WPA2 keys */
1211 lbs_set_key_material(priv,
1212 KEY_TYPE_ID_WEP, /* doesn't matter */
1213 KEY_INFO_WPA_UNICAST,
1214 NULL, 0);
1215 lbs_set_key_material(priv,
1216 KEY_TYPE_ID_WEP, /* doesn't matter */
1217 KEY_INFO_WPA_MCAST,
1218 NULL, 0);
1219 /* RSN mode for WPA/WPA2 */
1220 lbs_enable_rsn(priv, sme->crypto.cipher_group != 0);
1221 break;
1222 default:
1223 lbs_pr_err("unsupported cipher group 0x%x\n",
1224 sme->crypto.cipher_group);
1225 ret = -ENOTSUPP;
1226 goto done;
1227 }
1228
1229 lbs_set_authtype(priv, sme);
1230 lbs_set_radio(priv, preamble, 1);
1231
1232 /* Do the actual association */
1233 lbs_associate(priv, bss, sme);
1234
1235 done:
1236 if (bss)
1237 cfg80211_put_bss(bss);
1238 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1239 return ret;
1240}
1241
1242static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
1243 u16 reason_code)
1244{
1245 struct lbs_private *priv = wiphy_priv(wiphy);
1246 struct cmd_ds_802_11_deauthenticate cmd;
1247
1248 lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
1249
1250 /* store for lbs_cfg_ret_disconnect() */
1251 priv->disassoc_reason = reason_code;
1252
1253 memset(&cmd, 0, sizeof(cmd));
1254 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1255 /* Mildly ugly to use a locally store my own BSSID ... */
1256 memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN);
1257 cmd.reasoncode = cpu_to_le16(reason_code);
1258
1259 if (lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd))
1260 return -EFAULT;
1261
1262 cfg80211_disconnected(priv->dev,
1263 priv->disassoc_reason,
1264 NULL, 0,
1265 GFP_KERNEL);
1266 priv->connect_status = LBS_DISCONNECTED;
1267
1268 return 0;
1269}
1270
1271
1272static int lbs_cfg_set_default_key(struct wiphy *wiphy,
1273 struct net_device *netdev,
1274 u8 key_index)
1275{
1276 struct lbs_private *priv = wiphy_priv(wiphy);
1277
1278 lbs_deb_enter(LBS_DEB_CFG80211);
1279
1280 if (key_index != priv->wep_tx_key) {
1281 lbs_deb_assoc("set_default_key: to %d\n", key_index);
1282 priv->wep_tx_key = key_index;
1283 lbs_set_wep_keys(priv);
1284 }
1285
1286 return 0;
1287}
1288
1289
1290static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
1291 u8 idx, const u8 *mac_addr,
1292 struct key_params *params)
1293{
1294 struct lbs_private *priv = wiphy_priv(wiphy);
1295 u16 key_info;
1296 u16 key_type;
1297 int ret = 0;
1298
1299 lbs_deb_enter(LBS_DEB_CFG80211);
1300
1301 lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
1302 params->cipher, mac_addr);
1303 lbs_deb_assoc("add_key: key index %d, key len %d\n",
1304 idx, params->key_len);
1305 if (params->key_len)
1306 lbs_deb_hex(LBS_DEB_CFG80211, "KEY",
1307 params->key, params->key_len);
1308
1309 lbs_deb_assoc("add_key: seq len %d\n", params->seq_len);
1310 if (params->seq_len)
1311 lbs_deb_hex(LBS_DEB_CFG80211, "SEQ",
1312 params->seq, params->seq_len);
1313
1314 switch (params->cipher) {
1315 case WLAN_CIPHER_SUITE_WEP40:
1316 case WLAN_CIPHER_SUITE_WEP104:
1317 /* actually compare if something has changed ... */
1318 if ((priv->wep_key_len[idx] != params->key_len) ||
1319 memcmp(priv->wep_key[idx],
1320 params->key, params->key_len) != 0) {
1321 priv->wep_key_len[idx] = params->key_len;
1322 memcpy(priv->wep_key[idx],
1323 params->key, params->key_len);
1324 lbs_set_wep_keys(priv);
1325 }
1326 break;
1327 case WLAN_CIPHER_SUITE_TKIP:
1328 case WLAN_CIPHER_SUITE_CCMP:
1329 key_info = KEY_INFO_WPA_ENABLED | ((idx == 0)
1330 ? KEY_INFO_WPA_UNICAST
1331 : KEY_INFO_WPA_MCAST);
1332 key_type = (params->cipher == WLAN_CIPHER_SUITE_TKIP)
1333 ? KEY_TYPE_ID_TKIP
1334 : KEY_TYPE_ID_AES;
1335 lbs_set_key_material(priv,
1336 key_type,
1337 key_info,
1338 params->key, params->key_len);
1339 break;
1340 default:
1341 lbs_pr_err("unhandled cipher 0x%x\n", params->cipher);
1342 ret = -ENOTSUPP;
1343 break;
1344 }
1345
1346 return ret;
1347}
1348
1349
1350static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
1351 u8 key_index, const u8 *mac_addr)
1352{
1353
1354 lbs_deb_enter(LBS_DEB_CFG80211);
1355
1356 lbs_deb_assoc("del_key: key_idx %d, mac_addr %pM\n",
1357 key_index, mac_addr);
1358
1359#ifdef TODO
1360 struct lbs_private *priv = wiphy_priv(wiphy);
1361 /*
1362 * I think can keep this a NO-OP, because:
1363
1364 * - we clear all keys whenever we do lbs_cfg_connect() anyway
1365 * - neither "iw" nor "wpa_supplicant" won't call this during
1366 * an ongoing connection
1367 * - TODO: but I have to check if this is still true when
1368 * I set the AP to periodic re-keying
1369 * - we've not kzallec() something when we've added a key at
1370 * lbs_cfg_connect() or lbs_cfg_add_key().
1371 *
1372 * This causes lbs_cfg_del_key() only called at disconnect time,
1373 * where we'd just waste time deleting a key that is not going
1374 * to be used anyway.
1375 */
1376 if (key_index < 3 && priv->wep_key_len[key_index]) {
1377 priv->wep_key_len[key_index] = 0;
1378 lbs_set_wep_keys(priv);
1379 }
1380#endif
1381
1382 return 0;
1383}
1384
1385
1386
1387/***************************************************************************
1388 * Monitor mode
1389 */
1390
1391/* like "struct cmd_ds_802_11_monitor_mode", but with cmd_header. Once we
1392 * get rid of WEXT, this should go into host.h */
1393struct cmd_monitor_mode {
1394 struct cmd_header hdr;
1395
1396 __le16 action;
1397 __le16 mode;
1398} __attribute__ ((packed));
1399
1400static int lbs_enable_monitor_mode(struct lbs_private *priv, int mode)
1401{
1402 struct cmd_monitor_mode cmd;
1403 int ret;
1404
1405 lbs_deb_enter(LBS_DEB_CFG80211);
1406
1407 /*
1408 * cmd 98 00
1409 * size 0c 00
1410 * sequence xx xx
1411 * result 00 00
1412 * action 01 00 ACT_SET
1413 * enable 01 00
1414 */
1415 memset(&cmd, 0, sizeof(cmd));
1416 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1417 cmd.action = cpu_to_le16(CMD_ACT_SET);
1418 cmd.mode = cpu_to_le16(mode);
1419
1420 ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd);
1421
1422 if (ret == 0)
1423 priv->dev->type = ARPHRD_IEEE80211_RADIOTAP;
1424 else
1425 priv->dev->type = ARPHRD_ETHER;
1426
1427 lbs_deb_leave(LBS_DEB_CFG80211);
1428 return ret;
1429}
1430
1431
1432
1433
1434
1435
1436/***************************************************************************
1437 * Get station
1438 */
1439
1440/*
1441 * Returns the signal or 0 in case of an error.
1442 */
1443
1444/* like "struct cmd_ds_802_11_rssi", but with cmd_header. Once we get rid
1445 * of WEXT, this should go into host.h */
1446struct cmd_rssi {
1447 struct cmd_header hdr;
1448
1449 __le16 n_or_snr;
1450 __le16 nf;
1451 __le16 avg_snr;
1452 __le16 avg_nf;
1453} __attribute__ ((packed));
1454
1455static int lbs_get_signal(struct lbs_private *priv, s8 *signal, s8 *noise)
1456{
1457 struct cmd_rssi cmd;
1458 int ret;
1459
1460 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1461 cmd.n_or_snr = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
1462 ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
1463
1464 if (ret == 0) {
1465 *signal = CAL_RSSI(le16_to_cpu(cmd.n_or_snr),
1466 le16_to_cpu(cmd.nf));
1467 *noise = CAL_NF(le16_to_cpu(cmd.nf));
1468 }
1469 return ret;
1470}
1471
1472
1473static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
1474 u8 *mac, struct station_info *sinfo)
1475{
1476 struct lbs_private *priv = wiphy_priv(wiphy);
1477 s8 signal, noise;
1478 int ret;
1479 size_t i;
1480
1481 lbs_deb_enter(LBS_DEB_CFG80211);
1482
1483 sinfo->filled |= STATION_INFO_TX_BYTES |
1484 STATION_INFO_TX_PACKETS |
1485 STATION_INFO_RX_BYTES |
1486 STATION_INFO_RX_PACKETS;
1487 sinfo->tx_bytes = priv->dev->stats.tx_bytes;
1488 sinfo->tx_packets = priv->dev->stats.tx_packets;
1489 sinfo->rx_bytes = priv->dev->stats.rx_bytes;
1490 sinfo->rx_packets = priv->dev->stats.rx_packets;
1491
1492 /* Get current RSSI */
1493 ret = lbs_get_signal(priv, &signal, &noise);
1494 if (ret == 0) {
1495 sinfo->signal = signal;
1496 sinfo->filled |= STATION_INFO_SIGNAL;
1497 }
1498
1499 /* Convert priv->cur_rate from hw_value to NL80211 value */
1500 for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) {
1501 if (priv->cur_rate == lbs_rates[i].hw_value) {
1502 sinfo->txrate.legacy = lbs_rates[i].bitrate;
1503 sinfo->filled |= STATION_INFO_TX_BITRATE;
1504 break;
1505 }
1506 }
1507
1508 return 0;
1509}
1510
1511
1512
1513
1514/***************************************************************************
1515 * "Site survey", here just current channel and noise level
1516 */
1517
1518static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
1519 int idx, struct survey_info *survey)
1520{
1521 struct lbs_private *priv = wiphy_priv(wiphy);
1522 s8 signal, noise;
1523 int ret;
1524
1525 if (idx != 0)
1526 ret = -ENOENT;
1527
1528 lbs_deb_enter(LBS_DEB_CFG80211);
1529
1530 survey->channel = ieee80211_get_channel(wiphy,
1531 ieee80211_channel_to_frequency(priv->channel));
1532
1533 ret = lbs_get_signal(priv, &signal, &noise);
1534 if (ret == 0) {
1535 survey->filled = SURVEY_INFO_NOISE_DBM;
1536 survey->noise = noise;
1537 }
1538
1539 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1540 return ret;
1541}
1542
1543
1544
1545
1546/***************************************************************************
1547 * Change interface
1548 */
1549
1550static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
1551 enum nl80211_iftype type, u32 *flags,
1552 struct vif_params *params)
1553{
1554 struct lbs_private *priv = wiphy_priv(wiphy);
1555 int ret = 0;
1556
1557 lbs_deb_enter(LBS_DEB_CFG80211);
1558
1559 switch (type) {
1560 case NL80211_IFTYPE_MONITOR:
1561 ret = lbs_enable_monitor_mode(priv, 1);
1562 break;
1563 case NL80211_IFTYPE_STATION:
1564 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
1565 ret = lbs_enable_monitor_mode(priv, 0);
1566 if (!ret)
1567 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
1568 break;
1569 case NL80211_IFTYPE_ADHOC:
1570 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
1571 ret = lbs_enable_monitor_mode(priv, 0);
1572 if (!ret)
1573 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
1574 break;
1575 default:
1576 ret = -ENOTSUPP;
1577 }
1578
1579 if (!ret)
1580 priv->wdev->iftype = type;
1581
1582 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1583 return ret;
1584}
1585
1586
1587
1588/***************************************************************************
1589 * IBSS (Ad-Hoc)
1590 */
1591
1592/* The firmware needs the following bits masked out of the beacon-derived
1593 * capability field when associating/joining to a BSS:
1594 * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused)
1595 */
1596#define CAPINFO_MASK (~(0xda00))
1597
1598
1599static void lbs_join_post(struct lbs_private *priv,
1600 struct cfg80211_ibss_params *params,
1601 u8 *bssid, u16 capability)
1602{
1603 u8 fake_ie[2 + IEEE80211_MAX_SSID_LEN + /* ssid */
1604 2 + 4 + /* basic rates */
1605 2 + 1 + /* DS parameter */
1606 2 + 2 + /* atim */
1607 2 + 8]; /* extended rates */
1608 u8 *fake = fake_ie;
1609
1610 lbs_deb_enter(LBS_DEB_CFG80211);
1611
1612 /*
1613 * For cfg80211_inform_bss, we'll need a fake IE, as we can't get
1614 * the real IE from the firmware. So we fabricate a fake IE based on
1615 * what the firmware actually sends (sniffed with wireshark).
1616 */
1617 /* Fake SSID IE */
1618 *fake++ = WLAN_EID_SSID;
1619 *fake++ = params->ssid_len;
1620 memcpy(fake, params->ssid, params->ssid_len);
1621 fake += params->ssid_len;
1622 /* Fake supported basic rates IE */
1623 *fake++ = WLAN_EID_SUPP_RATES;
1624 *fake++ = 4;
1625 *fake++ = 0x82;
1626 *fake++ = 0x84;
1627 *fake++ = 0x8b;
1628 *fake++ = 0x96;
1629 /* Fake DS channel IE */
1630 *fake++ = WLAN_EID_DS_PARAMS;
1631 *fake++ = 1;
1632 *fake++ = params->channel->hw_value;
1633 /* Fake IBSS params IE */
1634 *fake++ = WLAN_EID_IBSS_PARAMS;
1635 *fake++ = 2;
1636 *fake++ = 0; /* ATIM=0 */
1637 *fake++ = 0;
1638 /* Fake extended rates IE, TODO: don't add this for 802.11b only,
1639 * but I don't know how this could be checked */
1640 *fake++ = WLAN_EID_EXT_SUPP_RATES;
1641 *fake++ = 8;
1642 *fake++ = 0x0c;
1643 *fake++ = 0x12;
1644 *fake++ = 0x18;
1645 *fake++ = 0x24;
1646 *fake++ = 0x30;
1647 *fake++ = 0x48;
1648 *fake++ = 0x60;
1649 *fake++ = 0x6c;
1650 lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie);
1651
1652 cfg80211_inform_bss(priv->wdev->wiphy,
1653 params->channel,
1654 bssid,
1655 0,
1656 capability,
1657 params->beacon_interval,
1658 fake_ie, fake - fake_ie,
1659 0, GFP_KERNEL);
1660
1661 memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
1662 priv->wdev->ssid_len = params->ssid_len;
1663
1664 cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
1665
1666 /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
1667 priv->connect_status = LBS_CONNECTED;
1668 netif_carrier_on(priv->dev);
1669 if (!priv->tx_pending_len)
1670 netif_wake_queue(priv->dev);
1671
1672 lbs_deb_leave(LBS_DEB_CFG80211);
1673}
1674
1675static int lbs_ibss_join_existing(struct lbs_private *priv,
1676 struct cfg80211_ibss_params *params,
1677 struct cfg80211_bss *bss)
1678{
1679 const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1680 struct cmd_ds_802_11_ad_hoc_join cmd;
1681 u8 preamble = RADIO_PREAMBLE_SHORT;
1682 int ret = 0;
1683
1684 lbs_deb_enter(LBS_DEB_CFG80211);
1685
1686 /* TODO: set preamble based on scan result */
1687 ret = lbs_set_radio(priv, preamble, 1);
1688 if (ret)
1689 goto out;
1690
1691 /*
1692 * Example CMD_802_11_AD_HOC_JOIN command:
1693 *
1694 * command 2c 00 CMD_802_11_AD_HOC_JOIN
1695 * size 65 00
1696 * sequence xx xx
1697 * result 00 00
1698 * bssid 02 27 27 97 2f 96
1699 * ssid 49 42 53 53 00 00 00 00
1700 * 00 00 00 00 00 00 00 00
1701 * 00 00 00 00 00 00 00 00
1702 * 00 00 00 00 00 00 00 00
1703 * type 02 CMD_BSS_TYPE_IBSS
1704 * beacon period 64 00
1705 * dtim period 00
1706 * timestamp 00 00 00 00 00 00 00 00
1707 * localtime 00 00 00 00 00 00 00 00
1708 * IE DS 03
1709 * IE DS len 01
1710 * IE DS channel 01
1711 * reserveed 00 00 00 00
1712 * IE IBSS 06
1713 * IE IBSS len 02
1714 * IE IBSS atim 00 00
1715 * reserved 00 00 00 00
1716 * capability 02 00
1717 * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c 00
1718 * fail timeout ff 00
1719 * probe delay 00 00
1720 */
1721 memset(&cmd, 0, sizeof(cmd));
1722 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1723
1724 memcpy(cmd.bss.bssid, bss->bssid, ETH_ALEN);
1725 memcpy(cmd.bss.ssid, params->ssid, params->ssid_len);
1726 cmd.bss.type = CMD_BSS_TYPE_IBSS;
1727 cmd.bss.beaconperiod = cpu_to_le16(params->beacon_interval);
1728 cmd.bss.ds.header.id = WLAN_EID_DS_PARAMS;
1729 cmd.bss.ds.header.len = 1;
1730 cmd.bss.ds.channel = params->channel->hw_value;
1731 cmd.bss.ibss.header.id = WLAN_EID_IBSS_PARAMS;
1732 cmd.bss.ibss.header.len = 2;
1733 cmd.bss.ibss.atimwindow = 0;
1734 cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
1735
1736 /* set rates to the intersection of our rates and the rates in the
1737 bss */
1738 if (!rates_eid) {
1739 lbs_add_rates(cmd.bss.rates);
1740 } else {
1741 int hw, i;
1742 u8 rates_max = rates_eid[1];
1743 u8 *rates = cmd.bss.rates;
1744 for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) {
1745 u8 hw_rate = lbs_rates[hw].bitrate / 5;
1746 for (i = 0; i < rates_max; i++) {
1747 if (hw_rate == (rates_eid[i+2] & 0x7f)) {
1748 u8 rate = rates_eid[i+2];
1749 if (rate == 0x02 || rate == 0x04 ||
1750 rate == 0x0b || rate == 0x16)
1751 rate |= 0x80;
1752 *rates++ = rate;
1753 }
1754 }
1755 }
1756 }
1757
1758 /* Only v8 and below support setting this */
1759 if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) {
1760 cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
1761 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1762 }
1763 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
1764 if (ret)
1765 goto out;
1766
1767 /*
1768 * This is a sample response to CMD_802_11_AD_HOC_JOIN:
1769 *
1770 * response 2c 80
1771 * size 09 00
1772 * sequence xx xx
1773 * result 00 00
1774 * reserved 00
1775 */
1776 lbs_join_post(priv, params, bss->bssid, bss->capability);
1777
1778 out:
1779 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1780 return ret;
1781}
1782
1783
1784
1785static int lbs_ibss_start_new(struct lbs_private *priv,
1786 struct cfg80211_ibss_params *params)
1787{
1788 struct cmd_ds_802_11_ad_hoc_start cmd;
1789 struct cmd_ds_802_11_ad_hoc_result *resp =
1790 (struct cmd_ds_802_11_ad_hoc_result *) &cmd;
1791 u8 preamble = RADIO_PREAMBLE_SHORT;
1792 int ret = 0;
1793 u16 capability;
1794
1795 lbs_deb_enter(LBS_DEB_CFG80211);
1796
1797 ret = lbs_set_radio(priv, preamble, 1);
1798 if (ret)
1799 goto out;
1800
1801 /*
1802 * Example CMD_802_11_AD_HOC_START command:
1803 *
1804 * command 2b 00 CMD_802_11_AD_HOC_START
1805 * size b1 00
1806 * sequence xx xx
1807 * result 00 00
1808 * ssid 54 45 53 54 00 00 00 00
1809 * 00 00 00 00 00 00 00 00
1810 * 00 00 00 00 00 00 00 00
1811 * 00 00 00 00 00 00 00 00
1812 * bss type 02
1813 * beacon period 64 00
1814 * dtim period 00
1815 * IE IBSS 06
1816 * IE IBSS len 02
1817 * IE IBSS atim 00 00
1818 * reserved 00 00 00 00
1819 * IE DS 03
1820 * IE DS len 01
1821 * IE DS channel 01
1822 * reserved 00 00 00 00
1823 * probe delay 00 00
1824 * capability 02 00
1825 * rates 82 84 8b 96 (basic rates with have bit 7 set)
1826 * 0c 12 18 24 30 48 60 6c
1827 * padding 100 bytes
1828 */
1829 memset(&cmd, 0, sizeof(cmd));
1830 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1831 memcpy(cmd.ssid, params->ssid, params->ssid_len);
1832 cmd.bsstype = CMD_BSS_TYPE_IBSS;
1833 cmd.beaconperiod = cpu_to_le16(params->beacon_interval);
1834 cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS;
1835 cmd.ibss.header.len = 2;
1836 cmd.ibss.atimwindow = 0;
1837 cmd.ds.header.id = WLAN_EID_DS_PARAMS;
1838 cmd.ds.header.len = 1;
1839 cmd.ds.channel = params->channel->hw_value;
1840 /* Only v8 and below support setting probe delay */
1841 if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8)
1842 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1843 /* TODO: mix in WLAN_CAPABILITY_PRIVACY */
1844 capability = WLAN_CAPABILITY_IBSS;
1845 cmd.capability = cpu_to_le16(capability);
1846 lbs_add_rates(cmd.rates);
1847
1848
1849 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
1850 if (ret)
1851 goto out;
1852
1853 /*
1854 * This is a sample response to CMD_802_11_AD_HOC_JOIN:
1855 *
1856 * response 2b 80
1857 * size 14 00
1858 * sequence xx xx
1859 * result 00 00
1860 * reserved 00
1861 * bssid 02 2b 7b 0f 86 0e
1862 */
1863 lbs_join_post(priv, params, resp->bssid, capability);
1864
1865 out:
1866 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1867 return ret;
1868}
1869
1870
1871static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1872 struct cfg80211_ibss_params *params)
1873{
1874 struct lbs_private *priv = wiphy_priv(wiphy);
1875 int ret = 0;
1876 struct cfg80211_bss *bss;
1877 DECLARE_SSID_BUF(ssid_buf);
1878
1879 lbs_deb_enter(LBS_DEB_CFG80211);
1880
1881 if (!params->channel) {
1882 ret = -ENOTSUPP;
1883 goto out;
1884 }
1885
1886 ret = lbs_set_channel(priv, params->channel->hw_value);
1887 if (ret)
1888 goto out;
1889
1890 /* Search if someone is beaconing. This assumes that the
1891 * bss list is populated already */
1892 bss = cfg80211_get_bss(wiphy, params->channel, params->bssid,
1893 params->ssid, params->ssid_len,
1894 WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
1895
1896 if (bss) {
1897 ret = lbs_ibss_join_existing(priv, params, bss);
1898 cfg80211_put_bss(bss);
1899 } else
1900 ret = lbs_ibss_start_new(priv, params);
1901
1902
1903 out:
1904 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1905 return ret;
1906}
1907
1908
1909static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1910{
1911 struct lbs_private *priv = wiphy_priv(wiphy);
1912 struct cmd_ds_802_11_ad_hoc_stop cmd;
1913 int ret = 0;
1914
1915 lbs_deb_enter(LBS_DEB_CFG80211);
1916
1917 memset(&cmd, 0, sizeof(cmd));
1918 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1919 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
1920
1921 /* TODO: consider doing this at MACREG_INT_CODE_ADHOC_BCN_LOST time */
1922 lbs_mac_event_disconnected(priv);
1923
1924 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1925 return ret;
1926}
1927
1928
1929
1930
1931/***************************************************************************
1932 * Initialization
1933 */
1934
104static struct cfg80211_ops lbs_cfg80211_ops = { 1935static struct cfg80211_ops lbs_cfg80211_ops = {
105 .set_channel = lbs_cfg_set_channel, 1936 .set_channel = lbs_cfg_set_channel,
1937 .scan = lbs_cfg_scan,
1938 .connect = lbs_cfg_connect,
1939 .disconnect = lbs_cfg_disconnect,
1940 .add_key = lbs_cfg_add_key,
1941 .del_key = lbs_cfg_del_key,
1942 .set_default_key = lbs_cfg_set_default_key,
1943 .get_station = lbs_cfg_get_station,
1944 .dump_survey = lbs_get_survey,
1945 .change_virtual_intf = lbs_change_intf,
1946 .join_ibss = lbs_join_ibss,
1947 .leave_ibss = lbs_leave_ibss,
106}; 1948};
107 1949
108 1950
@@ -142,6 +1984,36 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev)
142} 1984}
143 1985
144 1986
1987static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv)
1988{
1989 struct region_code_mapping {
1990 const char *cn;
1991 int code;
1992 };
1993
1994 /* Section 5.17.2 */
1995 static struct region_code_mapping regmap[] = {
1996 {"US ", 0x10}, /* US FCC */
1997 {"CA ", 0x20}, /* Canada */
1998 {"EU ", 0x30}, /* ETSI */
1999 {"ES ", 0x31}, /* Spain */
2000 {"FR ", 0x32}, /* France */
2001 {"JP ", 0x40}, /* Japan */
2002 };
2003 size_t i;
2004
2005 lbs_deb_enter(LBS_DEB_CFG80211);
2006
2007 for (i = 0; i < ARRAY_SIZE(regmap); i++)
2008 if (regmap[i].code == priv->regioncode) {
2009 regulatory_hint(priv->wdev->wiphy, regmap[i].cn);
2010 break;
2011 }
2012
2013 lbs_deb_leave(LBS_DEB_CFG80211);
2014}
2015
2016
145/* 2017/*
146 * This function get's called after lbs_setup_firmware() determined the 2018 * This function get's called after lbs_setup_firmware() determined the
147 * firmware capabities. So we can setup the wiphy according to our 2019 * firmware capabities. So we can setup the wiphy according to our
@@ -157,10 +2029,12 @@ int lbs_cfg_register(struct lbs_private *priv)
157 wdev->wiphy->max_scan_ssids = 1; 2029 wdev->wiphy->max_scan_ssids = 1;
158 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 2030 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
159 2031
160 /* TODO: BIT(NL80211_IFTYPE_ADHOC); */ 2032 wdev->wiphy->interface_modes =
161 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 2033 BIT(NL80211_IFTYPE_STATION) |
2034 BIT(NL80211_IFTYPE_ADHOC);
2035 if (lbs_rtap_supported(priv))
2036 wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
162 2037
163 /* TODO: honor priv->regioncode */
164 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; 2038 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
165 2039
166 /* 2040 /*
@@ -169,6 +2043,7 @@ int lbs_cfg_register(struct lbs_private *priv)
169 */ 2043 */
170 wdev->wiphy->cipher_suites = cipher_suites; 2044 wdev->wiphy->cipher_suites = cipher_suites;
171 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 2045 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
2046 wdev->wiphy->reg_notifier = lbs_reg_notifier;
172 2047
173 ret = wiphy_register(wdev->wiphy); 2048 ret = wiphy_register(wdev->wiphy);
174 if (ret < 0) 2049 if (ret < 0)
@@ -180,10 +2055,129 @@ int lbs_cfg_register(struct lbs_private *priv)
180 if (ret) 2055 if (ret)
181 lbs_pr_err("cannot register network device\n"); 2056 lbs_pr_err("cannot register network device\n");
182 2057
2058 INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
2059
2060 lbs_cfg_set_regulatory_hint(priv);
2061
183 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); 2062 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
184 return ret; 2063 return ret;
185} 2064}
186 2065
2066/**
2067 * @brief This function sets DOMAIN INFO to FW
2068 * @param priv pointer to struct lbs_private
2069 * @return 0; -1
2070*/
2071static int lbs_11d_set_domain_info(struct lbs_private *priv)
2072{
2073 int ret;
2074
2075 ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
2076 CMD_ACT_SET,
2077 CMD_OPTION_WAITFORRSP, 0, NULL);
2078 if (ret)
2079 lbs_deb_11d("fail to dnld domain info\n");
2080
2081 return ret;
2082}
2083
2084static void lbs_send_domain_info_cmd_fw(struct wiphy *wiphy,
2085 struct regulatory_request *request)
2086{
2087 u8 no_of_triplet = 0;
2088 u8 no_of_parsed_chan = 0;
2089 u8 first_channel = 0, next_chan = 0, max_pwr = 0;
2090 u8 i, flag = 0;
2091 enum ieee80211_band band;
2092 struct ieee80211_supported_band *sband;
2093 struct ieee80211_channel *ch;
2094 struct lbs_private *priv = wiphy_priv(wiphy);
2095 struct lbs_802_11d_domain_reg *domain_info = &priv->domain_reg;
2096 int ret = 0;
2097
2098 lbs_deb_enter(LBS_DEB_CFG80211);
2099
2100 /* Set country code */
2101 domain_info->country_code[0] = request->alpha2[0];
2102 domain_info->country_code[1] = request->alpha2[1];
2103 domain_info->country_code[2] = ' ';
2104
2105 for (band = 0; band < IEEE80211_NUM_BANDS ; band++) {
2106
2107 if (!wiphy->bands[band])
2108 continue;
2109
2110 sband = wiphy->bands[band];
2111
2112 for (i = 0; i < sband->n_channels ; i++) {
2113 ch = &sband->channels[i];
2114 if (ch->flags & IEEE80211_CHAN_DISABLED)
2115 continue;
2116
2117 if (!flag) {
2118 flag = 1;
2119 next_chan = first_channel = (u32) ch->hw_value;
2120 max_pwr = ch->max_power;
2121 no_of_parsed_chan = 1;
2122 continue;
2123 }
2124
2125 if (ch->hw_value == next_chan + 1 &&
2126 ch->max_power == max_pwr) {
2127 next_chan++;
2128 no_of_parsed_chan++;
2129 } else {
2130 domain_info->triplet[no_of_triplet]
2131 .chans.first_channel = first_channel;
2132 domain_info->triplet[no_of_triplet]
2133 .chans.num_channels = no_of_parsed_chan;
2134 domain_info->triplet[no_of_triplet]
2135 .chans.max_power = max_pwr;
2136 no_of_triplet++;
2137 flag = 0;
2138 }
2139 }
2140 if (flag) {
2141 domain_info->triplet[no_of_triplet]
2142 .chans.first_channel = first_channel;
2143 domain_info->triplet[no_of_triplet]
2144 .chans.num_channels = no_of_parsed_chan;
2145 domain_info->triplet[no_of_triplet]
2146 .chans.max_power = max_pwr;
2147 no_of_triplet++;
2148 }
2149 }
2150
2151 domain_info->no_triplet = no_of_triplet;
2152
2153 /* Set domain info */
2154 ret = lbs_11d_set_domain_info(priv);
2155 if (ret)
2156 lbs_pr_err("11D: error setting domain info in FW\n");
2157
2158 lbs_deb_leave(LBS_DEB_CFG80211);
2159}
2160
2161int lbs_reg_notifier(struct wiphy *wiphy,
2162 struct regulatory_request *request)
2163{
2164 lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
2165 "callback for domain %c%c\n", request->alpha2[0],
2166 request->alpha2[1]);
2167
2168 lbs_send_domain_info_cmd_fw(wiphy, request);
2169
2170 lbs_deb_leave(LBS_DEB_CFG80211);
2171
2172 return 0;
2173}
2174
2175void lbs_scan_deinit(struct lbs_private *priv)
2176{
2177 lbs_deb_enter(LBS_DEB_CFG80211);
2178 cancel_delayed_work_sync(&priv->scan_work);
2179}
2180
187 2181
188void lbs_cfg_free(struct lbs_private *priv) 2182void lbs_cfg_free(struct lbs_private *priv)
189{ 2183{
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
index e09a193a34d6..756fb98f9f05 100644
--- a/drivers/net/wireless/libertas/cfg.h
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -1,16 +1,27 @@
1#ifndef __LBS_CFG80211_H__ 1#ifndef __LBS_CFG80211_H__
2#define __LBS_CFG80211_H__ 2#define __LBS_CFG80211_H__
3 3
4#include "dev.h" 4struct device;
5struct lbs_private;
6struct regulatory_request;
7struct wiphy;
5 8
6struct wireless_dev *lbs_cfg_alloc(struct device *dev); 9struct wireless_dev *lbs_cfg_alloc(struct device *dev);
7int lbs_cfg_register(struct lbs_private *priv); 10int lbs_cfg_register(struct lbs_private *priv);
8void lbs_cfg_free(struct lbs_private *priv); 11void lbs_cfg_free(struct lbs_private *priv);
9 12
10int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, 13int lbs_reg_notifier(struct wiphy *wiphy,
11 u8 ssid_len); 14 struct regulatory_request *request);
12int lbs_scan_networks(struct lbs_private *priv, int full_scan);
13void lbs_cfg_scan_worker(struct work_struct *work);
14 15
16/* All of those are TODOs: */
17#define lbs_cmd_802_11_rssi(priv, cmdptr) (0)
18#define lbs_ret_802_11_rssi(priv, resp) (0)
19#define lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action) (0)
20#define lbs_ret_802_11_bcn_ctrl(priv, resp) (0)
21
22void lbs_send_disconnect_notification(struct lbs_private *priv);
23void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
24
25void lbs_scan_deinit(struct lbs_private *priv);
15 26
16#endif 27#endif
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 0fa6b0e59ea5..6c8a9d952a01 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -7,13 +7,8 @@
7#include <linux/sched.h> 7#include <linux/sched.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9 9
10#include "host.h"
11#include "decl.h" 10#include "decl.h"
12#include "defs.h" 11#include "cfg.h"
13#include "dev.h"
14#include "assoc.h"
15#include "wext.h"
16#include "scan.h"
17#include "cmd.h" 12#include "cmd.h"
18 13
19 14
@@ -177,11 +172,6 @@ int lbs_update_hw_spec(struct lbs_private *priv)
177 if (priv->mesh_dev) 172 if (priv->mesh_dev)
178 memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); 173 memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
179 174
180 if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
181 ret = -1;
182 goto out;
183 }
184
185out: 175out:
186 lbs_deb_leave(LBS_DEB_CMD); 176 lbs_deb_leave(LBS_DEB_CMD);
187 return ret; 177 return ret;
@@ -909,6 +899,66 @@ void lbs_set_mac_control(struct lbs_private *priv)
909} 899}
910 900
911/** 901/**
902 * @brief This function implements command CMD_802_11D_DOMAIN_INFO
903 * @param priv pointer to struct lbs_private
904 * @param cmd pointer to cmd buffer
905 * @param cmdno cmd ID
906 * @param cmdOption cmd action
907 * @return 0
908*/
909int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
910 struct cmd_ds_command *cmd,
911 u16 cmdoption)
912{
913 struct cmd_ds_802_11d_domain_info *pdomaininfo =
914 &cmd->params.domaininfo;
915 struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain;
916 u8 nr_triplet = priv->domain_reg.no_triplet;
917
918 lbs_deb_enter(LBS_DEB_11D);
919
920 lbs_deb_11d("nr_triplet=%x\n", nr_triplet);
921
922 pdomaininfo->action = cpu_to_le16(cmdoption);
923 if (cmdoption == CMD_ACT_GET) {
924 cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
925 sizeof(struct cmd_header));
926 lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
927 le16_to_cpu(cmd->size));
928 goto done;
929 }
930
931 domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
932 memcpy(domain->countrycode, priv->domain_reg.country_code,
933 sizeof(domain->countrycode));
934
935 domain->header.len = cpu_to_le16(nr_triplet
936 * sizeof(struct ieee80211_country_ie_triplet)
937 + sizeof(domain->countrycode));
938
939 if (nr_triplet) {
940 memcpy(domain->triplet, priv->domain_reg.triplet,
941 nr_triplet *
942 sizeof(struct ieee80211_country_ie_triplet));
943
944 cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
945 le16_to_cpu(domain->header.len) +
946 sizeof(struct mrvl_ie_header) +
947 sizeof(struct cmd_header));
948 } else {
949 cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
950 sizeof(struct cmd_header));
951 }
952
953 lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
954 le16_to_cpu(cmd->size));
955
956done:
957 lbs_deb_enter(LBS_DEB_11D);
958 return 0;
959}
960
961/**
912 * @brief This function prepare the command before send to firmware. 962 * @brief This function prepare the command before send to firmware.
913 * 963 *
914 * @param priv A pointer to struct lbs_private structure 964 * @param priv A pointer to struct lbs_private structure
@@ -1006,6 +1056,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
1006 ret = 0; 1056 ret = 0;
1007 goto done; 1057 goto done;
1008 1058
1059 case CMD_802_11D_DOMAIN_INFO:
1060 cmdptr->command = cpu_to_le16(cmd_no);
1061 ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, cmd_action);
1062 break;
1063
1009 case CMD_802_11_TPC_CFG: 1064 case CMD_802_11_TPC_CFG:
1010 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); 1065 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
1011 cmdptr->size = 1066 cmdptr->size =
@@ -1325,6 +1380,15 @@ int lbs_execute_next_command(struct lbs_private *priv)
1325 * check if in power save mode, if yes, put the device back 1380 * check if in power save mode, if yes, put the device back
1326 * to PS mode 1381 * to PS mode
1327 */ 1382 */
1383#ifdef TODO
1384 /*
1385 * This was the old code for libertas+wext. Someone that
1386 * understands this beast should re-code it in a sane way.
1387 *
1388 * I actually don't understand why this is related to WPA
1389 * and to connection status, shouldn't powering should be
1390 * independ of such things?
1391 */
1328 if ((priv->psmode != LBS802_11POWERMODECAM) && 1392 if ((priv->psmode != LBS802_11POWERMODECAM) &&
1329 (priv->psstate == PS_STATE_FULL_POWER) && 1393 (priv->psstate == PS_STATE_FULL_POWER) &&
1330 ((priv->connect_status == LBS_CONNECTED) || 1394 ((priv->connect_status == LBS_CONNECTED) ||
@@ -1346,6 +1410,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
1346 lbs_ps_sleep(priv, 0); 1410 lbs_ps_sleep(priv, 0);
1347 } 1411 }
1348 } 1412 }
1413#endif
1349 } 1414 }
1350 1415
1351 ret = 0; 1416 ret = 0;
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index d6c306353640..a0d9482ef5e2 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -5,18 +5,10 @@
5#include <linux/slab.h> 5#include <linux/slab.h>
6#include <linux/delay.h> 6#include <linux/delay.h>
7#include <linux/sched.h> 7#include <linux/sched.h>
8#include <linux/if_arp.h>
9#include <linux/netdevice.h>
10#include <asm/unaligned.h> 8#include <asm/unaligned.h>
11#include <net/iw_handler.h> 9#include <net/cfg80211.h>
12 10
13#include "host.h" 11#include "cfg.h"
14#include "decl.h"
15#include "cmd.h"
16#include "defs.h"
17#include "dev.h"
18#include "assoc.h"
19#include "wext.h"
20#include "cmd.h" 12#include "cmd.h"
21 13
22/** 14/**
@@ -39,7 +31,9 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
39 * It causes problem in the Supplicant 31 * It causes problem in the Supplicant
40 */ 32 */
41 msleep_interruptible(1000); 33 msleep_interruptible(1000);
42 lbs_send_disconnect_notification(priv); 34
35 if (priv->wdev->iftype == NL80211_IFTYPE_STATION)
36 lbs_send_disconnect_notification(priv);
43 37
44 /* report disconnect to upper layer */ 38 /* report disconnect to upper layer */
45 netif_stop_queue(priv->dev); 39 netif_stop_queue(priv->dev);
@@ -50,23 +44,8 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
50 priv->currenttxskb = NULL; 44 priv->currenttxskb = NULL;
51 priv->tx_pending_len = 0; 45 priv->tx_pending_len = 0;
52 46
53 /* reset SNR/NF/RSSI values */
54 memset(priv->SNR, 0x00, sizeof(priv->SNR));
55 memset(priv->NF, 0x00, sizeof(priv->NF));
56 memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
57 memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
58 memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
59 priv->nextSNRNF = 0;
60 priv->numSNRNF = 0;
61 priv->connect_status = LBS_DISCONNECTED; 47 priv->connect_status = LBS_DISCONNECTED;
62 48
63 /* Clear out associated SSID and BSSID since connection is
64 * no longer valid.
65 */
66 memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
67 memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN);
68 priv->curbssparams.ssid_len = 0;
69
70 if (priv->psstate != PS_STATE_FULL_POWER) { 49 if (priv->psstate != PS_STATE_FULL_POWER) {
71 /* make firmware to exit PS mode */ 50 /* make firmware to exit PS mode */
72 lbs_deb_cmd("disconnected, so exit PS mode\n"); 51 lbs_deb_cmd("disconnected, so exit PS mode\n");
@@ -118,6 +97,52 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
118 return ret; 97 return ret;
119} 98}
120 99
100/**
101 * @brief This function parses countryinfo from AP and download country info to FW
102 * @param priv pointer to struct lbs_private
103 * @param resp pointer to command response buffer
104 * @return 0; -1
105 */
106static int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
107{
108 struct cmd_ds_802_11d_domain_info *domaininfo =
109 &resp->params.domaininforesp;
110 struct mrvl_ie_domain_param_set *domain = &domaininfo->domain;
111 u16 action = le16_to_cpu(domaininfo->action);
112 s16 ret = 0;
113 u8 nr_triplet = 0;
114
115 lbs_deb_enter(LBS_DEB_11D);
116
117 lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp,
118 (int)le16_to_cpu(resp->size));
119
120 nr_triplet = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
121 sizeof(struct ieee80211_country_ie_triplet);
122
123 lbs_deb_11d("domain info resp: nr_triplet %d\n", nr_triplet);
124
125 if (nr_triplet > MRVDRV_MAX_TRIPLET_802_11D) {
126 lbs_deb_11d("invalid number of triplets returned!!\n");
127 return -1;
128 }
129
130 switch (action) {
131 case CMD_ACT_SET: /*Proc set action */
132 break;
133
134 case CMD_ACT_GET:
135 break;
136 default:
137 lbs_deb_11d("invalid action:%d\n", domaininfo->action);
138 ret = -1;
139 break;
140 }
141
142 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
143 return ret;
144}
145
121static inline int handle_cmd_response(struct lbs_private *priv, 146static inline int handle_cmd_response(struct lbs_private *priv,
122 struct cmd_header *cmd_response) 147 struct cmd_header *cmd_response)
123{ 148{
@@ -151,6 +176,10 @@ static inline int handle_cmd_response(struct lbs_private *priv,
151 ret = lbs_ret_802_11_rssi(priv, resp); 176 ret = lbs_ret_802_11_rssi(priv, resp);
152 break; 177 break;
153 178
179 case CMD_RET(CMD_802_11D_DOMAIN_INFO):
180 ret = lbs_ret_802_11d_domain_info(resp);
181 break;
182
154 case CMD_RET(CMD_802_11_TPC_CFG): 183 case CMD_RET(CMD_802_11_TPC_CFG):
155 spin_lock_irqsave(&priv->driver_lock, flags); 184 spin_lock_irqsave(&priv->driver_lock, flags);
156 memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, 185 memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
@@ -262,7 +291,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
262 * ad-hoc mode. It takes place in 291 * ad-hoc mode. It takes place in
263 * lbs_execute_next_command(). 292 * lbs_execute_next_command().
264 */ 293 */
265 if (priv->mode == IW_MODE_ADHOC && 294 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
266 action == CMD_SUBCMD_ENTER_PS) 295 action == CMD_SUBCMD_ENTER_PS)
267 priv->psmode = LBS802_11POWERMODECAM; 296 priv->psmode = LBS802_11POWERMODECAM;
268 } else if (action == CMD_SUBCMD_ENTER_PS) { 297 } else if (action == CMD_SUBCMD_ENTER_PS) {
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index de2caac11dd6..17367463c855 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -1,18 +1,13 @@
1#include <linux/module.h>
2#include <linux/dcache.h> 1#include <linux/dcache.h>
3#include <linux/debugfs.h> 2#include <linux/debugfs.h>
4#include <linux/delay.h> 3#include <linux/delay.h>
5#include <linux/mm.h> 4#include <linux/mm.h>
6#include <linux/string.h> 5#include <linux/string.h>
7#include <linux/slab.h> 6#include <linux/slab.h>
8#include <net/iw_handler.h>
9#include <net/lib80211.h>
10 7
11#include "dev.h"
12#include "decl.h" 8#include "decl.h"
13#include "host.h"
14#include "debugfs.h"
15#include "cmd.h" 9#include "cmd.h"
10#include "debugfs.h"
16 11
17static struct dentry *lbs_dir; 12static struct dentry *lbs_dir;
18static char *szStates[] = { 13static char *szStates[] = {
@@ -60,51 +55,6 @@ static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
60 return res; 55 return res;
61} 56}
62 57
63
64static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
65 size_t count, loff_t *ppos)
66{
67 struct lbs_private *priv = file->private_data;
68 size_t pos = 0;
69 int numscansdone = 0, res;
70 unsigned long addr = get_zeroed_page(GFP_KERNEL);
71 char *buf = (char *)addr;
72 DECLARE_SSID_BUF(ssid);
73 struct bss_descriptor * iter_bss;
74 if (!buf)
75 return -ENOMEM;
76
77 pos += snprintf(buf+pos, len-pos,
78 "# | ch | rssi | bssid | cap | Qual | SSID\n");
79
80 mutex_lock(&priv->lock);
81 list_for_each_entry (iter_bss, &priv->network_list, list) {
82 u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS);
83 u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
84 u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
85
86 pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |",
87 numscansdone, iter_bss->channel, iter_bss->rssi,
88 iter_bss->bssid);
89 pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
90 pos += snprintf(buf+pos, len-pos, "%c%c%c |",
91 ibss ? 'A' : 'I', privacy ? 'P' : ' ',
92 spectrum_mgmt ? 'S' : ' ');
93 pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi));
94 pos += snprintf(buf+pos, len-pos, " %s\n",
95 print_ssid(ssid, iter_bss->ssid,
96 iter_bss->ssid_len));
97
98 numscansdone++;
99 }
100 mutex_unlock(&priv->lock);
101
102 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
103
104 free_page(addr);
105 return res;
106}
107
108static ssize_t lbs_sleepparams_write(struct file *file, 58static ssize_t lbs_sleepparams_write(struct file *file,
109 const char __user *user_buf, size_t count, 59 const char __user *user_buf, size_t count,
110 loff_t *ppos) 60 loff_t *ppos)
@@ -723,8 +673,6 @@ struct lbs_debugfs_files {
723 673
724static const struct lbs_debugfs_files debugfs_files[] = { 674static const struct lbs_debugfs_files debugfs_files[] = {
725 { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), }, 675 { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
726 { "getscantable", 0444, FOPS(lbs_getscantable,
727 write_file_dummy), },
728 { "sleepparams", 0644, FOPS(lbs_sleepparams_read, 676 { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
729 lbs_sleepparams_write), }, 677 lbs_sleepparams_write), },
730}; 678};
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 61db8bc62b3c..ba5438a7ba17 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -1,3 +1,4 @@
1
1/** 2/**
2 * This file contains declaration referring to 3 * This file contains declaration referring to
3 * functions defined in other source files 4 * functions defined in other source files
@@ -12,6 +13,7 @@
12struct lbs_private; 13struct lbs_private;
13struct sk_buff; 14struct sk_buff;
14struct net_device; 15struct net_device;
16struct cmd_ds_command;
15 17
16 18
17/* ethtool.c */ 19/* ethtool.c */
@@ -34,6 +36,8 @@ int lbs_start_card(struct lbs_private *priv);
34void lbs_stop_card(struct lbs_private *priv); 36void lbs_stop_card(struct lbs_private *priv);
35void lbs_host_to_card_done(struct lbs_private *priv); 37void lbs_host_to_card_done(struct lbs_private *priv);
36 38
39int lbs_rtap_supported(struct lbs_private *priv);
40
37int lbs_set_mac_address(struct net_device *dev, void *addr); 41int lbs_set_mac_address(struct net_device *dev, void *addr);
38void lbs_set_multicast_list(struct net_device *dev); 42void lbs_set_multicast_list(struct net_device *dev);
39 43
@@ -49,5 +53,9 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
49u32 lbs_fw_index_to_data_rate(u8 index); 53u32 lbs_fw_index_to_data_rate(u8 index);
50u8 lbs_data_rate_to_fw_index(u32 rate); 54u8 lbs_data_rate_to_fw_index(u32 rate);
51 55
56int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
57 struct cmd_ds_command *cmd, u16 cmdoption);
58
59int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
52 60
53#endif 61#endif
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 71c5ad46ebf6..4536d9c0ad87 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -7,8 +7,8 @@
7#define _LBS_DEV_H_ 7#define _LBS_DEV_H_
8 8
9#include "mesh.h" 9#include "mesh.h"
10#include "scan.h" 10#include "defs.h"
11#include "assoc.h" 11#include "host.h"
12 12
13#include <linux/kfifo.h> 13#include <linux/kfifo.h>
14 14
@@ -29,7 +29,6 @@ struct lbs_private {
29 /* Basic networking */ 29 /* Basic networking */
30 struct net_device *dev; 30 struct net_device *dev;
31 u32 connect_status; 31 u32 connect_status;
32 int infra_open;
33 struct work_struct mcast_work; 32 struct work_struct mcast_work;
34 u32 nr_of_multicastmacaddr; 33 u32 nr_of_multicastmacaddr;
35 u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; 34 u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
@@ -37,6 +36,9 @@ struct lbs_private {
37 /* CFG80211 */ 36 /* CFG80211 */
38 struct wireless_dev *wdev; 37 struct wireless_dev *wdev;
39 bool wiphy_registered; 38 bool wiphy_registered;
39 struct cfg80211_scan_request *scan_req;
40 u8 assoc_bss[ETH_ALEN];
41 u8 disassoc_reason;
40 42
41 /* Mesh */ 43 /* Mesh */
42 struct net_device *mesh_dev; /* Virtual device */ 44 struct net_device *mesh_dev; /* Virtual device */
@@ -49,10 +51,6 @@ struct lbs_private {
49 u8 mesh_ssid_len; 51 u8 mesh_ssid_len;
50#endif 52#endif
51 53
52 /* Monitor mode */
53 struct net_device *rtap_net_dev;
54 u32 monitormode;
55
56 /* Debugfs */ 54 /* Debugfs */
57 struct dentry *debugfs_dir; 55 struct dentry *debugfs_dir;
58 struct dentry *debugfs_debug; 56 struct dentry *debugfs_debug;
@@ -62,6 +60,9 @@ struct lbs_private {
62 struct dentry *regs_dir; 60 struct dentry *regs_dir;
63 struct dentry *debugfs_regs_files[6]; 61 struct dentry *debugfs_regs_files[6];
64 62
63 /** 11D and domain regulatory data */
64 struct lbs_802_11d_domain_reg domain_reg;
65
65 /* Hardware debugging */ 66 /* Hardware debugging */
66 u32 mac_offset; 67 u32 mac_offset;
67 u32 bbp_offset; 68 u32 bbp_offset;
@@ -133,14 +134,10 @@ struct lbs_private {
133 struct workqueue_struct *work_thread; 134 struct workqueue_struct *work_thread;
134 135
135 /** Encryption stuff */ 136 /** Encryption stuff */
136 struct lbs_802_11_security secinfo;
137 struct enc_key wpa_mcast_key;
138 struct enc_key wpa_unicast_key;
139 u8 wpa_ie[MAX_WPA_IE_LEN];
140 u8 wpa_ie_len;
141 u16 wep_tx_keyidx;
142 struct enc_key wep_keys[4];
143 u8 authtype_auto; 137 u8 authtype_auto;
138 u8 wep_tx_key;
139 u8 wep_key[4][WLAN_KEY_LEN_WEP104];
140 u8 wep_key_len[4];
144 141
145 /* Wake On LAN */ 142 /* Wake On LAN */
146 uint32_t wol_criteria; 143 uint32_t wol_criteria;
@@ -161,6 +158,7 @@ struct lbs_private {
161 /* NIC/link operation characteristics */ 158 /* NIC/link operation characteristics */
162 u16 mac_control; 159 u16 mac_control;
163 u8 radio_on; 160 u8 radio_on;
161 u8 cur_rate;
164 u8 channel; 162 u8 channel;
165 s16 txpower_cur; 163 s16 txpower_cur;
166 s16 txpower_min; 164 s16 txpower_min;
@@ -169,42 +167,6 @@ struct lbs_private {
169 /** Scanning */ 167 /** Scanning */
170 struct delayed_work scan_work; 168 struct delayed_work scan_work;
171 int scan_channel; 169 int scan_channel;
172 /* remember which channel was scanned last, != 0 if currently scanning */
173 u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1];
174 u8 scan_ssid_len;
175
176 /* Associating */
177 struct delayed_work assoc_work;
178 struct current_bss_params curbssparams;
179 u8 mode;
180 struct list_head network_list;
181 struct list_head network_free_list;
182 struct bss_descriptor *networks;
183 struct assoc_request * pending_assoc_req;
184 struct assoc_request * in_progress_assoc_req;
185 uint16_t enablehwauto;
186
187 /* ADHOC */
188 u16 beacon_period;
189 u8 beacon_enable;
190 u8 adhoccreate;
191
192 /* WEXT */
193 char name[DEV_NAME_LEN];
194 u8 nodename[16];
195 struct iw_statistics wstats;
196 u8 cur_rate;
197#define MAX_REGION_CHANNEL_NUM 2
198 struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
199
200 /** Requested Signal Strength*/
201 u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
202 u16 NF[MAX_TYPE_B][MAX_TYPE_AVG];
203 u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG];
204 u8 rawSNR[DEFAULT_DATA_AVG_FACTOR];
205 u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
206 u16 nextSNRNF;
207 u16 numSNRNF;
208}; 170};
209 171
210extern struct cmd_confirm_sleep confirm_sleep; 172extern struct cmd_confirm_sleep confirm_sleep;
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 0cf31bbf6567..50193aac679e 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -2,13 +2,8 @@
2#include <linux/ethtool.h> 2#include <linux/ethtool.h>
3#include <linux/delay.h> 3#include <linux/delay.h>
4 4
5#include "host.h"
6#include "decl.h" 5#include "decl.h"
7#include "defs.h"
8#include "dev.h"
9#include "wext.h"
10#include "cmd.h" 6#include "cmd.h"
11#include "mesh.h"
12 7
13 8
14static void lbs_ethtool_get_drvinfo(struct net_device *dev, 9static void lbs_ethtool_get_drvinfo(struct net_device *dev,
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 3bd5d3b6037a..db8e209878c1 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -389,6 +389,30 @@ struct lbs_offset_value {
389 u32 value; 389 u32 value;
390} __packed; 390} __packed;
391 391
392#define MRVDRV_MAX_TRIPLET_802_11D 83
393
394#define COUNTRY_CODE_LEN 3
395
396struct mrvl_ie_domain_param_set {
397 struct mrvl_ie_header header;
398
399 u8 countrycode[COUNTRY_CODE_LEN];
400 struct ieee80211_country_ie_triplet triplet[1];
401} __attribute__ ((packed));
402
403struct cmd_ds_802_11d_domain_info {
404 __le16 action;
405 struct mrvl_ie_domain_param_set domain;
406} __attribute__ ((packed));
407
408struct lbs_802_11d_domain_reg {
409 /** Country code*/
410 u8 country_code[COUNTRY_CODE_LEN];
411 /** No. of triplet*/
412 u8 no_triplet;
413 struct ieee80211_country_ie_triplet triplet[MRVDRV_MAX_TRIPLET_802_11D];
414} __attribute__ ((packed));
415
392/* 416/*
393 * Define data structure for CMD_GET_HW_SPEC 417 * Define data structure for CMD_GET_HW_SPEC
394 * This structure defines the response for the GET_HW_SPEC command 418 * This structure defines the response for the GET_HW_SPEC command
@@ -949,6 +973,9 @@ struct cmd_ds_command {
949 struct cmd_ds_bbp_reg_access bbpreg; 973 struct cmd_ds_bbp_reg_access bbpreg;
950 struct cmd_ds_rf_reg_access rfreg; 974 struct cmd_ds_rf_reg_access rfreg;
951 975
976 struct cmd_ds_802_11d_domain_info domaininfo;
977 struct cmd_ds_802_11d_domain_info domaininforesp;
978
952 struct cmd_ds_802_11_tpc_cfg tpccfg; 979 struct cmd_ds_802_11_tpc_cfg tpccfg;
953 struct cmd_ds_802_11_afc afc; 980 struct cmd_ds_802_11_afc afc;
954 struct cmd_ds_802_11_led_ctrl ledgpio; 981 struct cmd_ds_802_11_led_ctrl ledgpio;
@@ -958,5 +985,4 @@ struct cmd_ds_command {
958 struct cmd_ds_802_11_beacon_control bcn_ctrl; 985 struct cmd_ds_802_11_beacon_control bcn_ctrl;
959 } params; 986 } params;
960} __packed; 987} __packed;
961
962#endif 988#endif
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index abfecc4814b4..b519fc70f04f 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -11,20 +11,14 @@
11#include <linux/if_arp.h> 11#include <linux/if_arp.h>
12#include <linux/kthread.h> 12#include <linux/kthread.h>
13#include <linux/kfifo.h> 13#include <linux/kfifo.h>
14#include <linux/stddef.h>
15#include <linux/ieee80211.h>
16#include <linux/slab.h> 14#include <linux/slab.h>
17#include <net/iw_handler.h>
18#include <net/cfg80211.h> 15#include <net/cfg80211.h>
19 16
20#include "host.h" 17#include "host.h"
21#include "decl.h" 18#include "decl.h"
22#include "dev.h" 19#include "dev.h"
23#include "wext.h"
24#include "cfg.h" 20#include "cfg.h"
25#include "debugfs.h" 21#include "debugfs.h"
26#include "scan.h"
27#include "assoc.h"
28#include "cmd.h" 22#include "cmd.h"
29 23
30#define DRIVER_RELEASE_VERSION "323.p0" 24#define DRIVER_RELEASE_VERSION "323.p0"
@@ -96,72 +90,6 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
96} 90}
97 91
98 92
99static int lbs_add_rtap(struct lbs_private *priv);
100static void lbs_remove_rtap(struct lbs_private *priv);
101
102
103/**
104 * Get function for sysfs attribute rtap
105 */
106static ssize_t lbs_rtap_get(struct device *dev,
107 struct device_attribute *attr, char * buf)
108{
109 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
110 return snprintf(buf, 5, "0x%X\n", priv->monitormode);
111}
112
113/**
114 * Set function for sysfs attribute rtap
115 */
116static ssize_t lbs_rtap_set(struct device *dev,
117 struct device_attribute *attr, const char * buf, size_t count)
118{
119 int monitor_mode;
120 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
121
122 sscanf(buf, "%x", &monitor_mode);
123 if (monitor_mode) {
124 if (priv->monitormode == monitor_mode)
125 return strlen(buf);
126 if (!priv->monitormode) {
127 if (priv->infra_open || lbs_mesh_open(priv))
128 return -EBUSY;
129 if (priv->mode == IW_MODE_INFRA)
130 lbs_cmd_80211_deauthenticate(priv,
131 priv->curbssparams.bssid,
132 WLAN_REASON_DEAUTH_LEAVING);
133 else if (priv->mode == IW_MODE_ADHOC)
134 lbs_adhoc_stop(priv);
135 lbs_add_rtap(priv);
136 }
137 priv->monitormode = monitor_mode;
138 } else {
139 if (!priv->monitormode)
140 return strlen(buf);
141 priv->monitormode = 0;
142 lbs_remove_rtap(priv);
143
144 if (priv->currenttxskb) {
145 dev_kfree_skb_any(priv->currenttxskb);
146 priv->currenttxskb = NULL;
147 }
148
149 /* Wake queues, command thread, etc. */
150 lbs_host_to_card_done(priv);
151 }
152
153 lbs_prepare_and_send_command(priv,
154 CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
155 CMD_OPTION_WAITFORRSP, 0, &priv->monitormode);
156 return strlen(buf);
157}
158
159/**
160 * lbs_rtap attribute to be exported per ethX interface
161 * through sysfs (/sys/class/net/ethX/lbs_rtap)
162 */
163static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
164
165/** 93/**
166 * @brief This function opens the ethX interface 94 * @brief This function opens the ethX interface
167 * 95 *
@@ -177,13 +105,6 @@ static int lbs_dev_open(struct net_device *dev)
177 105
178 spin_lock_irq(&priv->driver_lock); 106 spin_lock_irq(&priv->driver_lock);
179 107
180 if (priv->monitormode) {
181 ret = -EBUSY;
182 goto out;
183 }
184
185 priv->infra_open = 1;
186
187 if (priv->connect_status == LBS_CONNECTED) 108 if (priv->connect_status == LBS_CONNECTED)
188 netif_carrier_on(dev); 109 netif_carrier_on(dev);
189 else 110 else
@@ -191,7 +112,6 @@ static int lbs_dev_open(struct net_device *dev)
191 112
192 if (!priv->tx_pending_len) 113 if (!priv->tx_pending_len)
193 netif_wake_queue(dev); 114 netif_wake_queue(dev);
194 out:
195 115
196 spin_unlock_irq(&priv->driver_lock); 116 spin_unlock_irq(&priv->driver_lock);
197 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); 117 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
@@ -211,7 +131,6 @@ static int lbs_eth_stop(struct net_device *dev)
211 lbs_deb_enter(LBS_DEB_NET); 131 lbs_deb_enter(LBS_DEB_NET);
212 132
213 spin_lock_irq(&priv->driver_lock); 133 spin_lock_irq(&priv->driver_lock);
214 priv->infra_open = 0;
215 netif_stop_queue(dev); 134 netif_stop_queue(dev);
216 spin_unlock_irq(&priv->driver_lock); 135 spin_unlock_irq(&priv->driver_lock);
217 136
@@ -733,6 +652,9 @@ static int lbs_setup_firmware(struct lbs_private *priv)
733 priv->txpower_max = maxlevel; 652 priv->txpower_max = maxlevel;
734 } 653 }
735 654
655 /* Send cmd to FW to enable 11D function */
656 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
657
736 lbs_set_mac_control(priv); 658 lbs_set_mac_control(priv);
737done: 659done:
738 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 660 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
@@ -822,37 +744,16 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
822 744
823static int lbs_init_adapter(struct lbs_private *priv) 745static int lbs_init_adapter(struct lbs_private *priv)
824{ 746{
825 size_t bufsize; 747 int ret;
826 int i, ret = 0;
827 748
828 lbs_deb_enter(LBS_DEB_MAIN); 749 lbs_deb_enter(LBS_DEB_MAIN);
829 750
830 /* Allocate buffer to store the BSSID list */
831 bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
832 priv->networks = kzalloc(bufsize, GFP_KERNEL);
833 if (!priv->networks) {
834 lbs_pr_err("Out of memory allocating beacons\n");
835 ret = -1;
836 goto out;
837 }
838
839 /* Initialize scan result lists */
840 INIT_LIST_HEAD(&priv->network_free_list);
841 INIT_LIST_HEAD(&priv->network_list);
842 for (i = 0; i < MAX_NETWORK_COUNT; i++) {
843 list_add_tail(&priv->networks[i].list,
844 &priv->network_free_list);
845 }
846
847 memset(priv->current_addr, 0xff, ETH_ALEN); 751 memset(priv->current_addr, 0xff, ETH_ALEN);
848 752
849 priv->connect_status = LBS_DISCONNECTED; 753 priv->connect_status = LBS_DISCONNECTED;
850 priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
851 priv->mode = IW_MODE_INFRA;
852 priv->channel = DEFAULT_AD_HOC_CHANNEL; 754 priv->channel = DEFAULT_AD_HOC_CHANNEL;
853 priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; 755 priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
854 priv->radio_on = 1; 756 priv->radio_on = 1;
855 priv->enablehwauto = 1;
856 priv->psmode = LBS802_11POWERMODECAM; 757 priv->psmode = LBS802_11POWERMODECAM;
857 priv->psstate = PS_STATE_FULL_POWER; 758 priv->psstate = PS_STATE_FULL_POWER;
858 priv->is_deep_sleep = 0; 759 priv->is_deep_sleep = 0;
@@ -907,8 +808,6 @@ static void lbs_free_adapter(struct lbs_private *priv)
907 kfifo_free(&priv->event_fifo); 808 kfifo_free(&priv->event_fifo);
908 del_timer(&priv->command_timer); 809 del_timer(&priv->command_timer);
909 del_timer(&priv->auto_deepsleep_timer); 810 del_timer(&priv->auto_deepsleep_timer);
910 kfree(priv->networks);
911 priv->networks = NULL;
912 811
913 lbs_deb_leave(LBS_DEB_MAIN); 812 lbs_deb_leave(LBS_DEB_MAIN);
914} 813}
@@ -945,7 +844,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
945 lbs_pr_err("cfg80211 init failed\n"); 844 lbs_pr_err("cfg80211 init failed\n");
946 goto done; 845 goto done;
947 } 846 }
948 /* TODO? */ 847
949 wdev->iftype = NL80211_IFTYPE_STATION; 848 wdev->iftype = NL80211_IFTYPE_STATION;
950 priv = wdev_priv(wdev); 849 priv = wdev_priv(wdev);
951 priv->wdev = wdev; 850 priv->wdev = wdev;
@@ -955,7 +854,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
955 goto err_wdev; 854 goto err_wdev;
956 } 855 }
957 856
958 //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
959 dev = alloc_netdev(0, "wlan%d", ether_setup); 857 dev = alloc_netdev(0, "wlan%d", ether_setup);
960 if (!dev) { 858 if (!dev) {
961 dev_err(dmdev, "no memory for network device instance\n"); 859 dev_err(dmdev, "no memory for network device instance\n");
@@ -971,20 +869,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
971 dev->netdev_ops = &lbs_netdev_ops; 869 dev->netdev_ops = &lbs_netdev_ops;
972 dev->watchdog_timeo = 5 * HZ; 870 dev->watchdog_timeo = 5 * HZ;
973 dev->ethtool_ops = &lbs_ethtool_ops; 871 dev->ethtool_ops = &lbs_ethtool_ops;
974#ifdef WIRELESS_EXT
975 dev->wireless_handlers = &lbs_handler_def;
976#endif
977 dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 872 dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
978 873
979
980 // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
981
982
983 priv->card = card; 874 priv->card = card;
984 priv->infra_open = 0;
985
986 875
987 priv->rtap_net_dev = NULL;
988 strcpy(dev->name, "wlan%d"); 876 strcpy(dev->name, "wlan%d");
989 877
990 lbs_deb_thread("Starting main thread...\n"); 878 lbs_deb_thread("Starting main thread...\n");
@@ -996,8 +884,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
996 } 884 }
997 885
998 priv->work_thread = create_singlethread_workqueue("lbs_worker"); 886 priv->work_thread = create_singlethread_workqueue("lbs_worker");
999 INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
1000 INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
1001 INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); 887 INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
1002 888
1003 priv->wol_criteria = 0xffffffff; 889 priv->wol_criteria = 0xffffffff;
@@ -1031,12 +917,10 @@ void lbs_remove_card(struct lbs_private *priv)
1031 lbs_deb_enter(LBS_DEB_MAIN); 917 lbs_deb_enter(LBS_DEB_MAIN);
1032 918
1033 lbs_remove_mesh(priv); 919 lbs_remove_mesh(priv);
1034 lbs_remove_rtap(priv); 920 lbs_scan_deinit(priv);
1035 921
1036 dev = priv->dev; 922 dev = priv->dev;
1037 923
1038 cancel_delayed_work_sync(&priv->scan_work);
1039 cancel_delayed_work_sync(&priv->assoc_work);
1040 cancel_work_sync(&priv->mcast_work); 924 cancel_work_sync(&priv->mcast_work);
1041 925
1042 /* worker thread destruction blocks on the in-flight command which 926 /* worker thread destruction blocks on the in-flight command which
@@ -1051,8 +935,6 @@ void lbs_remove_card(struct lbs_private *priv)
1051 lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); 935 lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
1052 } 936 }
1053 937
1054 lbs_send_disconnect_notification(priv);
1055
1056 if (priv->is_deep_sleep) { 938 if (priv->is_deep_sleep) {
1057 priv->is_deep_sleep = 0; 939 priv->is_deep_sleep = 0;
1058 wake_up_interruptible(&priv->ds_awake_q); 940 wake_up_interruptible(&priv->ds_awake_q);
@@ -1077,7 +959,7 @@ void lbs_remove_card(struct lbs_private *priv)
1077EXPORT_SYMBOL_GPL(lbs_remove_card); 959EXPORT_SYMBOL_GPL(lbs_remove_card);
1078 960
1079 961
1080static int lbs_rtap_supported(struct lbs_private *priv) 962int lbs_rtap_supported(struct lbs_private *priv)
1081{ 963{
1082 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) 964 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
1083 return 1; 965 return 1;
@@ -1109,16 +991,6 @@ int lbs_start_card(struct lbs_private *priv)
1109 991
1110 lbs_init_mesh(priv); 992 lbs_init_mesh(priv);
1111 993
1112 /*
1113 * While rtap isn't related to mesh, only mesh-enabled
1114 * firmware implements the rtap functionality via
1115 * CMD_802_11_MONITOR_MODE.
1116 */
1117 if (lbs_rtap_supported(priv)) {
1118 if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
1119 lbs_pr_err("cannot register lbs_rtap attribute\n");
1120 }
1121
1122 lbs_debugfs_init_one(priv, dev); 994 lbs_debugfs_init_one(priv, dev);
1123 995
1124 lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); 996 lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
@@ -1150,9 +1022,6 @@ void lbs_stop_card(struct lbs_private *priv)
1150 lbs_debugfs_remove_one(priv); 1022 lbs_debugfs_remove_one(priv);
1151 lbs_deinit_mesh(priv); 1023 lbs_deinit_mesh(priv);
1152 1024
1153 if (lbs_rtap_supported(priv))
1154 device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
1155
1156 /* Delete the timeout of the currently processing command */ 1025 /* Delete the timeout of the currently processing command */
1157 del_timer_sync(&priv->command_timer); 1026 del_timer_sync(&priv->command_timer);
1158 del_timer_sync(&priv->auto_deepsleep_timer); 1027 del_timer_sync(&priv->auto_deepsleep_timer);
@@ -1239,87 +1108,6 @@ static void __exit lbs_exit_module(void)
1239 lbs_deb_leave(LBS_DEB_MAIN); 1108 lbs_deb_leave(LBS_DEB_MAIN);
1240} 1109}
1241 1110
1242/*
1243 * rtap interface support fuctions
1244 */
1245
1246static int lbs_rtap_open(struct net_device *dev)
1247{
1248 /* Yes, _stop_ the queue. Because we don't support injection */
1249 lbs_deb_enter(LBS_DEB_MAIN);
1250 netif_carrier_off(dev);
1251 netif_stop_queue(dev);
1252 lbs_deb_leave(LBS_DEB_LEAVE);
1253 return 0;
1254}
1255
1256static int lbs_rtap_stop(struct net_device *dev)
1257{
1258 lbs_deb_enter(LBS_DEB_MAIN);
1259 lbs_deb_leave(LBS_DEB_MAIN);
1260 return 0;
1261}
1262
1263static netdev_tx_t lbs_rtap_hard_start_xmit(struct sk_buff *skb,
1264 struct net_device *dev)
1265{
1266 netif_stop_queue(dev);
1267 return NETDEV_TX_BUSY;
1268}
1269
1270static void lbs_remove_rtap(struct lbs_private *priv)
1271{
1272 lbs_deb_enter(LBS_DEB_MAIN);
1273 if (priv->rtap_net_dev == NULL)
1274 goto out;
1275 unregister_netdev(priv->rtap_net_dev);
1276 free_netdev(priv->rtap_net_dev);
1277 priv->rtap_net_dev = NULL;
1278out:
1279 lbs_deb_leave(LBS_DEB_MAIN);
1280}
1281
1282static const struct net_device_ops rtap_netdev_ops = {
1283 .ndo_open = lbs_rtap_open,
1284 .ndo_stop = lbs_rtap_stop,
1285 .ndo_start_xmit = lbs_rtap_hard_start_xmit,
1286};
1287
1288static int lbs_add_rtap(struct lbs_private *priv)
1289{
1290 int ret = 0;
1291 struct net_device *rtap_dev;
1292
1293 lbs_deb_enter(LBS_DEB_MAIN);
1294 if (priv->rtap_net_dev) {
1295 ret = -EPERM;
1296 goto out;
1297 }
1298
1299 rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
1300 if (rtap_dev == NULL) {
1301 ret = -ENOMEM;
1302 goto out;
1303 }
1304
1305 memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
1306 rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
1307 rtap_dev->netdev_ops = &rtap_netdev_ops;
1308 rtap_dev->ml_priv = priv;
1309 SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
1310
1311 ret = register_netdev(rtap_dev);
1312 if (ret) {
1313 free_netdev(rtap_dev);
1314 goto out;
1315 }
1316 priv->rtap_net_dev = rtap_dev;
1317
1318out:
1319 lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
1320 return ret;
1321}
1322
1323module_init(lbs_init_module); 1111module_init(lbs_init_module);
1324module_exit(lbs_exit_module); 1112module_exit(lbs_exit_module);
1325 1113
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index e385af1f4583..bc5bc1384c35 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -5,6 +5,7 @@
5#include <linux/if_arp.h> 5#include <linux/if_arp.h>
6#include <linux/kthread.h> 6#include <linux/kthread.h>
7#include <linux/kfifo.h> 7#include <linux/kfifo.h>
8#include <net/cfg80211.h>
8 9
9#include "mesh.h" 10#include "mesh.h"
10#include "decl.h" 11#include "decl.h"
@@ -314,7 +315,7 @@ static int lbs_mesh_dev_open(struct net_device *dev)
314 315
315 spin_lock_irq(&priv->driver_lock); 316 spin_lock_irq(&priv->driver_lock);
316 317
317 if (priv->monitormode) { 318 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
318 ret = -EBUSY; 319 ret = -EBUSY;
319 goto out; 320 goto out;
320 } 321 }
@@ -369,9 +370,6 @@ int lbs_add_mesh(struct lbs_private *priv)
369 370
370 SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); 371 SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
371 372
372#ifdef WIRELESS_EXT
373 mesh_dev->wireless_handlers = &mesh_handler_def;
374#endif
375 mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 373 mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
376 /* Register virtual mesh interface */ 374 /* Register virtual mesh interface */
377 ret = register_netdev(mesh_dev); 375 ret = register_netdev(mesh_dev);
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index e2573303a328..84ea2481ff20 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -70,11 +70,6 @@ void lbs_persist_config_init(struct net_device *net);
70void lbs_persist_config_remove(struct net_device *net); 70void lbs_persist_config_remove(struct net_device *net);
71 71
72 72
73/* WEXT handler */
74
75extern struct iw_handler_def mesh_handler_def;
76
77
78/* Ethtool statistics */ 73/* Ethtool statistics */
79 74
80struct ethtool_stats; 75struct ethtool_stats;
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 1c63f8ce7349..a4d0bca9ef2c 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -4,12 +4,13 @@
4#include <linux/etherdevice.h> 4#include <linux/etherdevice.h>
5#include <linux/slab.h> 5#include <linux/slab.h>
6#include <linux/types.h> 6#include <linux/types.h>
7#include <net/cfg80211.h>
7 8
9#include "defs.h"
8#include "host.h" 10#include "host.h"
9#include "radiotap.h" 11#include "radiotap.h"
10#include "decl.h" 12#include "decl.h"
11#include "dev.h" 13#include "dev.h"
12#include "wext.h"
13 14
14struct eth803hdr { 15struct eth803hdr {
15 u8 dest_addr[6]; 16 u8 dest_addr[6];
@@ -39,98 +40,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
39 struct sk_buff *skb); 40 struct sk_buff *skb);
40 41
41/** 42/**
42 * @brief This function computes the avgSNR .
43 *
44 * @param priv A pointer to struct lbs_private structure
45 * @return avgSNR
46 */
47static u8 lbs_getavgsnr(struct lbs_private *priv)
48{
49 u8 i;
50 u16 temp = 0;
51 if (priv->numSNRNF == 0)
52 return 0;
53 for (i = 0; i < priv->numSNRNF; i++)
54 temp += priv->rawSNR[i];
55 return (u8) (temp / priv->numSNRNF);
56
57}
58
59/**
60 * @brief This function computes the AvgNF
61 *
62 * @param priv A pointer to struct lbs_private structure
63 * @return AvgNF
64 */
65static u8 lbs_getavgnf(struct lbs_private *priv)
66{
67 u8 i;
68 u16 temp = 0;
69 if (priv->numSNRNF == 0)
70 return 0;
71 for (i = 0; i < priv->numSNRNF; i++)
72 temp += priv->rawNF[i];
73 return (u8) (temp / priv->numSNRNF);
74
75}
76
77/**
78 * @brief This function save the raw SNR/NF to our internel buffer
79 *
80 * @param priv A pointer to struct lbs_private structure
81 * @param prxpd A pointer to rxpd structure of received packet
82 * @return n/a
83 */
84static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
85{
86 if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
87 priv->numSNRNF++;
88 priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr;
89 priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf;
90 priv->nextSNRNF++;
91 if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
92 priv->nextSNRNF = 0;
93}
94
95/**
96 * @brief This function computes the RSSI in received packet.
97 *
98 * @param priv A pointer to struct lbs_private structure
99 * @param prxpd A pointer to rxpd structure of received packet
100 * @return n/a
101 */
102static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
103{
104
105 lbs_deb_enter(LBS_DEB_RX);
106
107 lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
108 lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
109 priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
110 priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
111
112 priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
113 priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
114 lbs_save_rawSNRNF(priv, p_rx_pd);
115
116 priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE;
117 priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE;
118 lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
119 priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
120 priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
121
122 priv->RSSI[TYPE_RXPD][TYPE_NOAVG] =
123 CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG],
124 priv->NF[TYPE_RXPD][TYPE_NOAVG]);
125
126 priv->RSSI[TYPE_RXPD][TYPE_AVG] =
127 CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
128 priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
129
130 lbs_deb_leave(LBS_DEB_RX);
131}
132
133/**
134 * @brief This function processes received packet and forwards it 43 * @brief This function processes received packet and forwards it
135 * to kernel/upper layer 44 * to kernel/upper layer
136 * 45 *
@@ -154,7 +63,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
154 63
155 skb->ip_summed = CHECKSUM_NONE; 64 skb->ip_summed = CHECKSUM_NONE;
156 65
157 if (priv->monitormode) 66 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
158 return process_rxed_802_11_packet(priv, skb); 67 return process_rxed_802_11_packet(priv, skb);
159 68
160 p_rx_pd = (struct rxpd *) skb->data; 69 p_rx_pd = (struct rxpd *) skb->data;
@@ -225,13 +134,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
225 */ 134 */
226 skb_pull(skb, hdrchop); 135 skb_pull(skb, hdrchop);
227 136
228 /* Take the data rate from the rxpd structure 137 priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
229 * only if the rate is auto
230 */
231 if (priv->enablehwauto)
232 priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
233
234 lbs_compute_rssi(priv, p_rx_pd);
235 138
236 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); 139 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
237 dev->stats.rx_bytes += skb->len; 140 dev->stats.rx_bytes += skb->len;
@@ -352,20 +255,18 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
352 pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr)); 255 pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
353 memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr)); 256 memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
354 257
355 /* Take the data rate from the rxpd structure 258 priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
356 * only if the rate is auto
357 */
358 if (priv->enablehwauto)
359 priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
360
361 lbs_compute_rssi(priv, prxpd);
362 259
363 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); 260 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
364 dev->stats.rx_bytes += skb->len; 261 dev->stats.rx_bytes += skb->len;
365 dev->stats.rx_packets++; 262 dev->stats.rx_packets++;
366 263
367 skb->protocol = eth_type_trans(skb, priv->rtap_net_dev); 264 skb->protocol = eth_type_trans(skb, priv->dev);
368 netif_rx(skb); 265
266 if (in_interrupt())
267 netif_rx(skb);
268 else
269 netif_rx_ni(skb);
369 270
370 ret = 0; 271 ret = 0;
371 272
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
deleted file mode 100644
index 7d82f13bdf1d..000000000000
--- a/drivers/net/wireless/libertas/scan.c
+++ /dev/null
@@ -1,1354 +0,0 @@
1/**
2 * Functions implementing wlan scan IOCTL and firmware command APIs
3 *
4 * IOCTL handlers as well as command preperation and response routines
5 * for sending scan commands to the firmware.
6 */
7#include <linux/slab.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/etherdevice.h>
11#include <linux/if_arp.h>
12#include <asm/unaligned.h>
13#include <net/lib80211.h>
14
15#include "host.h"
16#include "dev.h"
17#include "scan.h"
18#include "assoc.h"
19#include "wext.h"
20#include "cmd.h"
21
22//! Approximate amount of data needed to pass a scan result back to iwlist
23#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
24 + IEEE80211_MAX_SSID_LEN \
25 + IW_EV_UINT_LEN \
26 + IW_EV_FREQ_LEN \
27 + IW_EV_QUAL_LEN \
28 + IEEE80211_MAX_SSID_LEN \
29 + IW_EV_PARAM_LEN \
30 + 40) /* 40 for WPAIE */
31
32//! Memory needed to store a max sized channel List TLV for a firmware scan
33#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvl_ie_header) \
34 + (MRVDRV_MAX_CHANNELS_PER_SCAN \
35 * sizeof(struct chanscanparamset)))
36
37//! Memory needed to store a max number/size SSID TLV for a firmware scan
38#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvl_ie_ssid_param_set))
39
40//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
41#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \
42 + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE)
43
44//! The maximum number of channels the firmware can scan per command
45#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
46
47/**
48 * @brief Number of channels to scan per firmware scan command issuance.
49 *
50 * Number restricted to prevent hitting the limit on the amount of scan data
51 * returned in a single firmware scan command.
52 */
53#define MRVDRV_CHANNELS_PER_SCAN_CMD 4
54
55//! Scan time specified in the channel TLV for each channel for passive scans
56#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100
57
58//! Scan time specified in the channel TLV for each channel for active scans
59#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
60
61#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
62
63static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
64 struct cmd_header *resp);
65
66/*********************************************************************/
67/* */
68/* Misc helper functions */
69/* */
70/*********************************************************************/
71
72/**
73 * @brief Unsets the MSB on basic rates
74 *
75 * Scan through an array and unset the MSB for basic data rates.
76 *
77 * @param rates buffer of data rates
78 * @param len size of buffer
79 */
80static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
81{
82 int i;
83
84 for (i = 0; i < len; i++)
85 rates[i] &= 0x7f;
86}
87
88
89static inline void clear_bss_descriptor(struct bss_descriptor *bss)
90{
91 /* Don't blow away ->list, just BSS data */
92 memset(bss, 0, offsetof(struct bss_descriptor, list));
93}
94
95/**
96 * @brief Compare two SSIDs
97 *
98 * @param ssid1 A pointer to ssid to compare
99 * @param ssid2 A pointer to ssid to compare
100 *
101 * @return 0: ssid is same, otherwise is different
102 */
103int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
104 uint8_t ssid2_len)
105{
106 if (ssid1_len != ssid2_len)
107 return -1;
108
109 return memcmp(ssid1, ssid2, ssid1_len);
110}
111
112static inline int is_same_network(struct bss_descriptor *src,
113 struct bss_descriptor *dst)
114{
115 /* A network is only a duplicate if the channel, BSSID, and ESSID
116 * all match. We treat all <hidden> with the same BSSID and channel
117 * as one network */
118 return ((src->ssid_len == dst->ssid_len) &&
119 (src->channel == dst->channel) &&
120 !compare_ether_addr(src->bssid, dst->bssid) &&
121 !memcmp(src->ssid, dst->ssid, src->ssid_len));
122}
123
124
125
126/*********************************************************************/
127/* */
128/* Region channel support */
129/* */
130/*********************************************************************/
131
132#define LBS_TX_PWR_DEFAULT 20 /*100mW */
133#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
134#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
135#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */
136#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */
137
138/* Format { channel, frequency (MHz), maxtxpower } */
139/* band: 'B/G', region: USA FCC/Canada IC */
140static struct chan_freq_power channel_freq_power_US_BG[] = {
141 {1, 2412, LBS_TX_PWR_US_DEFAULT},
142 {2, 2417, LBS_TX_PWR_US_DEFAULT},
143 {3, 2422, LBS_TX_PWR_US_DEFAULT},
144 {4, 2427, LBS_TX_PWR_US_DEFAULT},
145 {5, 2432, LBS_TX_PWR_US_DEFAULT},
146 {6, 2437, LBS_TX_PWR_US_DEFAULT},
147 {7, 2442, LBS_TX_PWR_US_DEFAULT},
148 {8, 2447, LBS_TX_PWR_US_DEFAULT},
149 {9, 2452, LBS_TX_PWR_US_DEFAULT},
150 {10, 2457, LBS_TX_PWR_US_DEFAULT},
151 {11, 2462, LBS_TX_PWR_US_DEFAULT}
152};
153
154/* band: 'B/G', region: Europe ETSI */
155static struct chan_freq_power channel_freq_power_EU_BG[] = {
156 {1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
157 {2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
158 {3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
159 {4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
160 {5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
161 {6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
162 {7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
163 {8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
164 {9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
165 {10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
166 {11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
167 {12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
168 {13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
169};
170
171/* band: 'B/G', region: Spain */
172static struct chan_freq_power channel_freq_power_SPN_BG[] = {
173 {10, 2457, LBS_TX_PWR_DEFAULT},
174 {11, 2462, LBS_TX_PWR_DEFAULT}
175};
176
177/* band: 'B/G', region: France */
178static struct chan_freq_power channel_freq_power_FR_BG[] = {
179 {10, 2457, LBS_TX_PWR_FR_DEFAULT},
180 {11, 2462, LBS_TX_PWR_FR_DEFAULT},
181 {12, 2467, LBS_TX_PWR_FR_DEFAULT},
182 {13, 2472, LBS_TX_PWR_FR_DEFAULT}
183};
184
185/* band: 'B/G', region: Japan */
186static struct chan_freq_power channel_freq_power_JPN_BG[] = {
187 {1, 2412, LBS_TX_PWR_JP_DEFAULT},
188 {2, 2417, LBS_TX_PWR_JP_DEFAULT},
189 {3, 2422, LBS_TX_PWR_JP_DEFAULT},
190 {4, 2427, LBS_TX_PWR_JP_DEFAULT},
191 {5, 2432, LBS_TX_PWR_JP_DEFAULT},
192 {6, 2437, LBS_TX_PWR_JP_DEFAULT},
193 {7, 2442, LBS_TX_PWR_JP_DEFAULT},
194 {8, 2447, LBS_TX_PWR_JP_DEFAULT},
195 {9, 2452, LBS_TX_PWR_JP_DEFAULT},
196 {10, 2457, LBS_TX_PWR_JP_DEFAULT},
197 {11, 2462, LBS_TX_PWR_JP_DEFAULT},
198 {12, 2467, LBS_TX_PWR_JP_DEFAULT},
199 {13, 2472, LBS_TX_PWR_JP_DEFAULT},
200 {14, 2484, LBS_TX_PWR_JP_DEFAULT}
201};
202
203/**
204 * the structure for channel, frequency and power
205 */
206struct region_cfp_table {
207 u8 region;
208 struct chan_freq_power *cfp_BG;
209 int cfp_no_BG;
210};
211
212/**
213 * the structure for the mapping between region and CFP
214 */
215static struct region_cfp_table region_cfp_table[] = {
216 {0x10, /*US FCC */
217 channel_freq_power_US_BG,
218 ARRAY_SIZE(channel_freq_power_US_BG),
219 }
220 ,
221 {0x20, /*CANADA IC */
222 channel_freq_power_US_BG,
223 ARRAY_SIZE(channel_freq_power_US_BG),
224 }
225 ,
226 {0x30, /*EU*/ channel_freq_power_EU_BG,
227 ARRAY_SIZE(channel_freq_power_EU_BG),
228 }
229 ,
230 {0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
231 ARRAY_SIZE(channel_freq_power_SPN_BG),
232 }
233 ,
234 {0x32, /*FRANCE*/ channel_freq_power_FR_BG,
235 ARRAY_SIZE(channel_freq_power_FR_BG),
236 }
237 ,
238 {0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
239 ARRAY_SIZE(channel_freq_power_JPN_BG),
240 }
241 ,
242/*Add new region here */
243};
244
245/**
246 * @brief This function finds the CFP in
247 * region_cfp_table based on region and band parameter.
248 *
249 * @param region The region code
250 * @param band The band
251 * @param cfp_no A pointer to CFP number
252 * @return A pointer to CFP
253 */
254static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
255{
256 int i, end;
257
258 lbs_deb_enter(LBS_DEB_MAIN);
259
260 end = ARRAY_SIZE(region_cfp_table);
261
262 for (i = 0; i < end ; i++) {
263 lbs_deb_main("region_cfp_table[i].region=%d\n",
264 region_cfp_table[i].region);
265 if (region_cfp_table[i].region == region) {
266 *cfp_no = region_cfp_table[i].cfp_no_BG;
267 lbs_deb_leave(LBS_DEB_MAIN);
268 return region_cfp_table[i].cfp_BG;
269 }
270 }
271
272 lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
273 return NULL;
274}
275
276int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
277{
278 int ret = 0;
279 int i = 0;
280
281 struct chan_freq_power *cfp;
282 int cfp_no;
283
284 lbs_deb_enter(LBS_DEB_MAIN);
285
286 memset(priv->region_channel, 0, sizeof(priv->region_channel));
287
288 cfp = lbs_get_region_cfp_table(region, &cfp_no);
289 if (cfp != NULL) {
290 priv->region_channel[i].nrcfp = cfp_no;
291 priv->region_channel[i].CFP = cfp;
292 } else {
293 lbs_deb_main("wrong region code %#x in band B/G\n",
294 region);
295 ret = -1;
296 goto out;
297 }
298 priv->region_channel[i].valid = 1;
299 priv->region_channel[i].region = region;
300 priv->region_channel[i].band = band;
301 i++;
302out:
303 lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
304 return ret;
305}
306
307
308
309
310/*********************************************************************/
311/* */
312/* Main scanning support */
313/* */
314/*********************************************************************/
315
316/**
317 * @brief Create a channel list for the driver to scan based on region info
318 *
319 * Only used from lbs_scan_setup_scan_config()
320 *
321 * Use the driver region/band information to construct a comprehensive list
322 * of channels to scan. This routine is used for any scan that is not
323 * provided a specific channel list to scan.
324 *
325 * @param priv A pointer to struct lbs_private structure
326 * @param scanchanlist Output parameter: resulting channel list to scan
327 *
328 * @return void
329 */
330static int lbs_scan_create_channel_list(struct lbs_private *priv,
331 struct chanscanparamset *scanchanlist)
332{
333 struct region_channel *scanregion;
334 struct chan_freq_power *cfp;
335 int rgnidx;
336 int chanidx;
337 int nextchan;
338 uint8_t scantype;
339
340 chanidx = 0;
341
342 /* Set the default scan type to the user specified type, will later
343 * be changed to passive on a per channel basis if restricted by
344 * regulatory requirements (11d or 11h)
345 */
346 scantype = CMD_SCAN_TYPE_ACTIVE;
347
348 for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
349 if (!priv->region_channel[rgnidx].valid)
350 continue;
351 scanregion = &priv->region_channel[rgnidx];
352
353 for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
354 struct chanscanparamset *chan = &scanchanlist[chanidx];
355
356 cfp = scanregion->CFP + nextchan;
357
358 if (scanregion->band == BAND_B || scanregion->band == BAND_G)
359 chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
360
361 if (scantype == CMD_SCAN_TYPE_PASSIVE) {
362 chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
363 chan->chanscanmode.passivescan = 1;
364 } else {
365 chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
366 chan->chanscanmode.passivescan = 0;
367 }
368
369 chan->channumber = cfp->channel;
370 }
371 }
372 return chanidx;
373}
374
375/*
376 * Add SSID TLV of the form:
377 *
378 * TLV-ID SSID 00 00
379 * length 06 00
380 * ssid 4d 4e 54 45 53 54
381 */
382static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
383{
384 struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv;
385
386 ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
387 ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
388 memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
389 return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
390}
391
392/*
393 * Add CHANLIST TLV of the form
394 *
395 * TLV-ID CHANLIST 01 01
396 * length 5b 00
397 * channel 1 00 01 00 00 00 64 00
398 * radio type 00
399 * channel 01
400 * scan type 00
401 * min scan time 00 00
402 * max scan time 64 00
403 * channel 2 00 02 00 00 00 64 00
404 * channel 3 00 03 00 00 00 64 00
405 * channel 4 00 04 00 00 00 64 00
406 * channel 5 00 05 00 00 00 64 00
407 * channel 6 00 06 00 00 00 64 00
408 * channel 7 00 07 00 00 00 64 00
409 * channel 8 00 08 00 00 00 64 00
410 * channel 9 00 09 00 00 00 64 00
411 * channel 10 00 0a 00 00 00 64 00
412 * channel 11 00 0b 00 00 00 64 00
413 * channel 12 00 0c 00 00 00 64 00
414 * channel 13 00 0d 00 00 00 64 00
415 *
416 */
417static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
418 struct chanscanparamset *chan_list,
419 int chan_count)
420{
421 size_t size = sizeof(struct chanscanparamset) *chan_count;
422 struct mrvl_ie_chanlist_param_set *chan_tlv = (void *)tlv;
423
424 chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
425 memcpy(chan_tlv->chanscanparam, chan_list, size);
426 chan_tlv->header.len = cpu_to_le16(size);
427 return sizeof(chan_tlv->header) + size;
428}
429
430/*
431 * Add RATES TLV of the form
432 *
433 * TLV-ID RATES 01 00
434 * length 0e 00
435 * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c
436 *
437 * The rates are in lbs_bg_rates[], but for the 802.11b
438 * rates the high bit isn't set.
439 */
440static int lbs_scan_add_rates_tlv(uint8_t *tlv)
441{
442 int i;
443 struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
444
445 rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
446 tlv += sizeof(rate_tlv->header);
447 for (i = 0; i < MAX_RATES; i++) {
448 *tlv = lbs_bg_rates[i];
449 if (*tlv == 0)
450 break;
451 /* This code makes sure that the 802.11b rates (1 MBit/s, 2
452 MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set.
453 Note that the values are MBit/s * 2, to mark them as
454 basic rates so that the firmware likes it better */
455 if (*tlv == 0x02 || *tlv == 0x04 ||
456 *tlv == 0x0b || *tlv == 0x16)
457 *tlv |= 0x80;
458 tlv++;
459 }
460 rate_tlv->header.len = cpu_to_le16(i);
461 return sizeof(rate_tlv->header) + i;
462}
463
464/*
465 * Generate the CMD_802_11_SCAN command with the proper tlv
466 * for a bunch of channels.
467 */
468static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
469 struct chanscanparamset *chan_list, int chan_count)
470{
471 int ret = -ENOMEM;
472 struct cmd_ds_802_11_scan *scan_cmd;
473 uint8_t *tlv; /* pointer into our current, growing TLV storage area */
474
475 lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d",
476 bsstype, chan_list ? chan_list[0].channumber : -1,
477 chan_count);
478
479 /* create the fixed part for scan command */
480 scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
481 if (scan_cmd == NULL)
482 goto out;
483
484 tlv = scan_cmd->tlvbuffer;
485 /* TODO: do we need to scan for a specific BSSID?
486 memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
487 scan_cmd->bsstype = bsstype;
488
489 /* add TLVs */
490 if (priv->scan_ssid_len)
491 tlv += lbs_scan_add_ssid_tlv(priv, tlv);
492 if (chan_list && chan_count)
493 tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
494 tlv += lbs_scan_add_rates_tlv(tlv);
495
496 /* This is the final data we are about to send */
497 scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd);
498 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
499 sizeof(*scan_cmd));
500 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
501 tlv - scan_cmd->tlvbuffer);
502
503 ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
504 le16_to_cpu(scan_cmd->hdr.size),
505 lbs_ret_80211_scan, 0);
506
507out:
508 kfree(scan_cmd);
509 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
510 return ret;
511}
512
513/**
514 * @brief Internal function used to start a scan based on an input config
515 *
516 * Use the input user scan configuration information when provided in
517 * order to send the appropriate scan commands to firmware to populate or
518 * update the internal driver scan table
519 *
520 * @param priv A pointer to struct lbs_private structure
521 * @param full_scan Do a full-scan (blocking)
522 *
523 * @return 0 or < 0 if error
524 */
525int lbs_scan_networks(struct lbs_private *priv, int full_scan)
526{
527 int ret = -ENOMEM;
528 struct chanscanparamset *chan_list;
529 struct chanscanparamset *curr_chans;
530 int chan_count;
531 uint8_t bsstype = CMD_BSS_TYPE_ANY;
532 int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
533 union iwreq_data wrqu;
534#ifdef CONFIG_LIBERTAS_DEBUG
535 struct bss_descriptor *iter;
536 int i = 0;
537 DECLARE_SSID_BUF(ssid);
538#endif
539
540 lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
541
542 /* Cancel any partial outstanding partial scans if this scan
543 * is a full scan.
544 */
545 if (full_scan && delayed_work_pending(&priv->scan_work))
546 cancel_delayed_work(&priv->scan_work);
547
548 /* User-specified bsstype or channel list
549 TODO: this can be implemented if some user-space application
550 need the feature. Formerly, it was accessible from debugfs,
551 but then nowhere used.
552 if (user_cfg) {
553 if (user_cfg->bsstype)
554 bsstype = user_cfg->bsstype;
555 } */
556
557 lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
558
559 /* Create list of channels to scan */
560 chan_list = kzalloc(sizeof(struct chanscanparamset) *
561 LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
562 if (!chan_list) {
563 lbs_pr_alert("SCAN: chan_list empty\n");
564 goto out;
565 }
566
567 /* We want to scan all channels */
568 chan_count = lbs_scan_create_channel_list(priv, chan_list);
569
570 netif_stop_queue(priv->dev);
571 if (priv->mesh_dev)
572 netif_stop_queue(priv->mesh_dev);
573
574 /* Prepare to continue an interrupted scan */
575 lbs_deb_scan("chan_count %d, scan_channel %d\n",
576 chan_count, priv->scan_channel);
577 curr_chans = chan_list;
578 /* advance channel list by already-scanned-channels */
579 if (priv->scan_channel > 0) {
580 curr_chans += priv->scan_channel;
581 chan_count -= priv->scan_channel;
582 }
583
584 /* Send scan command(s)
585 * numchannels contains the number of channels we should maximally scan
586 * chan_count is the total number of channels to scan
587 */
588
589 while (chan_count) {
590 int to_scan = min(numchannels, chan_count);
591 lbs_deb_scan("scanning %d of %d channels\n",
592 to_scan, chan_count);
593 ret = lbs_do_scan(priv, bsstype, curr_chans,
594 to_scan);
595 if (ret) {
596 lbs_pr_err("SCAN_CMD failed\n");
597 goto out2;
598 }
599 curr_chans += to_scan;
600 chan_count -= to_scan;
601
602 /* somehow schedule the next part of the scan */
603 if (chan_count && !full_scan &&
604 !priv->surpriseremoved) {
605 /* -1 marks just that we're currently scanning */
606 if (priv->scan_channel < 0)
607 priv->scan_channel = to_scan;
608 else
609 priv->scan_channel += to_scan;
610 cancel_delayed_work(&priv->scan_work);
611 queue_delayed_work(priv->work_thread, &priv->scan_work,
612 msecs_to_jiffies(300));
613 /* skip over GIWSCAN event */
614 goto out;
615 }
616
617 }
618 memset(&wrqu, 0, sizeof(union iwreq_data));
619 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
620
621#ifdef CONFIG_LIBERTAS_DEBUG
622 /* Dump the scan table */
623 mutex_lock(&priv->lock);
624 lbs_deb_scan("scan table:\n");
625 list_for_each_entry(iter, &priv->network_list, list)
626 lbs_deb_scan("%02d: BSSID %pM, RSSI %d, SSID '%s'\n",
627 i++, iter->bssid, iter->rssi,
628 print_ssid(ssid, iter->ssid, iter->ssid_len));
629 mutex_unlock(&priv->lock);
630#endif
631
632out2:
633 priv->scan_channel = 0;
634
635out:
636 if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
637 netif_wake_queue(priv->dev);
638
639 if (priv->mesh_dev && lbs_mesh_connected(priv) &&
640 !priv->tx_pending_len)
641 netif_wake_queue(priv->mesh_dev);
642
643 kfree(chan_list);
644
645 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
646 return ret;
647}
648
649void lbs_scan_worker(struct work_struct *work)
650{
651 struct lbs_private *priv =
652 container_of(work, struct lbs_private, scan_work.work);
653
654 lbs_deb_enter(LBS_DEB_SCAN);
655 lbs_scan_networks(priv, 0);
656 lbs_deb_leave(LBS_DEB_SCAN);
657}
658
659
660/*********************************************************************/
661/* */
662/* Result interpretation */
663/* */
664/*********************************************************************/
665
666/**
667 * @brief Interpret a BSS scan response returned from the firmware
668 *
669 * Parse the various fixed fields and IEs passed back for a BSS probe
670 * response or beacon from the scan command. Record information as needed
671 * in the scan table struct bss_descriptor for that entry.
672 *
673 * @param bss Output parameter: Pointer to the BSS Entry
674 *
675 * @return 0 or -1
676 */
677static int lbs_process_bss(struct bss_descriptor *bss,
678 uint8_t **pbeaconinfo, int *bytesleft)
679{
680 struct ieee_ie_fh_param_set *fh;
681 struct ieee_ie_ds_param_set *ds;
682 struct ieee_ie_cf_param_set *cf;
683 struct ieee_ie_ibss_param_set *ibss;
684 DECLARE_SSID_BUF(ssid);
685 uint8_t *pos, *end, *p;
686 uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
687 uint16_t beaconsize = 0;
688 int ret;
689
690 lbs_deb_enter(LBS_DEB_SCAN);
691
692 if (*bytesleft >= sizeof(beaconsize)) {
693 /* Extract & convert beacon size from the command buffer */
694 beaconsize = get_unaligned_le16(*pbeaconinfo);
695 *bytesleft -= sizeof(beaconsize);
696 *pbeaconinfo += sizeof(beaconsize);
697 }
698
699 if (beaconsize == 0 || beaconsize > *bytesleft) {
700 *pbeaconinfo += *bytesleft;
701 *bytesleft = 0;
702 ret = -1;
703 goto done;
704 }
705
706 /* Initialize the current working beacon pointer for this BSS iteration */
707 pos = *pbeaconinfo;
708 end = pos + beaconsize;
709
710 /* Advance the return beacon pointer past the current beacon */
711 *pbeaconinfo += beaconsize;
712 *bytesleft -= beaconsize;
713
714 memcpy(bss->bssid, pos, ETH_ALEN);
715 lbs_deb_scan("process_bss: BSSID %pM\n", bss->bssid);
716 pos += ETH_ALEN;
717
718 if ((end - pos) < 12) {
719 lbs_deb_scan("process_bss: Not enough bytes left\n");
720 ret = -1;
721 goto done;
722 }
723
724 /*
725 * next 4 fields are RSSI, time stamp, beacon interval,
726 * and capability information
727 */
728
729 /* RSSI is 1 byte long */
730 bss->rssi = *pos;
731 lbs_deb_scan("process_bss: RSSI %d\n", *pos);
732 pos++;
733
734 /* time stamp is 8 bytes long */
735 pos += 8;
736
737 /* beacon interval is 2 bytes long */
738 bss->beaconperiod = get_unaligned_le16(pos);
739 pos += 2;
740
741 /* capability information is 2 bytes long */
742 bss->capability = get_unaligned_le16(pos);
743 lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability);
744 pos += 2;
745
746 if (bss->capability & WLAN_CAPABILITY_PRIVACY)
747 lbs_deb_scan("process_bss: WEP enabled\n");
748 if (bss->capability & WLAN_CAPABILITY_IBSS)
749 bss->mode = IW_MODE_ADHOC;
750 else
751 bss->mode = IW_MODE_INFRA;
752
753 /* rest of the current buffer are IE's */
754 lbs_deb_scan("process_bss: IE len %zd\n", end - pos);
755 lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos);
756
757 /* process variable IE */
758 while (pos <= end - 2) {
759 if (pos + pos[1] > end) {
760 lbs_deb_scan("process_bss: error in processing IE, "
761 "bytes left < IE length\n");
762 break;
763 }
764
765 switch (pos[0]) {
766 case WLAN_EID_SSID:
767 bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]);
768 memcpy(bss->ssid, pos + 2, bss->ssid_len);
769 lbs_deb_scan("got SSID IE: '%s', len %u\n",
770 print_ssid(ssid, bss->ssid, bss->ssid_len),
771 bss->ssid_len);
772 break;
773
774 case WLAN_EID_SUPP_RATES:
775 n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]);
776 memcpy(bss->rates, pos + 2, n_basic_rates);
777 got_basic_rates = 1;
778 lbs_deb_scan("got RATES IE\n");
779 break;
780
781 case WLAN_EID_FH_PARAMS:
782 fh = (struct ieee_ie_fh_param_set *) pos;
783 memcpy(&bss->phy.fh, fh, sizeof(*fh));
784 lbs_deb_scan("got FH IE\n");
785 break;
786
787 case WLAN_EID_DS_PARAMS:
788 ds = (struct ieee_ie_ds_param_set *) pos;
789 bss->channel = ds->channel;
790 memcpy(&bss->phy.ds, ds, sizeof(*ds));
791 lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
792 break;
793
794 case WLAN_EID_CF_PARAMS:
795 cf = (struct ieee_ie_cf_param_set *) pos;
796 memcpy(&bss->ss.cf, cf, sizeof(*cf));
797 lbs_deb_scan("got CF IE\n");
798 break;
799
800 case WLAN_EID_IBSS_PARAMS:
801 ibss = (struct ieee_ie_ibss_param_set *) pos;
802 bss->atimwindow = ibss->atimwindow;
803 memcpy(&bss->ss.ibss, ibss, sizeof(*ibss));
804 lbs_deb_scan("got IBSS IE\n");
805 break;
806
807 case WLAN_EID_EXT_SUPP_RATES:
808 /* only process extended supported rate if data rate is
809 * already found. Data rate IE should come before
810 * extended supported rate IE
811 */
812 lbs_deb_scan("got RATESEX IE\n");
813 if (!got_basic_rates) {
814 lbs_deb_scan("... but ignoring it\n");
815 break;
816 }
817
818 n_ex_rates = pos[1];
819 if (n_basic_rates + n_ex_rates > MAX_RATES)
820 n_ex_rates = MAX_RATES - n_basic_rates;
821
822 p = bss->rates + n_basic_rates;
823 memcpy(p, pos + 2, n_ex_rates);
824 break;
825
826 case WLAN_EID_GENERIC:
827 if (pos[1] >= 4 &&
828 pos[2] == 0x00 && pos[3] == 0x50 &&
829 pos[4] == 0xf2 && pos[5] == 0x01) {
830 bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
831 memcpy(bss->wpa_ie, pos, bss->wpa_ie_len);
832 lbs_deb_scan("got WPA IE\n");
833 lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
834 bss->wpa_ie_len);
835 } else if (pos[1] >= MARVELL_MESH_IE_LENGTH &&
836 pos[2] == 0x00 && pos[3] == 0x50 &&
837 pos[4] == 0x43 && pos[5] == 0x04) {
838 lbs_deb_scan("got mesh IE\n");
839 bss->mesh = 1;
840 } else {
841 lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
842 pos[2], pos[3],
843 pos[4], pos[5],
844 pos[1]);
845 }
846 break;
847
848 case WLAN_EID_RSN:
849 lbs_deb_scan("got RSN IE\n");
850 bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
851 memcpy(bss->rsn_ie, pos, bss->rsn_ie_len);
852 lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
853 bss->rsn_ie, bss->rsn_ie_len);
854 break;
855
856 default:
857 lbs_deb_scan("got IE 0x%04x, len %d\n",
858 pos[0], pos[1]);
859 break;
860 }
861
862 pos += pos[1] + 2;
863 }
864
865 /* Timestamp */
866 bss->last_scanned = jiffies;
867 lbs_unset_basic_rate_flags(bss->rates, sizeof(bss->rates));
868
869 ret = 0;
870
871done:
872 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
873 return ret;
874}
875
876/**
877 * @brief Send a scan command for all available channels filtered on a spec
878 *
879 * Used in association code and from debugfs
880 *
881 * @param priv A pointer to struct lbs_private structure
882 * @param ssid A pointer to the SSID to scan for
883 * @param ssid_len Length of the SSID
884 *
885 * @return 0-success, otherwise fail
886 */
887int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
888 uint8_t ssid_len)
889{
890 DECLARE_SSID_BUF(ssid_buf);
891 int ret = 0;
892
893 lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
894 print_ssid(ssid_buf, ssid, ssid_len));
895
896 if (!ssid_len)
897 goto out;
898
899 memcpy(priv->scan_ssid, ssid, ssid_len);
900 priv->scan_ssid_len = ssid_len;
901
902 lbs_scan_networks(priv, 1);
903 if (priv->surpriseremoved) {
904 ret = -1;
905 goto out;
906 }
907
908out:
909 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
910 return ret;
911}
912
913
914
915
916/*********************************************************************/
917/* */
918/* Support for Wireless Extensions */
919/* */
920/*********************************************************************/
921
922
923#define MAX_CUSTOM_LEN 64
924
925static inline char *lbs_translate_scan(struct lbs_private *priv,
926 struct iw_request_info *info,
927 char *start, char *stop,
928 struct bss_descriptor *bss)
929{
930 struct chan_freq_power *cfp;
931 char *current_val; /* For rates */
932 struct iw_event iwe; /* Temporary buffer */
933 int j;
934#define PERFECT_RSSI ((uint8_t)50)
935#define WORST_RSSI ((uint8_t)0)
936#define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI))
937 uint8_t rssi;
938
939 lbs_deb_enter(LBS_DEB_SCAN);
940
941 cfp = lbs_find_cfp_by_band_and_channel(priv, 0, bss->channel);
942 if (!cfp) {
943 lbs_deb_scan("Invalid channel number %d\n", bss->channel);
944 start = NULL;
945 goto out;
946 }
947
948 /* First entry *MUST* be the BSSID */
949 iwe.cmd = SIOCGIWAP;
950 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
951 memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
952 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
953
954 /* SSID */
955 iwe.cmd = SIOCGIWESSID;
956 iwe.u.data.flags = 1;
957 iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN);
958 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
959
960 /* Mode */
961 iwe.cmd = SIOCGIWMODE;
962 iwe.u.mode = bss->mode;
963 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
964
965 /* Frequency */
966 iwe.cmd = SIOCGIWFREQ;
967 iwe.u.freq.m = (long)cfp->freq * 100000;
968 iwe.u.freq.e = 1;
969 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
970
971 /* Add quality statistics */
972 iwe.cmd = IWEVQUAL;
973 iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
974 iwe.u.qual.level = SCAN_RSSI(bss->rssi);
975
976 rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
977 iwe.u.qual.qual =
978 (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
979 (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
980 (RSSI_DIFF * RSSI_DIFF);
981 if (iwe.u.qual.qual > 100)
982 iwe.u.qual.qual = 100;
983
984 if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
985 iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
986 } else {
987 iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
988 }
989
990 /* Locally created ad-hoc BSSs won't have beacons if this is the
991 * only station in the adhoc network; so get signal strength
992 * from receive statistics.
993 */
994 if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate
995 && !lbs_ssid_cmp(priv->curbssparams.ssid,
996 priv->curbssparams.ssid_len,
997 bss->ssid, bss->ssid_len)) {
998 int snr, nf;
999 snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
1000 nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
1001 iwe.u.qual.level = CAL_RSSI(snr, nf);
1002 }
1003 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
1004
1005 /* Add encryption capability */
1006 iwe.cmd = SIOCGIWENCODE;
1007 if (bss->capability & WLAN_CAPABILITY_PRIVACY) {
1008 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1009 } else {
1010 iwe.u.data.flags = IW_ENCODE_DISABLED;
1011 }
1012 iwe.u.data.length = 0;
1013 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
1014
1015 current_val = start + iwe_stream_lcp_len(info);
1016
1017 iwe.cmd = SIOCGIWRATE;
1018 iwe.u.bitrate.fixed = 0;
1019 iwe.u.bitrate.disabled = 0;
1020 iwe.u.bitrate.value = 0;
1021
1022 for (j = 0; j < ARRAY_SIZE(bss->rates) && bss->rates[j]; j++) {
1023 /* Bit rate given in 500 kb/s units */
1024 iwe.u.bitrate.value = bss->rates[j] * 500000;
1025 current_val = iwe_stream_add_value(info, start, current_val,
1026 stop, &iwe, IW_EV_PARAM_LEN);
1027 }
1028 if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
1029 && !lbs_ssid_cmp(priv->curbssparams.ssid,
1030 priv->curbssparams.ssid_len,
1031 bss->ssid, bss->ssid_len)) {
1032 iwe.u.bitrate.value = 22 * 500000;
1033 current_val = iwe_stream_add_value(info, start, current_val,
1034 stop, &iwe, IW_EV_PARAM_LEN);
1035 }
1036 /* Check if we added any event */
1037 if ((current_val - start) > iwe_stream_lcp_len(info))
1038 start = current_val;
1039
1040 memset(&iwe, 0, sizeof(iwe));
1041 if (bss->wpa_ie_len) {
1042 char buf[MAX_WPA_IE_LEN];
1043 memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
1044 iwe.cmd = IWEVGENIE;
1045 iwe.u.data.length = bss->wpa_ie_len;
1046 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1047 }
1048
1049 memset(&iwe, 0, sizeof(iwe));
1050 if (bss->rsn_ie_len) {
1051 char buf[MAX_WPA_IE_LEN];
1052 memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
1053 iwe.cmd = IWEVGENIE;
1054 iwe.u.data.length = bss->rsn_ie_len;
1055 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1056 }
1057
1058 if (bss->mesh) {
1059 char custom[MAX_CUSTOM_LEN];
1060 char *p = custom;
1061
1062 iwe.cmd = IWEVCUSTOM;
1063 p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
1064 iwe.u.data.length = p - custom;
1065 if (iwe.u.data.length)
1066 start = iwe_stream_add_point(info, start, stop,
1067 &iwe, custom);
1068 }
1069
1070out:
1071 lbs_deb_leave_args(LBS_DEB_SCAN, "start %p", start);
1072 return start;
1073}
1074
1075
1076/**
1077 * @brief Handle Scan Network ioctl
1078 *
1079 * @param dev A pointer to net_device structure
1080 * @param info A pointer to iw_request_info structure
1081 * @param vwrq A pointer to iw_param structure
1082 * @param extra A pointer to extra data buf
1083 *
1084 * @return 0 --success, otherwise fail
1085 */
1086int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
1087 union iwreq_data *wrqu, char *extra)
1088{
1089 DECLARE_SSID_BUF(ssid);
1090 struct lbs_private *priv = dev->ml_priv;
1091 int ret = 0;
1092
1093 lbs_deb_enter(LBS_DEB_WEXT);
1094
1095 if (!priv->radio_on) {
1096 ret = -EINVAL;
1097 goto out;
1098 }
1099
1100 if (!netif_running(dev)) {
1101 ret = -ENETDOWN;
1102 goto out;
1103 }
1104
1105 /* mac80211 does this:
1106 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1107 if (sdata->type != IEEE80211_IF_TYPE_xxx) {
1108 ret = -EOPNOTSUPP;
1109 goto out;
1110 }
1111 */
1112
1113 if (wrqu->data.length == sizeof(struct iw_scan_req) &&
1114 wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1115 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1116 priv->scan_ssid_len = req->essid_len;
1117 memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
1118 lbs_deb_wext("set_scan, essid '%s'\n",
1119 print_ssid(ssid, priv->scan_ssid, priv->scan_ssid_len));
1120 } else {
1121 priv->scan_ssid_len = 0;
1122 }
1123
1124 if (!delayed_work_pending(&priv->scan_work))
1125 queue_delayed_work(priv->work_thread, &priv->scan_work,
1126 msecs_to_jiffies(50));
1127 /* set marker that currently a scan is taking place */
1128 priv->scan_channel = -1;
1129
1130 if (priv->surpriseremoved)
1131 ret = -EIO;
1132
1133out:
1134 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1135 return ret;
1136}
1137
1138
1139/**
1140 * @brief Handle Retrieve scan table ioctl
1141 *
1142 * @param dev A pointer to net_device structure
1143 * @param info A pointer to iw_request_info structure
1144 * @param dwrq A pointer to iw_point structure
1145 * @param extra A pointer to extra data buf
1146 *
1147 * @return 0 --success, otherwise fail
1148 */
1149int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1150 struct iw_point *dwrq, char *extra)
1151{
1152#define SCAN_ITEM_SIZE 128
1153 struct lbs_private *priv = dev->ml_priv;
1154 int err = 0;
1155 char *ev = extra;
1156 char *stop = ev + dwrq->length;
1157 struct bss_descriptor *iter_bss;
1158 struct bss_descriptor *safe;
1159
1160 lbs_deb_enter(LBS_DEB_WEXT);
1161
1162 /* iwlist should wait until the current scan is finished */
1163 if (priv->scan_channel)
1164 return -EAGAIN;
1165
1166 /* Update RSSI if current BSS is a locally created ad-hoc BSS */
1167 if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
1168 err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
1169 CMD_OPTION_WAITFORRSP, 0, NULL);
1170 if (err)
1171 goto out;
1172 }
1173
1174 mutex_lock(&priv->lock);
1175 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
1176 char *next_ev;
1177 unsigned long stale_time;
1178
1179 if (stop - ev < SCAN_ITEM_SIZE) {
1180 err = -E2BIG;
1181 break;
1182 }
1183
1184 /* For mesh device, list only mesh networks */
1185 if (dev == priv->mesh_dev && !iter_bss->mesh)
1186 continue;
1187
1188 /* Prune old an old scan result */
1189 stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
1190 if (time_after(jiffies, stale_time)) {
1191 list_move_tail(&iter_bss->list, &priv->network_free_list);
1192 clear_bss_descriptor(iter_bss);
1193 continue;
1194 }
1195
1196 /* Translate to WE format this entry */
1197 next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss);
1198 if (next_ev == NULL)
1199 continue;
1200 ev = next_ev;
1201 }
1202 mutex_unlock(&priv->lock);
1203
1204 dwrq->length = (ev - extra);
1205 dwrq->flags = 0;
1206out:
1207 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
1208 return err;
1209}
1210
1211
1212
1213
1214/*********************************************************************/
1215/* */
1216/* Command execution */
1217/* */
1218/*********************************************************************/
1219
1220
1221/**
1222 * @brief This function handles the command response of scan
1223 *
1224 * Called from handle_cmd_response() in cmdrespc.
1225 *
1226 * The response buffer for the scan command has the following
1227 * memory layout:
1228 *
1229 * .-----------------------------------------------------------.
1230 * | header (4 * sizeof(u16)): Standard command response hdr |
1231 * .-----------------------------------------------------------.
1232 * | bufsize (u16) : sizeof the BSS Description data |
1233 * .-----------------------------------------------------------.
1234 * | NumOfSet (u8) : Number of BSS Descs returned |
1235 * .-----------------------------------------------------------.
1236 * | BSSDescription data (variable, size given in bufsize) |
1237 * .-----------------------------------------------------------.
1238 * | TLV data (variable, size calculated using header->size, |
1239 * | bufsize and sizeof the fixed fields above) |
1240 * .-----------------------------------------------------------.
1241 *
1242 * @param priv A pointer to struct lbs_private structure
1243 * @param resp A pointer to cmd_ds_command
1244 *
1245 * @return 0 or -1
1246 */
1247static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
1248 struct cmd_header *resp)
1249{
1250 struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
1251 struct bss_descriptor *iter_bss;
1252 struct bss_descriptor *safe;
1253 uint8_t *bssinfo;
1254 uint16_t scanrespsize;
1255 int bytesleft;
1256 int idx;
1257 int tlvbufsize;
1258 int ret;
1259
1260 lbs_deb_enter(LBS_DEB_SCAN);
1261
1262 /* Prune old entries from scan table */
1263 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
1264 unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
1265 if (time_before(jiffies, stale_time))
1266 continue;
1267 list_move_tail (&iter_bss->list, &priv->network_free_list);
1268 clear_bss_descriptor(iter_bss);
1269 }
1270
1271 if (scanresp->nr_sets > MAX_NETWORK_COUNT) {
1272 lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n",
1273 scanresp->nr_sets, MAX_NETWORK_COUNT);
1274 ret = -1;
1275 goto done;
1276 }
1277
1278 bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize);
1279 lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
1280
1281 scanrespsize = le16_to_cpu(resp->size);
1282 lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
1283
1284 bssinfo = scanresp->bssdesc_and_tlvbuffer;
1285
1286 /* The size of the TLV buffer is equal to the entire command response
1287 * size (scanrespsize) minus the fixed fields (sizeof()'s), the
1288 * BSS Descriptions (bssdescriptsize as bytesLef) and the command
1289 * response header (sizeof(struct cmd_header))
1290 */
1291 tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
1292 + sizeof(scanresp->nr_sets)
1293 + sizeof(struct cmd_header));
1294
1295 /*
1296 * Process each scan response returned (scanresp->nr_sets). Save
1297 * the information in the newbssentry and then insert into the
1298 * driver scan table either as an update to an existing entry
1299 * or as an addition at the end of the table
1300 */
1301 for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) {
1302 struct bss_descriptor new;
1303 struct bss_descriptor *found = NULL;
1304 struct bss_descriptor *oldest = NULL;
1305
1306 /* Process the data fields and IEs returned for this BSS */
1307 memset(&new, 0, sizeof (struct bss_descriptor));
1308 if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) {
1309 /* error parsing the scan response, skipped */
1310 lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
1311 continue;
1312 }
1313
1314 /* Try to find this bss in the scan table */
1315 list_for_each_entry (iter_bss, &priv->network_list, list) {
1316 if (is_same_network(iter_bss, &new)) {
1317 found = iter_bss;
1318 break;
1319 }
1320
1321 if ((oldest == NULL) ||
1322 (iter_bss->last_scanned < oldest->last_scanned))
1323 oldest = iter_bss;
1324 }
1325
1326 if (found) {
1327 /* found, clear it */
1328 clear_bss_descriptor(found);
1329 } else if (!list_empty(&priv->network_free_list)) {
1330 /* Pull one from the free list */
1331 found = list_entry(priv->network_free_list.next,
1332 struct bss_descriptor, list);
1333 list_move_tail(&found->list, &priv->network_list);
1334 } else if (oldest) {
1335 /* If there are no more slots, expire the oldest */
1336 found = oldest;
1337 clear_bss_descriptor(found);
1338 list_move_tail(&found->list, &priv->network_list);
1339 } else {
1340 continue;
1341 }
1342
1343 lbs_deb_scan("SCAN_RESP: BSSID %pM\n", new.bssid);
1344
1345 /* Copy the locally created newbssentry to the scan table */
1346 memcpy(found, &new, offsetof(struct bss_descriptor, list));
1347 }
1348
1349 ret = 0;
1350
1351done:
1352 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
1353 return ret;
1354}
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
deleted file mode 100644
index 8fb1706d7526..000000000000
--- a/drivers/net/wireless/libertas/scan.h
+++ /dev/null
@@ -1,63 +0,0 @@
1/**
2 * Interface for the wlan network scan routines
3 *
4 * Driver interface functions and type declarations for the scan module
5 * implemented in scan.c.
6 */
7#ifndef _LBS_SCAN_H
8#define _LBS_SCAN_H
9
10#include <net/iw_handler.h>
11
12struct lbs_private;
13
14#define MAX_NETWORK_COUNT 128
15
16/** Chan-freq-TxPower mapping table*/
17struct chan_freq_power {
18 /** channel Number */
19 u16 channel;
20 /** frequency of this channel */
21 u32 freq;
22 /** Max allowed Tx power level */
23 u16 maxtxpower;
24 /** TRUE:channel unsupported; FLASE:supported*/
25 u8 unsupported;
26};
27
28/** region-band mapping table*/
29struct region_channel {
30 /** TRUE if this entry is valid */
31 u8 valid;
32 /** region code for US, Japan ... */
33 u8 region;
34 /** band B/G/A, used for BAND_CONFIG cmd */
35 u8 band;
36 /** Actual No. of elements in the array below */
37 u8 nrcfp;
38 /** chan-freq-txpower mapping table*/
39 struct chan_freq_power *CFP;
40};
41
42/**
43 * @brief Maximum number of channels that can be sent in a setuserscan ioctl
44 */
45#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
46
47int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
48
49int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
50
51int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
52 u8 ssid_len);
53
54int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
55 struct iw_point *dwrq, char *extra);
56int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
57 union iwreq_data *wrqu, char *extra);
58
59int lbs_scan_networks(struct lbs_private *priv, int full_scan);
60
61void lbs_scan_worker(struct work_struct *work);
62
63#endif
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index a9bf658659eb..411a3bbf035e 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -4,13 +4,13 @@
4#include <linux/netdevice.h> 4#include <linux/netdevice.h>
5#include <linux/etherdevice.h> 5#include <linux/etherdevice.h>
6#include <linux/sched.h> 6#include <linux/sched.h>
7#include <net/cfg80211.h>
7 8
8#include "host.h" 9#include "host.h"
9#include "radiotap.h" 10#include "radiotap.h"
10#include "decl.h" 11#include "decl.h"
11#include "defs.h" 12#include "defs.h"
12#include "dev.h" 13#include "dev.h"
13#include "wext.h"
14 14
15/** 15/**
16 * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE 16 * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
@@ -111,7 +111,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
111 p802x_hdr = skb->data; 111 p802x_hdr = skb->data;
112 pkt_len = skb->len; 112 pkt_len = skb->len;
113 113
114 if (dev == priv->rtap_net_dev) { 114 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
115 struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data; 115 struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data;
116 116
117 /* set txpd fields from the radiotap header */ 117 /* set txpd fields from the radiotap header */
@@ -147,7 +147,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
147 dev->stats.tx_packets++; 147 dev->stats.tx_packets++;
148 dev->stats.tx_bytes += skb->len; 148 dev->stats.tx_bytes += skb->len;
149 149
150 if (priv->monitormode) { 150 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
151 /* Keep the skb to echo it back once Tx feedback is 151 /* Keep the skb to echo it back once Tx feedback is
152 received from FW */ 152 received from FW */
153 skb_orphan(skb); 153 skb_orphan(skb);
@@ -158,6 +158,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
158 free: 158 free:
159 dev_kfree_skb_any(skb); 159 dev_kfree_skb_any(skb);
160 } 160 }
161
161 unlock: 162 unlock:
162 spin_unlock_irqrestore(&priv->driver_lock, flags); 163 spin_unlock_irqrestore(&priv->driver_lock, flags);
163 wake_up(&priv->waitq); 164 wake_up(&priv->waitq);
@@ -179,7 +180,8 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
179{ 180{
180 struct tx_radiotap_hdr *radiotap_hdr; 181 struct tx_radiotap_hdr *radiotap_hdr;
181 182
182 if (!priv->monitormode || priv->currenttxskb == NULL) 183 if (!priv->wdev->iftype == NL80211_IFTYPE_MONITOR ||
184 priv->currenttxskb == NULL)
183 return; 185 return;
184 186
185 radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; 187 radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
@@ -188,7 +190,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
188 (1 + priv->txretrycount - try_count) : 0; 190 (1 + priv->txretrycount - try_count) : 0;
189 191
190 priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, 192 priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
191 priv->rtap_net_dev); 193 priv->dev);
192 netif_rx(priv->currenttxskb); 194 netif_rx(priv->currenttxskb);
193 195
194 priv->currenttxskb = NULL; 196 priv->currenttxskb = NULL;
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
deleted file mode 100644
index f96a96031a50..000000000000
--- a/drivers/net/wireless/libertas/wext.c
+++ /dev/null
@@ -1,2353 +0,0 @@
1/**
2 * This file contains ioctl functions
3 */
4#include <linux/ctype.h>
5#include <linux/slab.h>
6#include <linux/delay.h>
7#include <linux/if.h>
8#include <linux/if_arp.h>
9#include <linux/wireless.h>
10#include <linux/bitops.h>
11
12#include <net/lib80211.h>
13#include <net/iw_handler.h>
14
15#include "host.h"
16#include "radiotap.h"
17#include "decl.h"
18#include "defs.h"
19#include "dev.h"
20#include "wext.h"
21#include "scan.h"
22#include "assoc.h"
23#include "cmd.h"
24
25
26static inline void lbs_postpone_association_work(struct lbs_private *priv)
27{
28 if (priv->surpriseremoved)
29 return;
30 cancel_delayed_work(&priv->assoc_work);
31 queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
32}
33
34static inline void lbs_do_association_work(struct lbs_private *priv)
35{
36 if (priv->surpriseremoved)
37 return;
38 cancel_delayed_work(&priv->assoc_work);
39 queue_delayed_work(priv->work_thread, &priv->assoc_work, 0);
40}
41
42static inline void lbs_cancel_association_work(struct lbs_private *priv)
43{
44 cancel_delayed_work(&priv->assoc_work);
45 kfree(priv->pending_assoc_req);
46 priv->pending_assoc_req = NULL;
47}
48
49void lbs_send_disconnect_notification(struct lbs_private *priv)
50{
51 union iwreq_data wrqu;
52
53 memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
54 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
55 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
56}
57
58static void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
59{
60 union iwreq_data iwrq;
61 u8 buf[50];
62
63 lbs_deb_enter(LBS_DEB_WEXT);
64
65 memset(&iwrq, 0, sizeof(union iwreq_data));
66 memset(buf, 0, sizeof(buf));
67
68 snprintf(buf, sizeof(buf) - 1, "%s", str);
69
70 iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
71
72 /* Send Event to upper layer */
73 lbs_deb_wext("event indication string %s\n", (char *)buf);
74 lbs_deb_wext("event indication length %d\n", iwrq.data.length);
75 lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
76
77 wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
78
79 lbs_deb_leave(LBS_DEB_WEXT);
80}
81
82/**
83 * @brief This function handles MIC failure event.
84 *
85 * @param priv A pointer to struct lbs_private structure
86 * @para event the event id
87 * @return n/a
88 */
89void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
90{
91 char buf[50];
92
93 lbs_deb_enter(LBS_DEB_CMD);
94 memset(buf, 0, sizeof(buf));
95
96 sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
97
98 if (event == MACREG_INT_CODE_MIC_ERR_UNICAST)
99 strcat(buf, "unicast ");
100 else
101 strcat(buf, "multicast ");
102
103 lbs_send_iwevcustom_event(priv, buf);
104 lbs_deb_leave(LBS_DEB_CMD);
105}
106
107/**
108 * @brief Find the channel frequency power info with specific channel
109 *
110 * @param priv A pointer to struct lbs_private structure
111 * @param band it can be BAND_A, BAND_G or BAND_B
112 * @param channel the channel for looking
113 * @return A pointer to struct chan_freq_power structure or NULL if not find.
114 */
115struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
116 struct lbs_private *priv,
117 u8 band,
118 u16 channel)
119{
120 struct chan_freq_power *cfp = NULL;
121 struct region_channel *rc;
122 int i, j;
123
124 for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
125 rc = &priv->region_channel[j];
126
127 if (!rc->valid || !rc->CFP)
128 continue;
129 if (rc->band != band)
130 continue;
131 for (i = 0; i < rc->nrcfp; i++) {
132 if (rc->CFP[i].channel == channel) {
133 cfp = &rc->CFP[i];
134 break;
135 }
136 }
137 }
138
139 if (!cfp && channel)
140 lbs_deb_wext("lbs_find_cfp_by_band_and_channel: can't find "
141 "cfp by band %d / channel %d\n", band, channel);
142
143 return cfp;
144}
145
146/**
147 * @brief Find the channel frequency power info with specific frequency
148 *
149 * @param priv A pointer to struct lbs_private structure
150 * @param band it can be BAND_A, BAND_G or BAND_B
151 * @param freq the frequency for looking
152 * @return A pointer to struct chan_freq_power structure or NULL if not find.
153 */
154static struct chan_freq_power *find_cfp_by_band_and_freq(
155 struct lbs_private *priv,
156 u8 band,
157 u32 freq)
158{
159 struct chan_freq_power *cfp = NULL;
160 struct region_channel *rc;
161 int i, j;
162
163 for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
164 rc = &priv->region_channel[j];
165
166 if (!rc->valid || !rc->CFP)
167 continue;
168 if (rc->band != band)
169 continue;
170 for (i = 0; i < rc->nrcfp; i++) {
171 if (rc->CFP[i].freq == freq) {
172 cfp = &rc->CFP[i];
173 break;
174 }
175 }
176 }
177
178 if (!cfp && freq)
179 lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by "
180 "band %d / freq %d\n", band, freq);
181
182 return cfp;
183}
184
185/**
186 * @brief Copy active data rates based on adapter mode and status
187 *
188 * @param priv A pointer to struct lbs_private structure
189 * @param rate The buf to return the active rates
190 */
191static void copy_active_data_rates(struct lbs_private *priv, u8 *rates)
192{
193 lbs_deb_enter(LBS_DEB_WEXT);
194
195 if ((priv->connect_status != LBS_CONNECTED) &&
196 !lbs_mesh_connected(priv))
197 memcpy(rates, lbs_bg_rates, MAX_RATES);
198 else
199 memcpy(rates, priv->curbssparams.rates, MAX_RATES);
200
201 lbs_deb_leave(LBS_DEB_WEXT);
202}
203
204static int lbs_get_name(struct net_device *dev, struct iw_request_info *info,
205 char *cwrq, char *extra)
206{
207
208 lbs_deb_enter(LBS_DEB_WEXT);
209
210 /* We could add support for 802.11n here as needed. Jean II */
211 snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g");
212
213 lbs_deb_leave(LBS_DEB_WEXT);
214 return 0;
215}
216
217static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
218 struct iw_freq *fwrq, char *extra)
219{
220 struct lbs_private *priv = dev->ml_priv;
221 struct chan_freq_power *cfp;
222
223 lbs_deb_enter(LBS_DEB_WEXT);
224
225 cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
226 priv->channel);
227
228 if (!cfp) {
229 if (priv->channel)
230 lbs_deb_wext("invalid channel %d\n",
231 priv->channel);
232 return -EINVAL;
233 }
234
235 fwrq->m = (long)cfp->freq * 100000;
236 fwrq->e = 1;
237
238 lbs_deb_wext("freq %u\n", fwrq->m);
239 lbs_deb_leave(LBS_DEB_WEXT);
240 return 0;
241}
242
243static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
244 struct sockaddr *awrq, char *extra)
245{
246 struct lbs_private *priv = dev->ml_priv;
247
248 lbs_deb_enter(LBS_DEB_WEXT);
249
250 if (priv->connect_status == LBS_CONNECTED) {
251 memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN);
252 } else {
253 memset(awrq->sa_data, 0, ETH_ALEN);
254 }
255 awrq->sa_family = ARPHRD_ETHER;
256
257 lbs_deb_leave(LBS_DEB_WEXT);
258 return 0;
259}
260
261static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
262 struct iw_point *dwrq, char *extra)
263{
264 struct lbs_private *priv = dev->ml_priv;
265
266 lbs_deb_enter(LBS_DEB_WEXT);
267
268 /*
269 * Check the size of the string
270 */
271
272 if (dwrq->length > 16) {
273 return -E2BIG;
274 }
275
276 mutex_lock(&priv->lock);
277 memset(priv->nodename, 0, sizeof(priv->nodename));
278 memcpy(priv->nodename, extra, dwrq->length);
279 mutex_unlock(&priv->lock);
280
281 lbs_deb_leave(LBS_DEB_WEXT);
282 return 0;
283}
284
285static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
286 struct iw_point *dwrq, char *extra)
287{
288 struct lbs_private *priv = dev->ml_priv;
289
290 lbs_deb_enter(LBS_DEB_WEXT);
291
292 dwrq->length = strlen(priv->nodename);
293 memcpy(extra, priv->nodename, dwrq->length);
294 extra[dwrq->length] = '\0';
295
296 dwrq->flags = 1; /* active */
297
298 lbs_deb_leave(LBS_DEB_WEXT);
299 return 0;
300}
301
302#ifdef CONFIG_LIBERTAS_MESH
303static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
304 struct iw_point *dwrq, char *extra)
305{
306 struct lbs_private *priv = dev->ml_priv;
307
308 lbs_deb_enter(LBS_DEB_WEXT);
309
310 /* Use nickname to indicate that mesh is on */
311
312 if (lbs_mesh_connected(priv)) {
313 strncpy(extra, "Mesh", 12);
314 extra[12] = '\0';
315 dwrq->length = strlen(extra);
316 }
317
318 else {
319 extra[0] = '\0';
320 dwrq->length = 0;
321 }
322
323 lbs_deb_leave(LBS_DEB_WEXT);
324 return 0;
325}
326#endif
327
328static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
329 struct iw_param *vwrq, char *extra)
330{
331 int ret = 0;
332 struct lbs_private *priv = dev->ml_priv;
333 u32 val = vwrq->value;
334
335 lbs_deb_enter(LBS_DEB_WEXT);
336
337 if (vwrq->disabled)
338 val = MRVDRV_RTS_MAX_VALUE;
339
340 if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */
341 return -EINVAL;
342
343 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val);
344
345 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
346 return ret;
347}
348
349static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
350 struct iw_param *vwrq, char *extra)
351{
352 struct lbs_private *priv = dev->ml_priv;
353 int ret = 0;
354 u16 val = 0;
355
356 lbs_deb_enter(LBS_DEB_WEXT);
357
358 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
359 if (ret)
360 goto out;
361
362 vwrq->value = val;
363 vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */
364 vwrq->fixed = 1;
365
366out:
367 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
368 return ret;
369}
370
371static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
372 struct iw_param *vwrq, char *extra)
373{
374 struct lbs_private *priv = dev->ml_priv;
375 int ret = 0;
376 u32 val = vwrq->value;
377
378 lbs_deb_enter(LBS_DEB_WEXT);
379
380 if (vwrq->disabled)
381 val = MRVDRV_FRAG_MAX_VALUE;
382
383 if (val < MRVDRV_FRAG_MIN_VALUE || val > MRVDRV_FRAG_MAX_VALUE)
384 return -EINVAL;
385
386 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, (u16) val);
387
388 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
389 return ret;
390}
391
392static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
393 struct iw_param *vwrq, char *extra)
394{
395 struct lbs_private *priv = dev->ml_priv;
396 int ret = 0;
397 u16 val = 0;
398
399 lbs_deb_enter(LBS_DEB_WEXT);
400
401 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
402 if (ret)
403 goto out;
404
405 vwrq->value = val;
406 vwrq->disabled = ((val < MRVDRV_FRAG_MIN_VALUE)
407 || (val > MRVDRV_FRAG_MAX_VALUE));
408 vwrq->fixed = 1;
409
410out:
411 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
412 return ret;
413}
414
415static int lbs_get_mode(struct net_device *dev,
416 struct iw_request_info *info, u32 * uwrq, char *extra)
417{
418 struct lbs_private *priv = dev->ml_priv;
419
420 lbs_deb_enter(LBS_DEB_WEXT);
421
422 *uwrq = priv->mode;
423
424 lbs_deb_leave(LBS_DEB_WEXT);
425 return 0;
426}
427
428#ifdef CONFIG_LIBERTAS_MESH
429static int mesh_wlan_get_mode(struct net_device *dev,
430 struct iw_request_info *info, u32 * uwrq,
431 char *extra)
432{
433 lbs_deb_enter(LBS_DEB_WEXT);
434
435 *uwrq = IW_MODE_REPEAT;
436
437 lbs_deb_leave(LBS_DEB_WEXT);
438 return 0;
439}
440#endif
441
442static int lbs_get_txpow(struct net_device *dev,
443 struct iw_request_info *info,
444 struct iw_param *vwrq, char *extra)
445{
446 struct lbs_private *priv = dev->ml_priv;
447 s16 curlevel = 0;
448 int ret = 0;
449
450 lbs_deb_enter(LBS_DEB_WEXT);
451
452 if (!priv->radio_on) {
453 lbs_deb_wext("tx power off\n");
454 vwrq->value = 0;
455 vwrq->disabled = 1;
456 goto out;
457 }
458
459 ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL);
460 if (ret)
461 goto out;
462
463 lbs_deb_wext("tx power level %d dbm\n", curlevel);
464 priv->txpower_cur = curlevel;
465
466 vwrq->value = curlevel;
467 vwrq->fixed = 1;
468 vwrq->disabled = 0;
469 vwrq->flags = IW_TXPOW_DBM;
470
471out:
472 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
473 return ret;
474}
475
476static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
477 struct iw_param *vwrq, char *extra)
478{
479 struct lbs_private *priv = dev->ml_priv;
480 int ret = 0;
481 u16 slimit = 0, llimit = 0;
482
483 lbs_deb_enter(LBS_DEB_WEXT);
484
485 if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
486 return -EOPNOTSUPP;
487
488 /* The MAC has a 4-bit Total_Tx_Count register
489 Total_Tx_Count = 1 + Tx_Retry_Count */
490#define TX_RETRY_MIN 0
491#define TX_RETRY_MAX 14
492 if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
493 return -EINVAL;
494
495 /* Add 1 to convert retry count to try count */
496 if (vwrq->flags & IW_RETRY_SHORT)
497 slimit = (u16) (vwrq->value + 1);
498 else if (vwrq->flags & IW_RETRY_LONG)
499 llimit = (u16) (vwrq->value + 1);
500 else
501 slimit = llimit = (u16) (vwrq->value + 1); /* set both */
502
503 if (llimit) {
504 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT,
505 llimit);
506 if (ret)
507 goto out;
508 }
509
510 if (slimit) {
511 /* txretrycount follows the short retry limit */
512 priv->txretrycount = slimit;
513 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT,
514 slimit);
515 if (ret)
516 goto out;
517 }
518
519out:
520 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
521 return ret;
522}
523
524static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
525 struct iw_param *vwrq, char *extra)
526{
527 struct lbs_private *priv = dev->ml_priv;
528 int ret = 0;
529 u16 val = 0;
530
531 lbs_deb_enter(LBS_DEB_WEXT);
532
533 vwrq->disabled = 0;
534
535 if (vwrq->flags & IW_RETRY_LONG) {
536 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, &val);
537 if (ret)
538 goto out;
539
540 /* Subtract 1 to convert try count to retry count */
541 vwrq->value = val - 1;
542 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
543 } else {
544 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, &val);
545 if (ret)
546 goto out;
547
548 /* txretry count follows the short retry limit */
549 priv->txretrycount = val;
550 /* Subtract 1 to convert try count to retry count */
551 vwrq->value = val - 1;
552 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
553 }
554
555out:
556 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
557 return ret;
558}
559
560static inline void sort_channels(struct iw_freq *freq, int num)
561{
562 int i, j;
563 struct iw_freq temp;
564
565 for (i = 0; i < num; i++)
566 for (j = i + 1; j < num; j++)
567 if (freq[i].i > freq[j].i) {
568 temp.i = freq[i].i;
569 temp.m = freq[i].m;
570
571 freq[i].i = freq[j].i;
572 freq[i].m = freq[j].m;
573
574 freq[j].i = temp.i;
575 freq[j].m = temp.m;
576 }
577}
578
579/* data rate listing
580 MULTI_BANDS:
581 abg a b b/g
582 Infra G(12) A(8) B(4) G(12)
583 Adhoc A+B(12) A(8) B(4) B(4)
584
585 non-MULTI_BANDS:
586 b b/g
587 Infra B(4) G(12)
588 Adhoc B(4) B(4)
589 */
590/**
591 * @brief Get Range Info
592 *
593 * @param dev A pointer to net_device structure
594 * @param info A pointer to iw_request_info structure
595 * @param vwrq A pointer to iw_param structure
596 * @param extra A pointer to extra data buf
597 * @return 0 --success, otherwise fail
598 */
599static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
600 struct iw_point *dwrq, char *extra)
601{
602 int i, j;
603 struct lbs_private *priv = dev->ml_priv;
604 struct iw_range *range = (struct iw_range *)extra;
605 struct chan_freq_power *cfp;
606 u8 rates[MAX_RATES + 1];
607
608 lbs_deb_enter(LBS_DEB_WEXT);
609
610 dwrq->length = sizeof(struct iw_range);
611 memset(range, 0, sizeof(struct iw_range));
612
613 range->min_nwid = 0;
614 range->max_nwid = 0;
615
616 memset(rates, 0, sizeof(rates));
617 copy_active_data_rates(priv, rates);
618 range->num_bitrates = strnlen(rates, IW_MAX_BITRATES);
619 for (i = 0; i < range->num_bitrates; i++)
620 range->bitrate[i] = rates[i] * 500000;
621 range->num_bitrates = i;
622 lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES,
623 range->num_bitrates);
624
625 range->num_frequency = 0;
626
627 range->scan_capa = IW_SCAN_CAPA_ESSID;
628
629 for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
630 && (j < ARRAY_SIZE(priv->region_channel)); j++) {
631 cfp = priv->region_channel[j].CFP;
632 for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
633 && priv->region_channel[j].valid
634 && cfp
635 && (i < priv->region_channel[j].nrcfp); i++) {
636 range->freq[range->num_frequency].i =
637 (long)cfp->channel;
638 range->freq[range->num_frequency].m =
639 (long)cfp->freq * 100000;
640 range->freq[range->num_frequency].e = 1;
641 cfp++;
642 range->num_frequency++;
643 }
644 }
645
646 lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
647 IW_MAX_FREQUENCIES, range->num_frequency);
648
649 range->num_channels = range->num_frequency;
650
651 sort_channels(&range->freq[0], range->num_frequency);
652
653 /*
654 * Set an indication of the max TCP throughput in bit/s that we can
655 * expect using this interface
656 */
657 if (i > 2)
658 range->throughput = 5000 * 1000;
659 else
660 range->throughput = 1500 * 1000;
661
662 range->min_rts = MRVDRV_RTS_MIN_VALUE;
663 range->max_rts = MRVDRV_RTS_MAX_VALUE;
664 range->min_frag = MRVDRV_FRAG_MIN_VALUE;
665 range->max_frag = MRVDRV_FRAG_MAX_VALUE;
666
667 range->encoding_size[0] = 5;
668 range->encoding_size[1] = 13;
669 range->num_encoding_sizes = 2;
670 range->max_encoding_tokens = 4;
671
672 /*
673 * Right now we support only "iwconfig ethX power on|off"
674 */
675 range->pm_capa = IW_POWER_ON;
676
677 /*
678 * Minimum version we recommend
679 */
680 range->we_version_source = 15;
681
682 /*
683 * Version we are compiled with
684 */
685 range->we_version_compiled = WIRELESS_EXT;
686
687 range->retry_capa = IW_RETRY_LIMIT;
688 range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
689
690 range->min_retry = TX_RETRY_MIN;
691 range->max_retry = TX_RETRY_MAX;
692
693 /*
694 * Set the qual, level and noise range values
695 */
696 range->max_qual.qual = 100;
697 range->max_qual.level = 0;
698 range->max_qual.noise = 0;
699 range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
700
701 range->avg_qual.qual = 70;
702 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
703 range->avg_qual.level = 0;
704 range->avg_qual.noise = 0;
705 range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
706
707 range->sensitivity = 0;
708
709 /* Setup the supported power level ranges */
710 memset(range->txpower, 0, sizeof(range->txpower));
711 range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
712 range->txpower[0] = priv->txpower_min;
713 range->txpower[1] = priv->txpower_max;
714 range->num_txpower = 2;
715
716 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
717 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
718 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
719 range->event_capa[1] = IW_EVENT_CAPA_K_1;
720
721 if (priv->fwcapinfo & FW_CAPINFO_WPA) {
722 range->enc_capa = IW_ENC_CAPA_WPA
723 | IW_ENC_CAPA_WPA2
724 | IW_ENC_CAPA_CIPHER_TKIP
725 | IW_ENC_CAPA_CIPHER_CCMP;
726 }
727
728 lbs_deb_leave(LBS_DEB_WEXT);
729 return 0;
730}
731
732static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
733 struct iw_param *vwrq, char *extra)
734{
735 struct lbs_private *priv = dev->ml_priv;
736 int ret = 0;
737
738 lbs_deb_enter(LBS_DEB_WEXT);
739
740 if (!(priv->fwcapinfo & FW_CAPINFO_PS)) {
741 if (vwrq->disabled)
742 return 0;
743 else
744 return -EINVAL;
745 }
746
747 /* PS is currently supported only in Infrastructure mode
748 * Remove this check if it is to be supported in IBSS mode also
749 */
750
751 if (vwrq->disabled) {
752 priv->psmode = LBS802_11POWERMODECAM;
753 if (priv->psstate != PS_STATE_FULL_POWER) {
754 lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
755 }
756
757 return 0;
758 }
759
760 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
761 lbs_deb_wext(
762 "setting power timeout is not supported\n");
763 return -EINVAL;
764 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
765 vwrq->value = vwrq->value / 1000;
766 if (!priv->enter_deep_sleep) {
767 lbs_pr_err("deep sleep feature is not implemented "
768 "for this interface driver\n");
769 return -EINVAL;
770 }
771
772 if (priv->connect_status == LBS_CONNECTED) {
773 if ((priv->is_auto_deep_sleep_enabled) &&
774 (vwrq->value == -1000)) {
775 lbs_exit_auto_deep_sleep(priv);
776 return 0;
777 } else {
778 lbs_pr_err("can't use deep sleep cmd in "
779 "connected state\n");
780 return -EINVAL;
781 }
782 }
783
784 if ((vwrq->value < 0) && (vwrq->value != -1000)) {
785 lbs_pr_err("unknown option\n");
786 return -EINVAL;
787 }
788
789 if (vwrq->value > 0) {
790 if (!priv->is_auto_deep_sleep_enabled) {
791 priv->is_activity_detected = 0;
792 priv->auto_deep_sleep_timeout = vwrq->value;
793 lbs_enter_auto_deep_sleep(priv);
794 } else {
795 priv->auto_deep_sleep_timeout = vwrq->value;
796 lbs_deb_debugfs("auto deep sleep: "
797 "already enabled\n");
798 }
799 return 0;
800 } else {
801 if (priv->is_auto_deep_sleep_enabled) {
802 lbs_exit_auto_deep_sleep(priv);
803 /* Try to exit deep sleep if auto */
804 /*deep sleep disabled */
805 ret = lbs_set_deep_sleep(priv, 0);
806 }
807 if (vwrq->value == 0)
808 ret = lbs_set_deep_sleep(priv, 1);
809 else if (vwrq->value == -1000)
810 ret = lbs_set_deep_sleep(priv, 0);
811 return ret;
812 }
813 }
814
815 if (priv->psmode != LBS802_11POWERMODECAM) {
816 return 0;
817 }
818
819 priv->psmode = LBS802_11POWERMODEMAX_PSP;
820
821 if (priv->connect_status == LBS_CONNECTED) {
822 lbs_ps_sleep(priv, CMD_OPTION_WAITFORRSP);
823 }
824
825 lbs_deb_leave(LBS_DEB_WEXT);
826
827 return 0;
828}
829
830static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
831 struct iw_param *vwrq, char *extra)
832{
833 struct lbs_private *priv = dev->ml_priv;
834
835 lbs_deb_enter(LBS_DEB_WEXT);
836
837 vwrq->value = 0;
838 vwrq->flags = 0;
839 vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM
840 || priv->connect_status == LBS_DISCONNECTED;
841
842 lbs_deb_leave(LBS_DEB_WEXT);
843 return 0;
844}
845
846static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
847{
848 enum {
849 POOR = 30,
850 FAIR = 60,
851 GOOD = 80,
852 VERY_GOOD = 90,
853 EXCELLENT = 95,
854 PERFECT = 100
855 };
856 struct lbs_private *priv = dev->ml_priv;
857 u32 rssi_qual;
858 u32 tx_qual;
859 u32 quality = 0;
860 int ret, stats_valid = 0;
861 u8 rssi;
862 u32 tx_retries;
863 struct cmd_ds_802_11_get_log log;
864
865 lbs_deb_enter(LBS_DEB_WEXT);
866
867 priv->wstats.status = priv->mode;
868
869 /* If we're not associated, all quality values are meaningless */
870 if ((priv->connect_status != LBS_CONNECTED) &&
871 !lbs_mesh_connected(priv))
872 goto out;
873
874 /* Quality by RSSI */
875 priv->wstats.qual.level =
876 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
877 priv->NF[TYPE_BEACON][TYPE_NOAVG]);
878
879 if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
880 priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
881 } else {
882 priv->wstats.qual.noise =
883 CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
884 }
885
886 lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
887 lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
888
889 rssi = priv->wstats.qual.level - priv->wstats.qual.noise;
890 if (rssi < 15)
891 rssi_qual = rssi * POOR / 10;
892 else if (rssi < 20)
893 rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
894 else if (rssi < 30)
895 rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
896 else if (rssi < 40)
897 rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
898 10 + GOOD;
899 else
900 rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
901 10 + VERY_GOOD;
902 quality = rssi_qual;
903
904 /* Quality by TX errors */
905 priv->wstats.discard.retries = dev->stats.tx_errors;
906
907 memset(&log, 0, sizeof(log));
908 log.hdr.size = cpu_to_le16(sizeof(log));
909 ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
910 if (ret)
911 goto out;
912
913 tx_retries = le32_to_cpu(log.retry);
914
915 if (tx_retries > 75)
916 tx_qual = (90 - tx_retries) * POOR / 15;
917 else if (tx_retries > 70)
918 tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
919 else if (tx_retries > 65)
920 tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
921 else if (tx_retries > 50)
922 tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
923 15 + GOOD;
924 else
925 tx_qual = (50 - tx_retries) *
926 (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
927 quality = min(quality, tx_qual);
928
929 priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
930 priv->wstats.discard.retries = tx_retries;
931 priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
932
933 /* Calculate quality */
934 priv->wstats.qual.qual = min_t(u8, quality, 100);
935 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
936 stats_valid = 1;
937
938 /* update stats asynchronously for future calls */
939 ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
940 0, 0, NULL);
941 if (ret)
942 lbs_pr_err("RSSI command failed\n");
943out:
944 if (!stats_valid) {
945 priv->wstats.miss.beacon = 0;
946 priv->wstats.discard.retries = 0;
947 priv->wstats.qual.qual = 0;
948 priv->wstats.qual.level = 0;
949 priv->wstats.qual.noise = 0;
950 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
951 priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
952 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
953 }
954
955 lbs_deb_leave(LBS_DEB_WEXT);
956 return &priv->wstats;
957
958
959}
960
961static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
962 struct iw_freq *fwrq, char *extra)
963{
964 int ret = -EINVAL;
965 struct lbs_private *priv = dev->ml_priv;
966 struct chan_freq_power *cfp;
967 struct assoc_request * assoc_req;
968
969 lbs_deb_enter(LBS_DEB_WEXT);
970
971 mutex_lock(&priv->lock);
972 assoc_req = lbs_get_association_request(priv);
973 if (!assoc_req) {
974 ret = -ENOMEM;
975 goto out;
976 }
977
978 /* If setting by frequency, convert to a channel */
979 if (fwrq->e == 1) {
980 long f = fwrq->m / 100000;
981
982 cfp = find_cfp_by_band_and_freq(priv, 0, f);
983 if (!cfp) {
984 lbs_deb_wext("invalid freq %ld\n", f);
985 goto out;
986 }
987
988 fwrq->e = 0;
989 fwrq->m = (int) cfp->channel;
990 }
991
992 /* Setting by channel number */
993 if (fwrq->m > 1000 || fwrq->e > 0) {
994 goto out;
995 }
996
997 cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
998 if (!cfp) {
999 goto out;
1000 }
1001
1002 assoc_req->channel = fwrq->m;
1003 ret = 0;
1004
1005out:
1006 if (ret == 0) {
1007 set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
1008 lbs_postpone_association_work(priv);
1009 } else {
1010 lbs_cancel_association_work(priv);
1011 }
1012 mutex_unlock(&priv->lock);
1013
1014 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1015 return ret;
1016}
1017
1018#ifdef CONFIG_LIBERTAS_MESH
1019static int lbs_mesh_set_freq(struct net_device *dev,
1020 struct iw_request_info *info,
1021 struct iw_freq *fwrq, char *extra)
1022{
1023 struct lbs_private *priv = dev->ml_priv;
1024 struct chan_freq_power *cfp;
1025 int ret = -EINVAL;
1026
1027 lbs_deb_enter(LBS_DEB_WEXT);
1028
1029 /* If setting by frequency, convert to a channel */
1030 if (fwrq->e == 1) {
1031 long f = fwrq->m / 100000;
1032
1033 cfp = find_cfp_by_band_and_freq(priv, 0, f);
1034 if (!cfp) {
1035 lbs_deb_wext("invalid freq %ld\n", f);
1036 goto out;
1037 }
1038
1039 fwrq->e = 0;
1040 fwrq->m = (int) cfp->channel;
1041 }
1042
1043 /* Setting by channel number */
1044 if (fwrq->m > 1000 || fwrq->e > 0) {
1045 goto out;
1046 }
1047
1048 cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
1049 if (!cfp) {
1050 goto out;
1051 }
1052
1053 if (fwrq->m != priv->channel) {
1054 lbs_deb_wext("mesh channel change forces eth disconnect\n");
1055 if (priv->mode == IW_MODE_INFRA)
1056 lbs_cmd_80211_deauthenticate(priv,
1057 priv->curbssparams.bssid,
1058 WLAN_REASON_DEAUTH_LEAVING);
1059 else if (priv->mode == IW_MODE_ADHOC)
1060 lbs_adhoc_stop(priv);
1061 }
1062 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m);
1063 lbs_update_channel(priv);
1064 ret = 0;
1065
1066out:
1067 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1068 return ret;
1069}
1070#endif
1071
1072static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
1073 struct iw_param *vwrq, char *extra)
1074{
1075 struct lbs_private *priv = dev->ml_priv;
1076 u8 new_rate = 0;
1077 int ret = -EINVAL;
1078 u8 rates[MAX_RATES + 1];
1079
1080 lbs_deb_enter(LBS_DEB_WEXT);
1081
1082 lbs_deb_wext("vwrq->value %d\n", vwrq->value);
1083 lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
1084
1085 if (vwrq->fixed && vwrq->value == -1)
1086 goto out;
1087
1088 /* Auto rate? */
1089 priv->enablehwauto = !vwrq->fixed;
1090
1091 if (vwrq->value == -1)
1092 priv->cur_rate = 0;
1093 else {
1094 if (vwrq->value % 100000)
1095 goto out;
1096
1097 new_rate = vwrq->value / 500000;
1098 priv->cur_rate = new_rate;
1099 /* the rest is only needed for lbs_set_data_rate() */
1100 memset(rates, 0, sizeof(rates));
1101 copy_active_data_rates(priv, rates);
1102 if (!memchr(rates, new_rate, sizeof(rates))) {
1103 lbs_pr_alert("fixed data rate 0x%X out of range\n",
1104 new_rate);
1105 goto out;
1106 }
1107 if (priv->fwrelease < 0x09000000) {
1108 ret = lbs_set_power_adapt_cfg(priv, 0,
1109 POW_ADAPT_DEFAULT_P0,
1110 POW_ADAPT_DEFAULT_P1,
1111 POW_ADAPT_DEFAULT_P2);
1112 if (ret)
1113 goto out;
1114 }
1115 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
1116 TPC_DEFAULT_P2, 1);
1117 if (ret)
1118 goto out;
1119 }
1120
1121 /* Try the newer command first (Firmware Spec 5.1 and above) */
1122 ret = lbs_cmd_802_11_rate_adapt_rateset(priv, CMD_ACT_SET);
1123
1124 /* Fallback to older version */
1125 if (ret)
1126 ret = lbs_set_data_rate(priv, new_rate);
1127
1128out:
1129 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1130 return ret;
1131}
1132
1133static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
1134 struct iw_param *vwrq, char *extra)
1135{
1136 struct lbs_private *priv = dev->ml_priv;
1137
1138 lbs_deb_enter(LBS_DEB_WEXT);
1139
1140 if (priv->connect_status == LBS_CONNECTED) {
1141 vwrq->value = priv->cur_rate * 500000;
1142
1143 if (priv->enablehwauto)
1144 vwrq->fixed = 0;
1145 else
1146 vwrq->fixed = 1;
1147
1148 } else {
1149 vwrq->fixed = 0;
1150 vwrq->value = 0;
1151 }
1152
1153 lbs_deb_leave(LBS_DEB_WEXT);
1154 return 0;
1155}
1156
1157static int lbs_set_mode(struct net_device *dev,
1158 struct iw_request_info *info, u32 * uwrq, char *extra)
1159{
1160 int ret = 0;
1161 struct lbs_private *priv = dev->ml_priv;
1162 struct assoc_request * assoc_req;
1163
1164 lbs_deb_enter(LBS_DEB_WEXT);
1165
1166 if ( (*uwrq != IW_MODE_ADHOC)
1167 && (*uwrq != IW_MODE_INFRA)
1168 && (*uwrq != IW_MODE_AUTO)) {
1169 lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq);
1170 ret = -EINVAL;
1171 goto out;
1172 }
1173
1174 mutex_lock(&priv->lock);
1175 assoc_req = lbs_get_association_request(priv);
1176 if (!assoc_req) {
1177 ret = -ENOMEM;
1178 lbs_cancel_association_work(priv);
1179 } else {
1180 assoc_req->mode = *uwrq;
1181 set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
1182 lbs_postpone_association_work(priv);
1183 lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
1184 }
1185 mutex_unlock(&priv->lock);
1186
1187out:
1188 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1189 return ret;
1190}
1191
1192
1193/**
1194 * @brief Get Encryption key
1195 *
1196 * @param dev A pointer to net_device structure
1197 * @param info A pointer to iw_request_info structure
1198 * @param vwrq A pointer to iw_param structure
1199 * @param extra A pointer to extra data buf
1200 * @return 0 --success, otherwise fail
1201 */
1202static int lbs_get_encode(struct net_device *dev,
1203 struct iw_request_info *info,
1204 struct iw_point *dwrq, u8 * extra)
1205{
1206 struct lbs_private *priv = dev->ml_priv;
1207 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1208
1209 lbs_deb_enter(LBS_DEB_WEXT);
1210
1211 lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n",
1212 dwrq->flags, index, dwrq->length, priv->wep_tx_keyidx);
1213
1214 dwrq->flags = 0;
1215
1216 /* Authentication method */
1217 switch (priv->secinfo.auth_mode) {
1218 case IW_AUTH_ALG_OPEN_SYSTEM:
1219 dwrq->flags = IW_ENCODE_OPEN;
1220 break;
1221
1222 case IW_AUTH_ALG_SHARED_KEY:
1223 case IW_AUTH_ALG_LEAP:
1224 dwrq->flags = IW_ENCODE_RESTRICTED;
1225 break;
1226 default:
1227 dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
1228 break;
1229 }
1230
1231 memset(extra, 0, 16);
1232
1233 mutex_lock(&priv->lock);
1234
1235 /* Default to returning current transmit key */
1236 if (index < 0)
1237 index = priv->wep_tx_keyidx;
1238
1239 if ((priv->wep_keys[index].len) && priv->secinfo.wep_enabled) {
1240 memcpy(extra, priv->wep_keys[index].key,
1241 priv->wep_keys[index].len);
1242 dwrq->length = priv->wep_keys[index].len;
1243
1244 dwrq->flags |= (index + 1);
1245 /* Return WEP enabled */
1246 dwrq->flags &= ~IW_ENCODE_DISABLED;
1247 } else if ((priv->secinfo.WPAenabled)
1248 || (priv->secinfo.WPA2enabled)) {
1249 /* return WPA enabled */
1250 dwrq->flags &= ~IW_ENCODE_DISABLED;
1251 dwrq->flags |= IW_ENCODE_NOKEY;
1252 } else {
1253 dwrq->flags |= IW_ENCODE_DISABLED;
1254 }
1255
1256 mutex_unlock(&priv->lock);
1257
1258 lbs_deb_wext("key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d\n",
1259 extra[0], extra[1], extra[2],
1260 extra[3], extra[4], extra[5], dwrq->length);
1261
1262 lbs_deb_wext("return flags 0x%x\n", dwrq->flags);
1263
1264 lbs_deb_leave(LBS_DEB_WEXT);
1265 return 0;
1266}
1267
1268/**
1269 * @brief Set Encryption key (internal)
1270 *
1271 * @param priv A pointer to private card structure
1272 * @param key_material A pointer to key material
1273 * @param key_length length of key material
1274 * @param index key index to set
1275 * @param set_tx_key Force set TX key (1 = yes, 0 = no)
1276 * @return 0 --success, otherwise fail
1277 */
1278static int lbs_set_wep_key(struct assoc_request *assoc_req,
1279 const char *key_material,
1280 u16 key_length,
1281 u16 index,
1282 int set_tx_key)
1283{
1284 int ret = 0;
1285 struct enc_key *pkey;
1286
1287 lbs_deb_enter(LBS_DEB_WEXT);
1288
1289 /* Paranoid validation of key index */
1290 if (index > 3) {
1291 ret = -EINVAL;
1292 goto out;
1293 }
1294
1295 /* validate max key length */
1296 if (key_length > KEY_LEN_WEP_104) {
1297 ret = -EINVAL;
1298 goto out;
1299 }
1300
1301 pkey = &assoc_req->wep_keys[index];
1302
1303 if (key_length > 0) {
1304 memset(pkey, 0, sizeof(struct enc_key));
1305 pkey->type = KEY_TYPE_ID_WEP;
1306
1307 /* Standardize the key length */
1308 pkey->len = (key_length > KEY_LEN_WEP_40) ?
1309 KEY_LEN_WEP_104 : KEY_LEN_WEP_40;
1310 memcpy(pkey->key, key_material, key_length);
1311 }
1312
1313 if (set_tx_key) {
1314 /* Ensure the chosen key is valid */
1315 if (!pkey->len) {
1316 lbs_deb_wext("key not set, so cannot enable it\n");
1317 ret = -EINVAL;
1318 goto out;
1319 }
1320 assoc_req->wep_tx_keyidx = index;
1321 }
1322
1323 assoc_req->secinfo.wep_enabled = 1;
1324
1325out:
1326 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1327 return ret;
1328}
1329
1330static int validate_key_index(u16 def_index, u16 raw_index,
1331 u16 *out_index, u16 *is_default)
1332{
1333 if (!out_index || !is_default)
1334 return -EINVAL;
1335
1336 /* Verify index if present, otherwise use default TX key index */
1337 if (raw_index > 0) {
1338 if (raw_index > 4)
1339 return -EINVAL;
1340 *out_index = raw_index - 1;
1341 } else {
1342 *out_index = def_index;
1343 *is_default = 1;
1344 }
1345 return 0;
1346}
1347
1348static void disable_wep(struct assoc_request *assoc_req)
1349{
1350 int i;
1351
1352 lbs_deb_enter(LBS_DEB_WEXT);
1353
1354 /* Set Open System auth mode */
1355 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1356
1357 /* Clear WEP keys and mark WEP as disabled */
1358 assoc_req->secinfo.wep_enabled = 0;
1359 for (i = 0; i < 4; i++)
1360 assoc_req->wep_keys[i].len = 0;
1361
1362 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1363 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1364
1365 lbs_deb_leave(LBS_DEB_WEXT);
1366}
1367
1368static void disable_wpa(struct assoc_request *assoc_req)
1369{
1370 lbs_deb_enter(LBS_DEB_WEXT);
1371
1372 memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key));
1373 assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
1374 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
1375
1376 memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key));
1377 assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
1378 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
1379
1380 assoc_req->secinfo.WPAenabled = 0;
1381 assoc_req->secinfo.WPA2enabled = 0;
1382 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1383
1384 lbs_deb_leave(LBS_DEB_WEXT);
1385}
1386
1387/**
1388 * @brief Set Encryption key
1389 *
1390 * @param dev A pointer to net_device structure
1391 * @param info A pointer to iw_request_info structure
1392 * @param vwrq A pointer to iw_param structure
1393 * @param extra A pointer to extra data buf
1394 * @return 0 --success, otherwise fail
1395 */
1396static int lbs_set_encode(struct net_device *dev,
1397 struct iw_request_info *info,
1398 struct iw_point *dwrq, char *extra)
1399{
1400 int ret = 0;
1401 struct lbs_private *priv = dev->ml_priv;
1402 struct assoc_request * assoc_req;
1403 u16 is_default = 0, index = 0, set_tx_key = 0;
1404
1405 lbs_deb_enter(LBS_DEB_WEXT);
1406
1407 mutex_lock(&priv->lock);
1408 assoc_req = lbs_get_association_request(priv);
1409 if (!assoc_req) {
1410 ret = -ENOMEM;
1411 goto out;
1412 }
1413
1414 if (dwrq->flags & IW_ENCODE_DISABLED) {
1415 disable_wep (assoc_req);
1416 disable_wpa (assoc_req);
1417 goto out;
1418 }
1419
1420 ret = validate_key_index(assoc_req->wep_tx_keyidx,
1421 (dwrq->flags & IW_ENCODE_INDEX),
1422 &index, &is_default);
1423 if (ret) {
1424 ret = -EINVAL;
1425 goto out;
1426 }
1427
1428 /* If WEP isn't enabled, or if there is no key data but a valid
1429 * index, set the TX key.
1430 */
1431 if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default))
1432 set_tx_key = 1;
1433
1434 ret = lbs_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key);
1435 if (ret)
1436 goto out;
1437
1438 if (dwrq->length)
1439 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1440 if (set_tx_key)
1441 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
1442
1443 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
1444 priv->authtype_auto = 0;
1445 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1446 } else if (dwrq->flags & IW_ENCODE_OPEN) {
1447 priv->authtype_auto = 0;
1448 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1449 }
1450
1451out:
1452 if (ret == 0) {
1453 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1454 lbs_postpone_association_work(priv);
1455 } else {
1456 lbs_cancel_association_work(priv);
1457 }
1458 mutex_unlock(&priv->lock);
1459
1460 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1461 return ret;
1462}
1463
1464/**
1465 * @brief Get Extended Encryption key (WPA/802.1x and WEP)
1466 *
1467 * @param dev A pointer to net_device structure
1468 * @param info A pointer to iw_request_info structure
1469 * @param vwrq A pointer to iw_param structure
1470 * @param extra A pointer to extra data buf
1471 * @return 0 on success, otherwise failure
1472 */
1473static int lbs_get_encodeext(struct net_device *dev,
1474 struct iw_request_info *info,
1475 struct iw_point *dwrq,
1476 char *extra)
1477{
1478 int ret = -EINVAL;
1479 struct lbs_private *priv = dev->ml_priv;
1480 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1481 int index, max_key_len;
1482
1483 lbs_deb_enter(LBS_DEB_WEXT);
1484
1485 max_key_len = dwrq->length - sizeof(*ext);
1486 if (max_key_len < 0)
1487 goto out;
1488
1489 index = dwrq->flags & IW_ENCODE_INDEX;
1490 if (index) {
1491 if (index < 1 || index > 4)
1492 goto out;
1493 index--;
1494 } else {
1495 index = priv->wep_tx_keyidx;
1496 }
1497
1498 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
1499 ext->alg != IW_ENCODE_ALG_WEP) {
1500 if (index != 0 || priv->mode != IW_MODE_INFRA)
1501 goto out;
1502 }
1503
1504 dwrq->flags = index + 1;
1505 memset(ext, 0, sizeof(*ext));
1506
1507 if ( !priv->secinfo.wep_enabled
1508 && !priv->secinfo.WPAenabled
1509 && !priv->secinfo.WPA2enabled) {
1510 ext->alg = IW_ENCODE_ALG_NONE;
1511 ext->key_len = 0;
1512 dwrq->flags |= IW_ENCODE_DISABLED;
1513 } else {
1514 u8 *key = NULL;
1515
1516 if ( priv->secinfo.wep_enabled
1517 && !priv->secinfo.WPAenabled
1518 && !priv->secinfo.WPA2enabled) {
1519 /* WEP */
1520 ext->alg = IW_ENCODE_ALG_WEP;
1521 ext->key_len = priv->wep_keys[index].len;
1522 key = &priv->wep_keys[index].key[0];
1523 } else if ( !priv->secinfo.wep_enabled
1524 && (priv->secinfo.WPAenabled ||
1525 priv->secinfo.WPA2enabled)) {
1526 /* WPA */
1527 struct enc_key * pkey = NULL;
1528
1529 if ( priv->wpa_mcast_key.len
1530 && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
1531 pkey = &priv->wpa_mcast_key;
1532 else if ( priv->wpa_unicast_key.len
1533 && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
1534 pkey = &priv->wpa_unicast_key;
1535
1536 if (pkey) {
1537 if (pkey->type == KEY_TYPE_ID_AES) {
1538 ext->alg = IW_ENCODE_ALG_CCMP;
1539 } else {
1540 ext->alg = IW_ENCODE_ALG_TKIP;
1541 }
1542 ext->key_len = pkey->len;
1543 key = &pkey->key[0];
1544 } else {
1545 ext->alg = IW_ENCODE_ALG_TKIP;
1546 ext->key_len = 0;
1547 }
1548 } else {
1549 goto out;
1550 }
1551
1552 if (ext->key_len > max_key_len) {
1553 ret = -E2BIG;
1554 goto out;
1555 }
1556
1557 if (ext->key_len)
1558 memcpy(ext->key, key, ext->key_len);
1559 else
1560 dwrq->flags |= IW_ENCODE_NOKEY;
1561 dwrq->flags |= IW_ENCODE_ENABLED;
1562 }
1563 ret = 0;
1564
1565out:
1566 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1567 return ret;
1568}
1569
1570/**
1571 * @brief Set Encryption key Extended (WPA/802.1x and WEP)
1572 *
1573 * @param dev A pointer to net_device structure
1574 * @param info A pointer to iw_request_info structure
1575 * @param vwrq A pointer to iw_param structure
1576 * @param extra A pointer to extra data buf
1577 * @return 0 --success, otherwise fail
1578 */
1579static int lbs_set_encodeext(struct net_device *dev,
1580 struct iw_request_info *info,
1581 struct iw_point *dwrq,
1582 char *extra)
1583{
1584 int ret = 0;
1585 struct lbs_private *priv = dev->ml_priv;
1586 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1587 int alg = ext->alg;
1588 struct assoc_request * assoc_req;
1589
1590 lbs_deb_enter(LBS_DEB_WEXT);
1591
1592 mutex_lock(&priv->lock);
1593 assoc_req = lbs_get_association_request(priv);
1594 if (!assoc_req) {
1595 ret = -ENOMEM;
1596 goto out;
1597 }
1598
1599 if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
1600 disable_wep (assoc_req);
1601 disable_wpa (assoc_req);
1602 } else if (alg == IW_ENCODE_ALG_WEP) {
1603 u16 is_default = 0, index, set_tx_key = 0;
1604
1605 ret = validate_key_index(assoc_req->wep_tx_keyidx,
1606 (dwrq->flags & IW_ENCODE_INDEX),
1607 &index, &is_default);
1608 if (ret)
1609 goto out;
1610
1611 /* If WEP isn't enabled, or if there is no key data but a valid
1612 * index, or if the set-TX-key flag was passed, set the TX key.
1613 */
1614 if ( !assoc_req->secinfo.wep_enabled
1615 || (dwrq->length == 0 && !is_default)
1616 || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
1617 set_tx_key = 1;
1618
1619 /* Copy key to driver */
1620 ret = lbs_set_wep_key(assoc_req, ext->key, ext->key_len, index,
1621 set_tx_key);
1622 if (ret)
1623 goto out;
1624
1625 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
1626 priv->authtype_auto = 0;
1627 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1628 } else if (dwrq->flags & IW_ENCODE_OPEN) {
1629 priv->authtype_auto = 0;
1630 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1631 }
1632
1633 /* Mark the various WEP bits as modified */
1634 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1635 if (dwrq->length)
1636 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1637 if (set_tx_key)
1638 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
1639 } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
1640 struct enc_key * pkey;
1641
1642 /* validate key length */
1643 if (((alg == IW_ENCODE_ALG_TKIP)
1644 && (ext->key_len != KEY_LEN_WPA_TKIP))
1645 || ((alg == IW_ENCODE_ALG_CCMP)
1646 && (ext->key_len != KEY_LEN_WPA_AES))) {
1647 lbs_deb_wext("invalid size %d for key of alg "
1648 "type %d\n",
1649 ext->key_len,
1650 alg);
1651 ret = -EINVAL;
1652 goto out;
1653 }
1654
1655 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1656 pkey = &assoc_req->wpa_mcast_key;
1657 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
1658 } else {
1659 pkey = &assoc_req->wpa_unicast_key;
1660 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
1661 }
1662
1663 memset(pkey, 0, sizeof (struct enc_key));
1664 memcpy(pkey->key, ext->key, ext->key_len);
1665 pkey->len = ext->key_len;
1666 if (pkey->len)
1667 pkey->flags |= KEY_INFO_WPA_ENABLED;
1668
1669 /* Do this after zeroing key structure */
1670 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1671 pkey->flags |= KEY_INFO_WPA_MCAST;
1672 } else {
1673 pkey->flags |= KEY_INFO_WPA_UNICAST;
1674 }
1675
1676 if (alg == IW_ENCODE_ALG_TKIP) {
1677 pkey->type = KEY_TYPE_ID_TKIP;
1678 } else if (alg == IW_ENCODE_ALG_CCMP) {
1679 pkey->type = KEY_TYPE_ID_AES;
1680 }
1681
1682 /* If WPA isn't enabled yet, do that now */
1683 if ( assoc_req->secinfo.WPAenabled == 0
1684 && assoc_req->secinfo.WPA2enabled == 0) {
1685 assoc_req->secinfo.WPAenabled = 1;
1686 assoc_req->secinfo.WPA2enabled = 1;
1687 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1688 }
1689
1690 /* Only disable wep if necessary: can't waste time here. */
1691 if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE)
1692 disable_wep(assoc_req);
1693 }
1694
1695out:
1696 if (ret == 0) {
1697 /* 802.1x and WPA rekeying must happen as quickly as possible,
1698 * especially during the 4-way handshake; thus if in
1699 * infrastructure mode, and either (a) 802.1x is enabled or
1700 * (b) WPA is being used, set the key right away.
1701 */
1702 if (assoc_req->mode == IW_MODE_INFRA &&
1703 ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) ||
1704 (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) ||
1705 assoc_req->secinfo.WPAenabled ||
1706 assoc_req->secinfo.WPA2enabled)) {
1707 lbs_do_association_work(priv);
1708 } else
1709 lbs_postpone_association_work(priv);
1710 } else {
1711 lbs_cancel_association_work(priv);
1712 }
1713 mutex_unlock(&priv->lock);
1714
1715 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1716 return ret;
1717}
1718
1719
1720static int lbs_set_genie(struct net_device *dev,
1721 struct iw_request_info *info,
1722 struct iw_point *dwrq,
1723 char *extra)
1724{
1725 struct lbs_private *priv = dev->ml_priv;
1726 int ret = 0;
1727 struct assoc_request * assoc_req;
1728
1729 lbs_deb_enter(LBS_DEB_WEXT);
1730
1731 mutex_lock(&priv->lock);
1732 assoc_req = lbs_get_association_request(priv);
1733 if (!assoc_req) {
1734 ret = -ENOMEM;
1735 goto out;
1736 }
1737
1738 if (dwrq->length > MAX_WPA_IE_LEN ||
1739 (dwrq->length && extra == NULL)) {
1740 ret = -EINVAL;
1741 goto out;
1742 }
1743
1744 if (dwrq->length) {
1745 memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length);
1746 assoc_req->wpa_ie_len = dwrq->length;
1747 } else {
1748 memset(&assoc_req->wpa_ie[0], 0, sizeof(priv->wpa_ie));
1749 assoc_req->wpa_ie_len = 0;
1750 }
1751
1752out:
1753 if (ret == 0) {
1754 set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags);
1755 lbs_postpone_association_work(priv);
1756 } else {
1757 lbs_cancel_association_work(priv);
1758 }
1759 mutex_unlock(&priv->lock);
1760
1761 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1762 return ret;
1763}
1764
1765static int lbs_get_genie(struct net_device *dev,
1766 struct iw_request_info *info,
1767 struct iw_point *dwrq,
1768 char *extra)
1769{
1770 int ret = 0;
1771 struct lbs_private *priv = dev->ml_priv;
1772
1773 lbs_deb_enter(LBS_DEB_WEXT);
1774
1775 if (priv->wpa_ie_len == 0) {
1776 dwrq->length = 0;
1777 goto out;
1778 }
1779
1780 if (dwrq->length < priv->wpa_ie_len) {
1781 ret = -E2BIG;
1782 goto out;
1783 }
1784
1785 dwrq->length = priv->wpa_ie_len;
1786 memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len);
1787
1788out:
1789 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1790 return ret;
1791}
1792
1793
1794static int lbs_set_auth(struct net_device *dev,
1795 struct iw_request_info *info,
1796 struct iw_param *dwrq,
1797 char *extra)
1798{
1799 struct lbs_private *priv = dev->ml_priv;
1800 struct assoc_request * assoc_req;
1801 int ret = 0;
1802 int updated = 0;
1803
1804 lbs_deb_enter(LBS_DEB_WEXT);
1805
1806 mutex_lock(&priv->lock);
1807 assoc_req = lbs_get_association_request(priv);
1808 if (!assoc_req) {
1809 ret = -ENOMEM;
1810 goto out;
1811 }
1812
1813 switch (dwrq->flags & IW_AUTH_INDEX) {
1814 case IW_AUTH_PRIVACY_INVOKED:
1815 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1816 case IW_AUTH_TKIP_COUNTERMEASURES:
1817 case IW_AUTH_CIPHER_PAIRWISE:
1818 case IW_AUTH_CIPHER_GROUP:
1819 case IW_AUTH_DROP_UNENCRYPTED:
1820 /*
1821 * libertas does not use these parameters
1822 */
1823 break;
1824
1825 case IW_AUTH_KEY_MGMT:
1826 assoc_req->secinfo.key_mgmt = dwrq->value;
1827 updated = 1;
1828 break;
1829
1830 case IW_AUTH_WPA_VERSION:
1831 if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
1832 assoc_req->secinfo.WPAenabled = 0;
1833 assoc_req->secinfo.WPA2enabled = 0;
1834 disable_wpa (assoc_req);
1835 }
1836 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
1837 assoc_req->secinfo.WPAenabled = 1;
1838 assoc_req->secinfo.wep_enabled = 0;
1839 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1840 }
1841 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) {
1842 assoc_req->secinfo.WPA2enabled = 1;
1843 assoc_req->secinfo.wep_enabled = 0;
1844 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1845 }
1846 updated = 1;
1847 break;
1848
1849 case IW_AUTH_80211_AUTH_ALG:
1850 if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
1851 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1852 } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1853 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1854 } else if (dwrq->value & IW_AUTH_ALG_LEAP) {
1855 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP;
1856 } else {
1857 ret = -EINVAL;
1858 }
1859 updated = 1;
1860 break;
1861
1862 case IW_AUTH_WPA_ENABLED:
1863 if (dwrq->value) {
1864 if (!assoc_req->secinfo.WPAenabled &&
1865 !assoc_req->secinfo.WPA2enabled) {
1866 assoc_req->secinfo.WPAenabled = 1;
1867 assoc_req->secinfo.WPA2enabled = 1;
1868 assoc_req->secinfo.wep_enabled = 0;
1869 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1870 }
1871 } else {
1872 assoc_req->secinfo.WPAenabled = 0;
1873 assoc_req->secinfo.WPA2enabled = 0;
1874 disable_wpa (assoc_req);
1875 }
1876 updated = 1;
1877 break;
1878
1879 default:
1880 ret = -EOPNOTSUPP;
1881 break;
1882 }
1883
1884out:
1885 if (ret == 0) {
1886 if (updated)
1887 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1888 lbs_postpone_association_work(priv);
1889 } else if (ret != -EOPNOTSUPP) {
1890 lbs_cancel_association_work(priv);
1891 }
1892 mutex_unlock(&priv->lock);
1893
1894 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1895 return ret;
1896}
1897
1898static int lbs_get_auth(struct net_device *dev,
1899 struct iw_request_info *info,
1900 struct iw_param *dwrq,
1901 char *extra)
1902{
1903 int ret = 0;
1904 struct lbs_private *priv = dev->ml_priv;
1905
1906 lbs_deb_enter(LBS_DEB_WEXT);
1907
1908 switch (dwrq->flags & IW_AUTH_INDEX) {
1909 case IW_AUTH_KEY_MGMT:
1910 dwrq->value = priv->secinfo.key_mgmt;
1911 break;
1912
1913 case IW_AUTH_WPA_VERSION:
1914 dwrq->value = 0;
1915 if (priv->secinfo.WPAenabled)
1916 dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
1917 if (priv->secinfo.WPA2enabled)
1918 dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
1919 if (!dwrq->value)
1920 dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
1921 break;
1922
1923 case IW_AUTH_80211_AUTH_ALG:
1924 dwrq->value = priv->secinfo.auth_mode;
1925 break;
1926
1927 case IW_AUTH_WPA_ENABLED:
1928 if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled)
1929 dwrq->value = 1;
1930 break;
1931
1932 default:
1933 ret = -EOPNOTSUPP;
1934 }
1935
1936 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1937 return ret;
1938}
1939
1940
1941static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
1942 struct iw_param *vwrq, char *extra)
1943{
1944 int ret = 0;
1945 struct lbs_private *priv = dev->ml_priv;
1946 s16 dbm = (s16) vwrq->value;
1947
1948 lbs_deb_enter(LBS_DEB_WEXT);
1949
1950 if (vwrq->disabled) {
1951 lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
1952 goto out;
1953 }
1954
1955 if (vwrq->fixed == 0) {
1956 /* User requests automatic tx power control, however there are
1957 * many auto tx settings. For now use firmware defaults until
1958 * we come up with a good way to expose these to the user. */
1959 if (priv->fwrelease < 0x09000000) {
1960 ret = lbs_set_power_adapt_cfg(priv, 1,
1961 POW_ADAPT_DEFAULT_P0,
1962 POW_ADAPT_DEFAULT_P1,
1963 POW_ADAPT_DEFAULT_P2);
1964 if (ret)
1965 goto out;
1966 }
1967 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
1968 TPC_DEFAULT_P2, 1);
1969 if (ret)
1970 goto out;
1971 dbm = priv->txpower_max;
1972 } else {
1973 /* Userspace check in iwrange if it should use dBm or mW,
1974 * therefore this should never happen... Jean II */
1975 if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
1976 ret = -EOPNOTSUPP;
1977 goto out;
1978 }
1979
1980 /* Validate requested power level against firmware allowed
1981 * levels */
1982 if (priv->txpower_min && (dbm < priv->txpower_min)) {
1983 ret = -EINVAL;
1984 goto out;
1985 }
1986
1987 if (priv->txpower_max && (dbm > priv->txpower_max)) {
1988 ret = -EINVAL;
1989 goto out;
1990 }
1991 if (priv->fwrelease < 0x09000000) {
1992 ret = lbs_set_power_adapt_cfg(priv, 0,
1993 POW_ADAPT_DEFAULT_P0,
1994 POW_ADAPT_DEFAULT_P1,
1995 POW_ADAPT_DEFAULT_P2);
1996 if (ret)
1997 goto out;
1998 }
1999 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
2000 TPC_DEFAULT_P2, 1);
2001 if (ret)
2002 goto out;
2003 }
2004
2005 /* If the radio was off, turn it on */
2006 if (!priv->radio_on) {
2007 ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1);
2008 if (ret)
2009 goto out;
2010 }
2011
2012 lbs_deb_wext("txpower set %d dBm\n", dbm);
2013
2014 ret = lbs_set_tx_power(priv, dbm);
2015
2016out:
2017 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2018 return ret;
2019}
2020
2021static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
2022 struct iw_point *dwrq, char *extra)
2023{
2024 struct lbs_private *priv = dev->ml_priv;
2025
2026 lbs_deb_enter(LBS_DEB_WEXT);
2027
2028 /*
2029 * Note : if dwrq->flags != 0, we should get the relevant SSID from
2030 * the SSID list...
2031 */
2032
2033 /*
2034 * Get the current SSID
2035 */
2036 if (priv->connect_status == LBS_CONNECTED) {
2037 memcpy(extra, priv->curbssparams.ssid,
2038 priv->curbssparams.ssid_len);
2039 } else {
2040 memset(extra, 0, 32);
2041 }
2042 /*
2043 * If none, we may want to get the one that was set
2044 */
2045
2046 dwrq->length = priv->curbssparams.ssid_len;
2047
2048 dwrq->flags = 1; /* active */
2049
2050 lbs_deb_leave(LBS_DEB_WEXT);
2051 return 0;
2052}
2053
2054static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
2055 struct iw_point *dwrq, char *extra)
2056{
2057 struct lbs_private *priv = dev->ml_priv;
2058 int ret = 0;
2059 u8 ssid[IEEE80211_MAX_SSID_LEN];
2060 u8 ssid_len = 0;
2061 struct assoc_request * assoc_req;
2062 int in_ssid_len = dwrq->length;
2063 DECLARE_SSID_BUF(ssid_buf);
2064
2065 lbs_deb_enter(LBS_DEB_WEXT);
2066
2067 if (!priv->radio_on) {
2068 ret = -EINVAL;
2069 goto out;
2070 }
2071
2072 /* Check the size of the string */
2073 if (in_ssid_len > IEEE80211_MAX_SSID_LEN) {
2074 ret = -E2BIG;
2075 goto out;
2076 }
2077
2078 memset(&ssid, 0, sizeof(ssid));
2079
2080 if (!dwrq->flags || !in_ssid_len) {
2081 /* "any" SSID requested; leave SSID blank */
2082 } else {
2083 /* Specific SSID requested */
2084 memcpy(&ssid, extra, in_ssid_len);
2085 ssid_len = in_ssid_len;
2086 }
2087
2088 if (!ssid_len) {
2089 lbs_deb_wext("requested any SSID\n");
2090 } else {
2091 lbs_deb_wext("requested SSID '%s'\n",
2092 print_ssid(ssid_buf, ssid, ssid_len));
2093 }
2094
2095out:
2096 mutex_lock(&priv->lock);
2097 if (ret == 0) {
2098 /* Get or create the current association request */
2099 assoc_req = lbs_get_association_request(priv);
2100 if (!assoc_req) {
2101 ret = -ENOMEM;
2102 } else {
2103 /* Copy the SSID to the association request */
2104 memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN);
2105 assoc_req->ssid_len = ssid_len;
2106 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
2107 lbs_postpone_association_work(priv);
2108 }
2109 }
2110
2111 /* Cancel the association request if there was an error */
2112 if (ret != 0) {
2113 lbs_cancel_association_work(priv);
2114 }
2115
2116 mutex_unlock(&priv->lock);
2117
2118 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2119 return ret;
2120}
2121
2122#ifdef CONFIG_LIBERTAS_MESH
2123static int lbs_mesh_get_essid(struct net_device *dev,
2124 struct iw_request_info *info,
2125 struct iw_point *dwrq, char *extra)
2126{
2127 struct lbs_private *priv = dev->ml_priv;
2128
2129 lbs_deb_enter(LBS_DEB_WEXT);
2130
2131 memcpy(extra, priv->mesh_ssid, priv->mesh_ssid_len);
2132
2133 dwrq->length = priv->mesh_ssid_len;
2134
2135 dwrq->flags = 1; /* active */
2136
2137 lbs_deb_leave(LBS_DEB_WEXT);
2138 return 0;
2139}
2140
2141static int lbs_mesh_set_essid(struct net_device *dev,
2142 struct iw_request_info *info,
2143 struct iw_point *dwrq, char *extra)
2144{
2145 struct lbs_private *priv = dev->ml_priv;
2146 int ret = 0;
2147
2148 lbs_deb_enter(LBS_DEB_WEXT);
2149
2150 if (!priv->radio_on) {
2151 ret = -EINVAL;
2152 goto out;
2153 }
2154
2155 /* Check the size of the string */
2156 if (dwrq->length > IEEE80211_MAX_SSID_LEN) {
2157 ret = -E2BIG;
2158 goto out;
2159 }
2160
2161 if (!dwrq->flags || !dwrq->length) {
2162 ret = -EINVAL;
2163 goto out;
2164 } else {
2165 /* Specific SSID requested */
2166 memcpy(priv->mesh_ssid, extra, dwrq->length);
2167 priv->mesh_ssid_len = dwrq->length;
2168 }
2169
2170 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
2171 priv->channel);
2172 out:
2173 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2174 return ret;
2175}
2176#endif
2177
2178/**
2179 * @brief Connect to the AP or Ad-hoc Network with specific bssid
2180 *
2181 * @param dev A pointer to net_device structure
2182 * @param info A pointer to iw_request_info structure
2183 * @param awrq A pointer to iw_param structure
2184 * @param extra A pointer to extra data buf
2185 * @return 0 --success, otherwise fail
2186 */
2187static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
2188 struct sockaddr *awrq, char *extra)
2189{
2190 struct lbs_private *priv = dev->ml_priv;
2191 struct assoc_request * assoc_req;
2192 int ret = 0;
2193
2194 lbs_deb_enter(LBS_DEB_WEXT);
2195
2196 if (!priv->radio_on)
2197 return -EINVAL;
2198
2199 if (awrq->sa_family != ARPHRD_ETHER)
2200 return -EINVAL;
2201
2202 lbs_deb_wext("ASSOC: WAP: sa_data %pM\n", awrq->sa_data);
2203
2204 mutex_lock(&priv->lock);
2205
2206 /* Get or create the current association request */
2207 assoc_req = lbs_get_association_request(priv);
2208 if (!assoc_req) {
2209 lbs_cancel_association_work(priv);
2210 ret = -ENOMEM;
2211 } else {
2212 /* Copy the BSSID to the association request */
2213 memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN);
2214 set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
2215 lbs_postpone_association_work(priv);
2216 }
2217
2218 mutex_unlock(&priv->lock);
2219
2220 return ret;
2221}
2222
2223/*
2224 * iwconfig settable callbacks
2225 */
2226static const iw_handler lbs_handler[] = {
2227 (iw_handler) NULL, /* SIOCSIWCOMMIT */
2228 (iw_handler) lbs_get_name, /* SIOCGIWNAME */
2229 (iw_handler) NULL, /* SIOCSIWNWID */
2230 (iw_handler) NULL, /* SIOCGIWNWID */
2231 (iw_handler) lbs_set_freq, /* SIOCSIWFREQ */
2232 (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */
2233 (iw_handler) lbs_set_mode, /* SIOCSIWMODE */
2234 (iw_handler) lbs_get_mode, /* SIOCGIWMODE */
2235 (iw_handler) NULL, /* SIOCSIWSENS */
2236 (iw_handler) NULL, /* SIOCGIWSENS */
2237 (iw_handler) NULL, /* SIOCSIWRANGE */
2238 (iw_handler) lbs_get_range, /* SIOCGIWRANGE */
2239 (iw_handler) NULL, /* SIOCSIWPRIV */
2240 (iw_handler) NULL, /* SIOCGIWPRIV */
2241 (iw_handler) NULL, /* SIOCSIWSTATS */
2242 (iw_handler) NULL, /* SIOCGIWSTATS */
2243 iw_handler_set_spy, /* SIOCSIWSPY */
2244 iw_handler_get_spy, /* SIOCGIWSPY */
2245 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2246 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2247 (iw_handler) lbs_set_wap, /* SIOCSIWAP */
2248 (iw_handler) lbs_get_wap, /* SIOCGIWAP */
2249 (iw_handler) NULL, /* SIOCSIWMLME */
2250 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
2251 (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
2252 (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
2253 (iw_handler) lbs_set_essid, /* SIOCSIWESSID */
2254 (iw_handler) lbs_get_essid, /* SIOCGIWESSID */
2255 (iw_handler) lbs_set_nick, /* SIOCSIWNICKN */
2256 (iw_handler) lbs_get_nick, /* SIOCGIWNICKN */
2257 (iw_handler) NULL, /* -- hole -- */
2258 (iw_handler) NULL, /* -- hole -- */
2259 (iw_handler) lbs_set_rate, /* SIOCSIWRATE */
2260 (iw_handler) lbs_get_rate, /* SIOCGIWRATE */
2261 (iw_handler) lbs_set_rts, /* SIOCSIWRTS */
2262 (iw_handler) lbs_get_rts, /* SIOCGIWRTS */
2263 (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */
2264 (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */
2265 (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */
2266 (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */
2267 (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */
2268 (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */
2269 (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */
2270 (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */
2271 (iw_handler) lbs_set_power, /* SIOCSIWPOWER */
2272 (iw_handler) lbs_get_power, /* SIOCGIWPOWER */
2273 (iw_handler) NULL, /* -- hole -- */
2274 (iw_handler) NULL, /* -- hole -- */
2275 (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */
2276 (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */
2277 (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */
2278 (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */
2279 (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
2280 (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
2281 (iw_handler) NULL, /* SIOCSIWPMKSA */
2282};
2283struct iw_handler_def lbs_handler_def = {
2284 .num_standard = ARRAY_SIZE(lbs_handler),
2285 .standard = (iw_handler *) lbs_handler,
2286 .get_wireless_stats = lbs_get_wireless_stats,
2287};
2288
2289#ifdef CONFIG_LIBERTAS_MESH
2290static const iw_handler mesh_wlan_handler[] = {
2291 (iw_handler) NULL, /* SIOCSIWCOMMIT */
2292 (iw_handler) lbs_get_name, /* SIOCGIWNAME */
2293 (iw_handler) NULL, /* SIOCSIWNWID */
2294 (iw_handler) NULL, /* SIOCGIWNWID */
2295 (iw_handler) lbs_mesh_set_freq, /* SIOCSIWFREQ */
2296 (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */
2297 (iw_handler) NULL, /* SIOCSIWMODE */
2298 (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */
2299 (iw_handler) NULL, /* SIOCSIWSENS */
2300 (iw_handler) NULL, /* SIOCGIWSENS */
2301 (iw_handler) NULL, /* SIOCSIWRANGE */
2302 (iw_handler) lbs_get_range, /* SIOCGIWRANGE */
2303 (iw_handler) NULL, /* SIOCSIWPRIV */
2304 (iw_handler) NULL, /* SIOCGIWPRIV */
2305 (iw_handler) NULL, /* SIOCSIWSTATS */
2306 (iw_handler) NULL, /* SIOCGIWSTATS */
2307 iw_handler_set_spy, /* SIOCSIWSPY */
2308 iw_handler_get_spy, /* SIOCGIWSPY */
2309 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2310 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2311 (iw_handler) NULL, /* SIOCSIWAP */
2312 (iw_handler) NULL, /* SIOCGIWAP */
2313 (iw_handler) NULL, /* SIOCSIWMLME */
2314 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
2315 (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
2316 (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
2317 (iw_handler) lbs_mesh_set_essid,/* SIOCSIWESSID */
2318 (iw_handler) lbs_mesh_get_essid,/* SIOCGIWESSID */
2319 (iw_handler) NULL, /* SIOCSIWNICKN */
2320 (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */
2321 (iw_handler) NULL, /* -- hole -- */
2322 (iw_handler) NULL, /* -- hole -- */
2323 (iw_handler) lbs_set_rate, /* SIOCSIWRATE */
2324 (iw_handler) lbs_get_rate, /* SIOCGIWRATE */
2325 (iw_handler) lbs_set_rts, /* SIOCSIWRTS */
2326 (iw_handler) lbs_get_rts, /* SIOCGIWRTS */
2327 (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */
2328 (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */
2329 (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */
2330 (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */
2331 (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */
2332 (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */
2333 (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */
2334 (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */
2335 (iw_handler) lbs_set_power, /* SIOCSIWPOWER */
2336 (iw_handler) lbs_get_power, /* SIOCGIWPOWER */
2337 (iw_handler) NULL, /* -- hole -- */
2338 (iw_handler) NULL, /* -- hole -- */
2339 (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */
2340 (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */
2341 (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */
2342 (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */
2343 (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
2344 (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
2345 (iw_handler) NULL, /* SIOCSIWPMKSA */
2346};
2347
2348struct iw_handler_def mesh_handler_def = {
2349 .num_standard = ARRAY_SIZE(mesh_wlan_handler),
2350 .standard = (iw_handler *) mesh_wlan_handler,
2351 .get_wireless_stats = lbs_get_wireless_stats,
2352};
2353#endif
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
deleted file mode 100644
index f3f19fe8c6c6..000000000000
--- a/drivers/net/wireless/libertas/wext.h
+++ /dev/null
@@ -1,17 +0,0 @@
1/**
2 * This file contains definition for IOCTL call.
3 */
4#ifndef _LBS_WEXT_H_
5#define _LBS_WEXT_H_
6
7void lbs_send_disconnect_notification(struct lbs_private *priv);
8void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
9
10struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
11 struct lbs_private *priv,
12 u8 band,
13 u16 channel);
14
15extern struct iw_handler_def lbs_handler_def;
16
17#endif
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 49a7dfb4809a..e7f299dc9ef5 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1291,6 +1291,11 @@ static int __init init_mac80211_hwsim(void)
1291 hw->wiphy->n_addresses = 2; 1291 hw->wiphy->n_addresses = 2;
1292 hw->wiphy->addresses = data->addresses; 1292 hw->wiphy->addresses = data->addresses;
1293 1293
1294 if (fake_hw_scan) {
1295 hw->wiphy->max_scan_ssids = 255;
1296 hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
1297 }
1298
1294 hw->channel_change_time = 1; 1299 hw->channel_change_time = 1;
1295 hw->queues = 4; 1300 hw->queues = 4;
1296 hw->wiphy->interface_modes = 1301 hw->wiphy->interface_modes =
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 5e7f344b000d..719573bbbf81 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -520,8 +520,9 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
520 520
521static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed); 521static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
522 522
523static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, 523static int rndis_set_tx_power(struct wiphy *wiphy,
524 int dbm); 524 enum nl80211_tx_power_setting type,
525 int mbm);
525static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm); 526static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
526 527
527static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, 528static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
@@ -1856,20 +1857,25 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1856 return 0; 1857 return 0;
1857} 1858}
1858 1859
1859static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, 1860static int rndis_set_tx_power(struct wiphy *wiphy,
1860 int dbm) 1861 enum nl80211_tx_power_setting type,
1862 int mbm)
1861{ 1863{
1862 struct rndis_wlan_private *priv = wiphy_priv(wiphy); 1864 struct rndis_wlan_private *priv = wiphy_priv(wiphy);
1863 struct usbnet *usbdev = priv->usbdev; 1865 struct usbnet *usbdev = priv->usbdev;
1864 1866
1865 netdev_dbg(usbdev->net, "%s(): type:0x%x dbm:%i\n", 1867 netdev_dbg(usbdev->net, "%s(): type:0x%x mbm:%i\n",
1866 __func__, type, dbm); 1868 __func__, type, mbm);
1869
1870 if (mbm < 0 || (mbm % 100))
1871 return -ENOTSUPP;
1867 1872
1868 /* Device doesn't support changing txpower after initialization, only 1873 /* Device doesn't support changing txpower after initialization, only
1869 * turn off/on radio. Support 'auto' mode and setting same dBm that is 1874 * turn off/on radio. Support 'auto' mode and setting same dBm that is
1870 * currently used. 1875 * currently used.
1871 */ 1876 */
1872 if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) { 1877 if (type == NL80211_TX_POWER_AUTOMATIC ||
1878 MBM_TO_DBM(mbm) == get_bcm4320_power_dbm(priv)) {
1873 if (!priv->radio_on) 1879 if (!priv->radio_on)
1874 disassociate(usbdev, true); /* turn on radio */ 1880 disassociate(usbdev, true); /* turn on radio */
1875 1881
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 1eb882e15fb4..3bedf566c8ee 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1229,7 +1229,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
1229 } 1229 }
1230 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); 1230 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
1231 1231
1232 rt2x00pci_txdone(entry, &txdesc); 1232 rt2x00lib_txdone(entry, &txdesc);
1233 } 1233 }
1234} 1234}
1235 1235
@@ -1588,7 +1588,6 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
1588 .reset_tuner = rt2400pci_reset_tuner, 1588 .reset_tuner = rt2400pci_reset_tuner,
1589 .link_tuner = rt2400pci_link_tuner, 1589 .link_tuner = rt2400pci_link_tuner,
1590 .write_tx_desc = rt2400pci_write_tx_desc, 1590 .write_tx_desc = rt2400pci_write_tx_desc,
1591 .write_tx_data = rt2x00pci_write_tx_data,
1592 .write_beacon = rt2400pci_write_beacon, 1591 .write_beacon = rt2400pci_write_beacon,
1593 .kick_tx_queue = rt2400pci_kick_tx_queue, 1592 .kick_tx_queue = rt2400pci_kick_tx_queue,
1594 .kill_tx_queue = rt2400pci_kill_tx_queue, 1593 .kill_tx_queue = rt2400pci_kill_tx_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index a29cb212f89a..69d231d83952 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1365,7 +1365,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
1365 } 1365 }
1366 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); 1366 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
1367 1367
1368 rt2x00pci_txdone(entry, &txdesc); 1368 rt2x00lib_txdone(entry, &txdesc);
1369 } 1369 }
1370} 1370}
1371 1371
@@ -1886,7 +1886,6 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
1886 .reset_tuner = rt2500pci_reset_tuner, 1886 .reset_tuner = rt2500pci_reset_tuner,
1887 .link_tuner = rt2500pci_link_tuner, 1887 .link_tuner = rt2500pci_link_tuner,
1888 .write_tx_desc = rt2500pci_write_tx_desc, 1888 .write_tx_desc = rt2500pci_write_tx_desc,
1889 .write_tx_data = rt2x00pci_write_tx_data,
1890 .write_beacon = rt2500pci_write_beacon, 1889 .write_beacon = rt2500pci_write_beacon,
1891 .kick_tx_queue = rt2500pci_kick_tx_queue, 1890 .kick_tx_queue = rt2500pci_kick_tx_queue,
1892 .kill_tx_queue = rt2500pci_kill_tx_queue, 1891 .kill_tx_queue = rt2500pci_kill_tx_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 002db646ae0b..44205526013f 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -347,6 +347,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
347{ 347{
348 u32 mask; 348 u32 mask;
349 u16 reg; 349 u16 reg;
350 enum cipher curr_cipher;
350 351
351 if (crypto->cmd == SET_KEY) { 352 if (crypto->cmd == SET_KEY) {
352 /* 353 /*
@@ -357,6 +358,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
357 mask = TXRX_CSR0_KEY_ID.bit_mask; 358 mask = TXRX_CSR0_KEY_ID.bit_mask;
358 359
359 rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg); 360 rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
361 curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
360 reg &= mask; 362 reg &= mask;
361 363
362 if (reg && reg == mask) 364 if (reg && reg == mask)
@@ -365,6 +367,14 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
365 reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); 367 reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
366 368
367 key->hw_key_idx += reg ? ffz(reg) : 0; 369 key->hw_key_idx += reg ? ffz(reg) : 0;
370 /*
371 * Hardware requires that all keys use the same cipher
372 * (e.g. TKIP-only, AES-only, but not TKIP+AES).
373 * If this is not the first key, compare the cipher with the
374 * first one and fall back to SW crypto if not the same.
375 */
376 if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
377 return -EOPNOTSUPP;
368 378
369 rt2500usb_register_multiwrite(rt2x00dev, reg, 379 rt2500usb_register_multiwrite(rt2x00dev, reg,
370 crypto->key, sizeof(crypto->key)); 380 crypto->key, sizeof(crypto->key));
@@ -1769,7 +1779,6 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
1769 .link_stats = rt2500usb_link_stats, 1779 .link_stats = rt2500usb_link_stats,
1770 .reset_tuner = rt2500usb_reset_tuner, 1780 .reset_tuner = rt2500usb_reset_tuner,
1771 .write_tx_desc = rt2500usb_write_tx_desc, 1781 .write_tx_desc = rt2500usb_write_tx_desc,
1772 .write_tx_data = rt2x00usb_write_tx_data,
1773 .write_beacon = rt2500usb_write_beacon, 1782 .write_beacon = rt2500usb_write_beacon,
1774 .get_tx_data_len = rt2500usb_get_tx_data_len, 1783 .get_tx_data_len = rt2500usb_get_tx_data_len,
1775 .kick_tx_queue = rt2x00usb_kick_tx_queue, 1784 .kick_tx_queue = rt2x00usb_kick_tx_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 14c361ae87be..d3cf0cc39500 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -99,8 +99,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
99 rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word); 99 rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
100 rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1); 100 rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
101 rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0); 101 rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
102 if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) 102 rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
103 rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
104 103
105 rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); 104 rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
106 } 105 }
@@ -128,8 +127,7 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
128 rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word); 127 rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
129 rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1); 128 rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
130 rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1); 129 rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
131 if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) 130 rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
132 rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
133 131
134 rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); 132 rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
135 133
@@ -432,6 +430,20 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
432} 430}
433EXPORT_SYMBOL(rt2800_write_beacon); 431EXPORT_SYMBOL(rt2800_write_beacon);
434 432
433static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
434 unsigned int beacon_base)
435{
436 int i;
437
438 /*
439 * For the Beacon base registers we only need to clear
440 * the whole TXWI which (when set to 0) will invalidate
441 * the entire beacon.
442 */
443 for (i = 0; i < TXWI_DESC_SIZE; i += sizeof(__le32))
444 rt2800_register_write(rt2x00dev, beacon_base + i, 0);
445}
446
435#ifdef CONFIG_RT2X00_LIB_DEBUGFS 447#ifdef CONFIG_RT2X00_LIB_DEBUGFS
436const struct rt2x00debug rt2800_rt2x00debug = { 448const struct rt2x00debug rt2800_rt2x00debug = {
437 .owner = THIS_MODULE, 449 .owner = THIS_MODULE,
@@ -733,19 +745,14 @@ EXPORT_SYMBOL_GPL(rt2800_config_filter);
733void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, 745void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
734 struct rt2x00intf_conf *conf, const unsigned int flags) 746 struct rt2x00intf_conf *conf, const unsigned int flags)
735{ 747{
736 unsigned int beacon_base;
737 u32 reg; 748 u32 reg;
738 749
739 if (flags & CONFIG_UPDATE_TYPE) { 750 if (flags & CONFIG_UPDATE_TYPE) {
740 /* 751 /*
741 * Clear current synchronisation setup. 752 * Clear current synchronisation setup.
742 * For the Beacon base registers we only need to clear
743 * the first byte since that byte contains the VALID and OWNER
744 * bits which (when set to 0) will invalidate the entire beacon.
745 */ 753 */
746 beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); 754 rt2800_clear_beacon(rt2x00dev,
747 rt2800_register_write(rt2x00dev, beacon_base, 0); 755 HW_BEACON_OFFSET(intf->beacon->entry_idx));
748
749 /* 756 /*
750 * Enable synchronisation. 757 * Enable synchronisation.
751 */ 758 */
@@ -768,8 +775,8 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
768 775
769 if (flags & CONFIG_UPDATE_BSSID) { 776 if (flags & CONFIG_UPDATE_BSSID) {
770 reg = le32_to_cpu(conf->bssid[1]); 777 reg = le32_to_cpu(conf->bssid[1]);
771 rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 0); 778 rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
772 rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0); 779 rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
773 conf->bssid[1] = cpu_to_le32(reg); 780 conf->bssid[1] = cpu_to_le32(reg);
774 781
775 rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, 782 rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
@@ -827,14 +834,12 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
827 switch ((int)ant->tx) { 834 switch ((int)ant->tx) {
828 case 1: 835 case 1:
829 rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); 836 rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
830 if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
831 rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
832 break; 837 break;
833 case 2: 838 case 2:
834 rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); 839 rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
835 break; 840 break;
836 case 3: 841 case 3:
837 /* Do nothing */ 842 rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
838 break; 843 break;
839 } 844 }
840 845
@@ -1565,18 +1570,15 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
1565 1570
1566 /* 1571 /*
1567 * Clear all beacons 1572 * Clear all beacons
1568 * For the Beacon base registers we only need to clear
1569 * the first byte since that byte contains the VALID and OWNER
1570 * bits which (when set to 0) will invalidate the entire beacon.
1571 */ 1573 */
1572 rt2800_register_write(rt2x00dev, HW_BEACON_BASE0, 0); 1574 rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0);
1573 rt2800_register_write(rt2x00dev, HW_BEACON_BASE1, 0); 1575 rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1);
1574 rt2800_register_write(rt2x00dev, HW_BEACON_BASE2, 0); 1576 rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2);
1575 rt2800_register_write(rt2x00dev, HW_BEACON_BASE3, 0); 1577 rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3);
1576 rt2800_register_write(rt2x00dev, HW_BEACON_BASE4, 0); 1578 rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4);
1577 rt2800_register_write(rt2x00dev, HW_BEACON_BASE5, 0); 1579 rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5);
1578 rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0); 1580 rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6);
1579 rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); 1581 rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7);
1580 1582
1581 if (rt2x00_is_usb(rt2x00dev)) { 1583 if (rt2x00_is_usb(rt2x00dev)) {
1582 rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg); 1584 rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
@@ -2185,6 +2187,8 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
2185 rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); 2187 rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
2186 rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); 2188 rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
2187 rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); 2189 rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
2190 rt2x00_set_field16(&word, EEPROM_NIC_ANT_DIVERSITY, 0);
2191 rt2x00_set_field16(&word, EEPROM_NIC_DAC_TEST, 0);
2188 rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); 2192 rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
2189 EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); 2193 EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
2190 } 2194 }
@@ -2192,6 +2196,10 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
2192 rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); 2196 rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
2193 if ((word & 0x00ff) == 0x00ff) { 2197 if ((word & 0x00ff) == 0x00ff) {
2194 rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); 2198 rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
2199 rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
2200 EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
2201 }
2202 if ((word & 0xff00) == 0xff00) {
2195 rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE, 2203 rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
2196 LED_MODE_TXRX_ACTIVITY); 2204 LED_MODE_TXRX_ACTIVITY);
2197 rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); 2205 rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
@@ -2199,7 +2207,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
2199 rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); 2207 rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
2200 rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); 2208 rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
2201 rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); 2209 rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
2202 EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); 2210 EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word);
2203 } 2211 }
2204 2212
2205 /* 2213 /*
@@ -2499,7 +2507,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2499 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 2507 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
2500 IEEE80211_HW_SIGNAL_DBM | 2508 IEEE80211_HW_SIGNAL_DBM |
2501 IEEE80211_HW_SUPPORTS_PS | 2509 IEEE80211_HW_SUPPORTS_PS |
2502 IEEE80211_HW_PS_NULLFUNC_STACK; 2510 IEEE80211_HW_PS_NULLFUNC_STACK |
2511 IEEE80211_HW_AMPDU_AGGREGATION;
2503 2512
2504 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 2513 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
2505 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 2514 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2559,12 +2568,15 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2559 IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 2568 IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
2560 IEEE80211_HT_CAP_GRN_FLD | 2569 IEEE80211_HT_CAP_GRN_FLD |
2561 IEEE80211_HT_CAP_SGI_20 | 2570 IEEE80211_HT_CAP_SGI_20 |
2562 IEEE80211_HT_CAP_SGI_40 | 2571 IEEE80211_HT_CAP_SGI_40;
2563 IEEE80211_HT_CAP_RX_STBC;
2564 2572
2565 if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2) 2573 if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2)
2566 spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; 2574 spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC;
2567 2575
2576 spec->ht.cap |=
2577 rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) <<
2578 IEEE80211_HT_CAP_RX_STBC_SHIFT;
2579
2568 spec->ht.ampdu_factor = 3; 2580 spec->ht.ampdu_factor = 3;
2569 spec->ht.ampdu_density = 4; 2581 spec->ht.ampdu_density = 4;
2570 spec->ht.mcs.tx_params = 2582 spec->ht.mcs.tx_params =
@@ -2751,6 +2763,35 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw)
2751 return tsf; 2763 return tsf;
2752} 2764}
2753 2765
2766static int rt2800_ampdu_action(struct ieee80211_hw *hw,
2767 struct ieee80211_vif *vif,
2768 enum ieee80211_ampdu_mlme_action action,
2769 struct ieee80211_sta *sta,
2770 u16 tid, u16 *ssn)
2771{
2772 int ret = 0;
2773
2774 switch (action) {
2775 case IEEE80211_AMPDU_RX_START:
2776 case IEEE80211_AMPDU_RX_STOP:
2777 /* we don't support RX aggregation yet */
2778 ret = -ENOTSUPP;
2779 break;
2780 case IEEE80211_AMPDU_TX_START:
2781 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
2782 break;
2783 case IEEE80211_AMPDU_TX_STOP:
2784 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
2785 break;
2786 case IEEE80211_AMPDU_TX_OPERATIONAL:
2787 break;
2788 default:
2789 WARNING((struct rt2x00_dev *)hw->priv, "Unknown AMPDU action\n");
2790 }
2791
2792 return ret;
2793}
2794
2754const struct ieee80211_ops rt2800_mac80211_ops = { 2795const struct ieee80211_ops rt2800_mac80211_ops = {
2755 .tx = rt2x00mac_tx, 2796 .tx = rt2x00mac_tx,
2756 .start = rt2x00mac_start, 2797 .start = rt2x00mac_start,
@@ -2768,6 +2809,7 @@ const struct ieee80211_ops rt2800_mac80211_ops = {
2768 .conf_tx = rt2800_conf_tx, 2809 .conf_tx = rt2800_conf_tx,
2769 .get_tsf = rt2800_get_tsf, 2810 .get_tsf = rt2800_get_tsf,
2770 .rfkill_poll = rt2x00mac_rfkill_poll, 2811 .rfkill_poll = rt2x00mac_rfkill_poll,
2812 .ampdu_action = rt2800_ampdu_action,
2771}; 2813};
2772EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); 2814EXPORT_SYMBOL_GPL(rt2800_mac80211_ops);
2773 2815
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index e5ea670a18db..6f11760117da 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -139,8 +139,18 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
139 eeprom.data = rt2x00dev; 139 eeprom.data = rt2x00dev;
140 eeprom.register_read = rt2800pci_eepromregister_read; 140 eeprom.register_read = rt2800pci_eepromregister_read;
141 eeprom.register_write = rt2800pci_eepromregister_write; 141 eeprom.register_write = rt2800pci_eepromregister_write;
142 eeprom.width = !rt2x00_get_field32(reg, E2PROM_CSR_TYPE) ? 142 switch (rt2x00_get_field32(reg, E2PROM_CSR_TYPE))
143 PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; 143 {
144 case 0:
145 eeprom.width = PCI_EEPROM_WIDTH_93C46;
146 break;
147 case 1:
148 eeprom.width = PCI_EEPROM_WIDTH_93C66;
149 break;
150 default:
151 eeprom.width = PCI_EEPROM_WIDTH_93C86;
152 break;
153 }
144 eeprom.reg_data_in = 0; 154 eeprom.reg_data_in = 0;
145 eeprom.reg_data_out = 0; 155 eeprom.reg_data_out = 0;
146 eeprom.reg_data_clock = 0; 156 eeprom.reg_data_clock = 0;
@@ -645,10 +655,12 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
645/* 655/*
646 * TX descriptor initialization 656 * TX descriptor initialization
647 */ 657 */
648static void rt2800pci_write_tx_datadesc(struct queue_entry* entry, 658static void rt2800pci_write_tx_data(struct queue_entry* entry,
649 struct txentry_desc *txdesc) 659 struct txentry_desc *txdesc)
650{ 660{
651 rt2800_write_txwi((__le32 *) entry->skb->data, txdesc); 661 __le32 *txwi = (__le32 *) entry->skb->data;
662
663 rt2800_write_txwi(txwi, txdesc);
652} 664}
653 665
654 666
@@ -905,7 +917,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
905 if (txdesc.retry) 917 if (txdesc.retry)
906 __set_bit(TXDONE_FALLBACK, &txdesc.flags); 918 __set_bit(TXDONE_FALLBACK, &txdesc.flags);
907 919
908 rt2x00pci_txdone(entry, &txdesc); 920 rt2x00lib_txdone(entry, &txdesc);
909 } 921 }
910} 922}
911 923
@@ -941,6 +953,12 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
941 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) 953 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
942 rt2800pci_txdone(rt2x00dev); 954 rt2800pci_txdone(rt2x00dev);
943 955
956 /*
957 * Current beacon was sent out, fetch the next one
958 */
959 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
960 rt2x00lib_beacondone(rt2x00dev);
961
944 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) 962 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
945 rt2800pci_wakeup(rt2x00dev); 963 rt2800pci_wakeup(rt2x00dev);
946 964
@@ -1044,8 +1062,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
1044 .reset_tuner = rt2800_reset_tuner, 1062 .reset_tuner = rt2800_reset_tuner,
1045 .link_tuner = rt2800_link_tuner, 1063 .link_tuner = rt2800_link_tuner,
1046 .write_tx_desc = rt2800pci_write_tx_desc, 1064 .write_tx_desc = rt2800pci_write_tx_desc,
1047 .write_tx_data = rt2x00pci_write_tx_data, 1065 .write_tx_data = rt2800pci_write_tx_data,
1048 .write_tx_datadesc = rt2800pci_write_tx_datadesc,
1049 .write_beacon = rt2800_write_beacon, 1066 .write_beacon = rt2800_write_beacon,
1050 .kick_tx_queue = rt2800pci_kick_tx_queue, 1067 .kick_tx_queue = rt2800pci_kick_tx_queue,
1051 .kill_tx_queue = rt2800pci_kill_tx_queue, 1068 .kill_tx_queue = rt2800pci_kill_tx_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index f18c12a19cc9..4f85f7b42441 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -430,21 +430,24 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
430/* 430/*
431 * TX descriptor initialization 431 * TX descriptor initialization
432 */ 432 */
433static void rt2800usb_write_tx_data(struct queue_entry* entry,
434 struct txentry_desc *txdesc)
435{
436 __le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
437
438 rt2800_write_txwi(txwi, txdesc);
439}
440
441
433static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, 442static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
434 struct sk_buff *skb, 443 struct sk_buff *skb,
435 struct txentry_desc *txdesc) 444 struct txentry_desc *txdesc)
436{ 445{
437 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 446 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
438 __le32 *txi = (__le32 *) skb->data; 447 __le32 *txi = (__le32 *) skb->data;
439 __le32 *txwi = (__le32 *) (skb->data + TXINFO_DESC_SIZE);
440 u32 word; 448 u32 word;
441 449
442 /* 450 /*
443 * Initialize TXWI descriptor
444 */
445 rt2800_write_txwi(txwi, txdesc);
446
447 /*
448 * Initialize TXINFO descriptor 451 * Initialize TXINFO descriptor
449 */ 452 */
450 rt2x00_desc_read(txi, 0, &word); 453 rt2x00_desc_read(txi, 0, &word);
@@ -652,7 +655,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
652 .reset_tuner = rt2800_reset_tuner, 655 .reset_tuner = rt2800_reset_tuner,
653 .link_tuner = rt2800_link_tuner, 656 .link_tuner = rt2800_link_tuner,
654 .write_tx_desc = rt2800usb_write_tx_desc, 657 .write_tx_desc = rt2800usb_write_tx_desc,
655 .write_tx_data = rt2x00usb_write_tx_data, 658 .write_tx_data = rt2800usb_write_tx_data,
656 .write_beacon = rt2800_write_beacon, 659 .write_beacon = rt2800_write_beacon,
657 .get_tx_data_len = rt2800usb_get_tx_data_len, 660 .get_tx_data_len = rt2800usb_get_tx_data_len,
658 .kick_tx_queue = rt2x00usb_kick_tx_queue, 661 .kick_tx_queue = rt2x00usb_kick_tx_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index e7acc6abfd89..788b0e452cc7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -550,10 +550,8 @@ struct rt2x00lib_ops {
550 void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, 550 void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
551 struct sk_buff *skb, 551 struct sk_buff *skb,
552 struct txentry_desc *txdesc); 552 struct txentry_desc *txdesc);
553 int (*write_tx_data) (struct queue_entry *entry, 553 void (*write_tx_data) (struct queue_entry *entry,
554 struct txentry_desc *txdesc); 554 struct txentry_desc *txdesc);
555 void (*write_tx_datadesc) (struct queue_entry *entry,
556 struct txentry_desc *txdesc);
557 void (*write_beacon) (struct queue_entry *entry, 555 void (*write_beacon) (struct queue_entry *entry,
558 struct txentry_desc *txdesc); 556 struct txentry_desc *txdesc);
559 int (*get_tx_data_len) (struct queue_entry *entry); 557 int (*get_tx_data_len) (struct queue_entry *entry);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 339cc84bf4fb..12ee7bdedd02 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -211,6 +211,21 @@ void rt2x00lib_txdone(struct queue_entry *entry,
211 bool success; 211 bool success;
212 212
213 /* 213 /*
214 * Unmap the skb.
215 */
216 rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
217
218 /*
219 * Remove the extra tx headroom from the skb.
220 */
221 skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom);
222
223 /*
224 * Signal that the TX descriptor is no longer in the skb.
225 */
226 skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
227
228 /*
214 * Remove L2 padding which was added during 229 * Remove L2 padding which was added during
215 */ 230 */
216 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) 231 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
@@ -286,6 +301,21 @@ void rt2x00lib_txdone(struct queue_entry *entry,
286 rt2x00dev->low_level_stats.dot11ACKFailureCount++; 301 rt2x00dev->low_level_stats.dot11ACKFailureCount++;
287 } 302 }
288 303
304 /*
305 * Every single frame has it's own tx status, hence report
306 * every frame as ampdu of size 1.
307 *
308 * TODO: if we can find out how many frames were aggregated
309 * by the hw we could provide the real ampdu_len to mac80211
310 * which would allow the rc algorithm to better decide on
311 * which rates are suitable.
312 */
313 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
314 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
315 tx_info->status.ampdu_len = 1;
316 tx_info->status.ampdu_ack_len = success ? 1 : 0;
317 }
318
289 if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { 319 if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
290 if (success) 320 if (success)
291 rt2x00dev->low_level_stats.dot11RTSSuccessCount++; 321 rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 0efbf5a6c254..2f8136cab7d8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -271,11 +271,11 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
271 271
272 /* 272 /*
273 * Link tuning should only be performed when 273 * Link tuning should only be performed when
274 * an active sta or master interface exists. 274 * an active sta interface exists. AP interfaces
275 * Single monitor mode interfaces should never have 275 * don't need link tuning and monitor mode interfaces
276 * work with link tuners. 276 * should never have to work with link tuners.
277 */ 277 */
278 if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count) 278 if (!rt2x00dev->intf_sta_count)
279 return; 279 return;
280 280
281 rt2x00link_reset_tuner(rt2x00dev, false); 281 rt2x00link_reset_tuner(rt2x00dev, false);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index abbd857ec759..3b838c0bf59f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -282,7 +282,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
282 * has been initialized. Otherwise the device can reset 282 * has been initialized. Otherwise the device can reset
283 * the MAC registers. 283 * the MAC registers.
284 */ 284 */
285 rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); 285 rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
286 intf->mac, intf->bssid);
286 287
287 /* 288 /*
288 * Some filters depend on the current working mode. We can force 289 * Some filters depend on the current working mode. We can force
@@ -562,7 +563,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
562{ 563{
563 struct rt2x00_dev *rt2x00dev = hw->priv; 564 struct rt2x00_dev *rt2x00dev = hw->priv;
564 struct rt2x00_intf *intf = vif_to_intf(vif); 565 struct rt2x00_intf *intf = vif_to_intf(vif);
565 int update_bssid = 0;
566 566
567 /* 567 /*
568 * mac80211 might be calling this function while we are trying 568 * mac80211 might be calling this function while we are trying
@@ -577,10 +577,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
577 * conf->bssid can be NULL if coming from the internal 577 * conf->bssid can be NULL if coming from the internal
578 * beacon update routine. 578 * beacon update routine.
579 */ 579 */
580 if (changes & BSS_CHANGED_BSSID) { 580 if (changes & BSS_CHANGED_BSSID)
581 update_bssid = 1;
582 memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); 581 memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN);
583 }
584 582
585 spin_unlock(&intf->lock); 583 spin_unlock(&intf->lock);
586 584
@@ -592,7 +590,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
592 */ 590 */
593 if (changes & BSS_CHANGED_BSSID) 591 if (changes & BSS_CHANGED_BSSID)
594 rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, 592 rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
595 update_bssid ? bss_conf->bssid : NULL); 593 bss_conf->bssid);
596 594
597 /* 595 /*
598 * Update the beacon. 596 * Update the beacon.
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 10eaffd12b1b..fc9da8358784 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -60,80 +60,6 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
60} 60}
61EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); 61EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
62 62
63/*
64 * TX data handlers.
65 */
66int rt2x00pci_write_tx_data(struct queue_entry *entry,
67 struct txentry_desc *txdesc)
68{
69 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
70
71 /*
72 * This should not happen, we already checked the entry
73 * was ours. When the hardware disagrees there has been
74 * a queue corruption!
75 */
76 if (unlikely(rt2x00dev->ops->lib->get_entry_state(entry))) {
77 ERROR(rt2x00dev,
78 "Corrupt queue %d, accessing entry which is not ours.\n"
79 "Please file bug report to %s.\n",
80 entry->queue->qid, DRV_PROJECT);
81 return -EINVAL;
82 }
83
84 /*
85 * Add the requested extra tx headroom in front of the skb.
86 */
87 skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom);
88 memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom);
89
90 /*
91 * Call the driver's write_tx_datadesc function, if it exists.
92 */
93 if (rt2x00dev->ops->lib->write_tx_datadesc)
94 rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc);
95
96 /*
97 * Map the skb to DMA.
98 */
99 if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
100 rt2x00queue_map_txskb(rt2x00dev, entry->skb);
101
102 return 0;
103}
104EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
105
106/*
107 * TX/RX data handlers.
108 */
109void rt2x00pci_txdone(struct queue_entry *entry,
110 struct txdone_entry_desc *txdesc)
111{
112 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
113 struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
114
115 /*
116 * Unmap the skb.
117 */
118 rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
119
120 /*
121 * Remove the extra tx headroom from the skb.
122 */
123 skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom);
124
125 /*
126 * Signal that the TX descriptor is no longer in the skb.
127 */
128 skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
129
130 /*
131 * Pass on to rt2x00lib.
132 */
133 rt2x00lib_txdone(entry, txdesc);
134}
135EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
136
137void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) 63void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
138{ 64{
139 struct data_queue *queue = rt2x00dev->rx; 65 struct data_queue *queue = rt2x00dev->rx;
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 00528b8a754d..b854d62ff99b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -86,16 +86,6 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
86 u32 *reg); 86 u32 *reg);
87 87
88/** 88/**
89 * rt2x00pci_write_tx_data - Initialize data for TX operation
90 * @entry: The entry where the frame is located
91 *
92 * This function will initialize the DMA and skb descriptor
93 * to prepare the entry for the actual TX operation.
94 */
95int rt2x00pci_write_tx_data(struct queue_entry *entry,
96 struct txentry_desc *txdesc);
97
98/**
99 * struct queue_entry_priv_pci: Per entry PCI specific information 89 * struct queue_entry_priv_pci: Per entry PCI specific information
100 * 90 *
101 * @desc: Pointer to device descriptor 91 * @desc: Pointer to device descriptor
@@ -109,14 +99,6 @@ struct queue_entry_priv_pci {
109}; 99};
110 100
111/** 101/**
112 * rt2x00pci_txdone - Handle TX done events.
113 * @entry: The queue entry for which a TX done event was received.
114 * @txdesc: The TX done descriptor for the entry.
115 */
116void rt2x00pci_txdone(struct queue_entry *entry,
117 struct txdone_entry_desc *txdesc);
118
119/**
120 * rt2x00pci_rxdone - Handle RX done events 102 * rt2x00pci_rxdone - Handle RX done events
121 * @rt2x00dev: Device pointer, see &struct rt2x00_dev. 103 * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
122 */ 104 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index f91637147116..5097fe0f9f51 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -404,6 +404,46 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
404 rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); 404 rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
405} 405}
406 406
407static int rt2x00queue_write_tx_data(struct queue_entry *entry,
408 struct txentry_desc *txdesc)
409{
410 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
411
412 /*
413 * This should not happen, we already checked the entry
414 * was ours. When the hardware disagrees there has been
415 * a queue corruption!
416 */
417 if (unlikely(rt2x00dev->ops->lib->get_entry_state &&
418 rt2x00dev->ops->lib->get_entry_state(entry))) {
419 ERROR(rt2x00dev,
420 "Corrupt queue %d, accessing entry which is not ours.\n"
421 "Please file bug report to %s.\n",
422 entry->queue->qid, DRV_PROJECT);
423 return -EINVAL;
424 }
425
426 /*
427 * Add the requested extra tx headroom in front of the skb.
428 */
429 skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom);
430 memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom);
431
432 /*
433 * Call the driver's write_tx_data function, if it exists.
434 */
435 if (rt2x00dev->ops->lib->write_tx_data)
436 rt2x00dev->ops->lib->write_tx_data(entry, txdesc);
437
438 /*
439 * Map the skb to DMA.
440 */
441 if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
442 rt2x00queue_map_txskb(rt2x00dev, entry->skb);
443
444 return 0;
445}
446
407static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, 447static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
408 struct txentry_desc *txdesc) 448 struct txentry_desc *txdesc)
409{ 449{
@@ -515,8 +555,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
515 * call failed. Since we always return NETDEV_TX_OK to mac80211, 555 * call failed. Since we always return NETDEV_TX_OK to mac80211,
516 * this frame will simply be dropped. 556 * this frame will simply be dropped.
517 */ 557 */
518 if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry, 558 if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
519 &txdesc))) {
520 clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); 559 clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
521 entry->skb = NULL; 560 entry->skb = NULL;
522 return -EIO; 561 return -EIO;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index b45bc24c3dae..a22837c560fd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -178,11 +178,6 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
178 return; 178 return;
179 179
180 /* 180 /*
181 * Remove the descriptor from the front of the skb.
182 */
183 skb_pull(entry->skb, entry->queue->desc_size);
184
185 /*
186 * Obtain the status about this packet. 181 * Obtain the status about this packet.
187 * Note that when the status is 0 it does not mean the 182 * Note that when the status is 0 it does not mean the
188 * frame was send out correctly. It only means the frame 183 * frame was send out correctly. It only means the frame
@@ -201,48 +196,28 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
201 rt2x00lib_txdone(entry, &txdesc); 196 rt2x00lib_txdone(entry, &txdesc);
202} 197}
203 198
204int rt2x00usb_write_tx_data(struct queue_entry *entry, 199static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
205 struct txentry_desc *txdesc)
206{ 200{
207 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 201 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
208 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); 202 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
209 struct queue_entry_priv_usb *entry_priv = entry->priv_data; 203 struct queue_entry_priv_usb *entry_priv = entry->priv_data;
210 u32 length; 204 u32 length;
211 205
212 /* 206 if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) {
213 * Add the descriptor in front of the skb. 207 /*
214 */ 208 * USB devices cannot blindly pass the skb->len as the
215 skb_push(entry->skb, entry->queue->desc_size); 209 * length of the data to usb_fill_bulk_urb. Pass the skb
216 memset(entry->skb->data, 0, entry->queue->desc_size); 210 * to the driver to determine what the length should be.
217 211 */
218 /* 212 length = rt2x00dev->ops->lib->get_tx_data_len(entry);
219 * USB devices cannot blindly pass the skb->len as the
220 * length of the data to usb_fill_bulk_urb. Pass the skb
221 * to the driver to determine what the length should be.
222 */
223 length = rt2x00dev->ops->lib->get_tx_data_len(entry);
224
225 usb_fill_bulk_urb(entry_priv->urb, usb_dev,
226 usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
227 entry->skb->data, length,
228 rt2x00usb_interrupt_txdone, entry);
229
230 /*
231 * Call the driver's write_tx_datadesc function, if it exists.
232 */
233 if (rt2x00dev->ops->lib->write_tx_datadesc)
234 rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc);
235
236 return 0;
237}
238EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
239 213
240static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) 214 usb_fill_bulk_urb(entry_priv->urb, usb_dev,
241{ 215 usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
242 struct queue_entry_priv_usb *entry_priv = entry->priv_data; 216 entry->skb->data, length,
217 rt2x00usb_interrupt_txdone, entry);
243 218
244 if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
245 usb_submit_urb(entry_priv->urb, GFP_ATOMIC); 219 usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
220 }
246} 221}
247 222
248void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, 223void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 255b81ef9530..2b7a1889e72f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -351,16 +351,6 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
351void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev); 351void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
352 352
353/** 353/**
354 * rt2x00usb_write_tx_data - Initialize URB for TX operation
355 * @entry: The entry where the frame is located
356 *
357 * This function will initialize the URB and skb descriptor
358 * to prepare the entry for the actual TX operation.
359 */
360int rt2x00usb_write_tx_data(struct queue_entry *entry,
361 struct txentry_desc *txdesc);
362
363/**
364 * struct queue_entry_priv_usb: Per entry USB specific information 354 * struct queue_entry_priv_usb: Per entry USB specific information
365 * 355 *
366 * @urb: Urb structure used for device communication. 356 * @urb: Urb structure used for device communication.
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 7ca383478eeb..0123fbc22ca2 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2108,7 +2108,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
2108 __set_bit(TXDONE_UNKNOWN, &txdesc.flags); 2108 __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
2109 txdesc.retry = 0; 2109 txdesc.retry = 0;
2110 2110
2111 rt2x00pci_txdone(entry_done, &txdesc); 2111 rt2x00lib_txdone(entry_done, &txdesc);
2112 entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); 2112 entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
2113 } 2113 }
2114 2114
@@ -2135,7 +2135,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
2135 if (txdesc.retry) 2135 if (txdesc.retry)
2136 __set_bit(TXDONE_FALLBACK, &txdesc.flags); 2136 __set_bit(TXDONE_FALLBACK, &txdesc.flags);
2137 2137
2138 rt2x00pci_txdone(entry, &txdesc); 2138 rt2x00lib_txdone(entry, &txdesc);
2139 } 2139 }
2140} 2140}
2141 2141
@@ -2200,6 +2200,12 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
2200 if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) 2200 if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
2201 rt61pci_wakeup(rt2x00dev); 2201 rt61pci_wakeup(rt2x00dev);
2202 2202
2203 /*
2204 * 5 - Beacon done interrupt.
2205 */
2206 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
2207 rt2x00lib_beacondone(rt2x00dev);
2208
2203 return IRQ_HANDLED; 2209 return IRQ_HANDLED;
2204} 2210}
2205 2211
@@ -2800,7 +2806,6 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
2800 .reset_tuner = rt61pci_reset_tuner, 2806 .reset_tuner = rt61pci_reset_tuner,
2801 .link_tuner = rt61pci_link_tuner, 2807 .link_tuner = rt61pci_link_tuner,
2802 .write_tx_desc = rt61pci_write_tx_desc, 2808 .write_tx_desc = rt61pci_write_tx_desc,
2803 .write_tx_data = rt2x00pci_write_tx_data,
2804 .write_beacon = rt61pci_write_beacon, 2809 .write_beacon = rt61pci_write_beacon,
2805 .kick_tx_queue = rt61pci_kick_tx_queue, 2810 .kick_tx_queue = rt61pci_kick_tx_queue,
2806 .kill_tx_queue = rt61pci_kill_tx_queue, 2811 .kill_tx_queue = rt61pci_kill_tx_queue,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index d06d90f003e7..286dd97e51d8 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2249,7 +2249,6 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
2249 .reset_tuner = rt73usb_reset_tuner, 2249 .reset_tuner = rt73usb_reset_tuner,
2250 .link_tuner = rt73usb_link_tuner, 2250 .link_tuner = rt73usb_link_tuner,
2251 .write_tx_desc = rt73usb_write_tx_desc, 2251 .write_tx_desc = rt73usb_write_tx_desc,
2252 .write_tx_data = rt2x00usb_write_tx_data,
2253 .write_beacon = rt73usb_write_beacon, 2252 .write_beacon = rt73usb_write_beacon,
2254 .get_tx_data_len = rt73usb_get_tx_data_len, 2253 .get_tx_data_len = rt73usb_get_tx_data_len,
2255 .kick_tx_queue = rt2x00usb_kick_tx_queue, 2254 .kick_tx_queue = rt2x00usb_kick_tx_queue,
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 515817de2905..42705028751d 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -671,7 +671,7 @@ static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
671 (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; 671 (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
672} 672}
673 673
674void rtl8180_beacon_work(struct work_struct *work) 674static void rtl8180_beacon_work(struct work_struct *work)
675{ 675{
676 struct rtl8180_vif *vif_priv = 676 struct rtl8180_vif *vif_priv =
677 container_of(work, struct rtl8180_vif, beacon_work.work); 677 container_of(work, struct rtl8180_vif, beacon_work.work);
diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
index a55c873e8b66..c4627cbdb8e0 100644
--- a/include/linux/eeprom_93cx6.h
+++ b/include/linux/eeprom_93cx6.h
@@ -30,6 +30,7 @@
30#define PCI_EEPROM_WIDTH_93C46 6 30#define PCI_EEPROM_WIDTH_93C46 6
31#define PCI_EEPROM_WIDTH_93C56 8 31#define PCI_EEPROM_WIDTH_93C56 8
32#define PCI_EEPROM_WIDTH_93C66 8 32#define PCI_EEPROM_WIDTH_93C66 8
33#define PCI_EEPROM_WIDTH_93C86 8
33#define PCI_EEPROM_WIDTH_OPCODE 3 34#define PCI_EEPROM_WIDTH_OPCODE 3
34#define PCI_EEPROM_WRITE_OPCODE 0x05 35#define PCI_EEPROM_WRITE_OPCODE 0x05
35#define PCI_EEPROM_READ_OPCODE 0x06 36#define PCI_EEPROM_READ_OPCODE 0x06
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 64fb32b93a28..2c8701687336 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -725,6 +725,12 @@ enum nl80211_commands {
725 * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations 725 * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
726 * connected to this BSS. 726 * connected to this BSS.
727 * 727 *
728 * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See
729 * &enum nl80211_tx_power_setting for possible values.
730 * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units.
731 * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
732 * for non-automatic settings.
733 *
728 * @NL80211_ATTR_MAX: highest attribute number currently defined 734 * @NL80211_ATTR_MAX: highest attribute number currently defined
729 * @__NL80211_ATTR_AFTER_LAST: internal use 735 * @__NL80211_ATTR_AFTER_LAST: internal use
730 */ 736 */
@@ -882,6 +888,9 @@ enum nl80211_attrs {
882 888
883 NL80211_ATTR_AP_ISOLATE, 889 NL80211_ATTR_AP_ISOLATE,
884 890
891 NL80211_ATTR_WIPHY_TX_POWER_SETTING,
892 NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
893
885 /* add attributes here, update the policy in nl80211.c */ 894 /* add attributes here, update the policy in nl80211.c */
886 895
887 __NL80211_ATTR_AFTER_LAST, 896 __NL80211_ATTR_AFTER_LAST,
@@ -1659,4 +1668,17 @@ enum nl80211_cqm_rssi_threshold_event {
1659 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, 1668 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
1660}; 1669};
1661 1670
1671
1672/**
1673 * enum nl80211_tx_power_setting - TX power adjustment
1674 * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
1675 * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter
1676 * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter
1677 */
1678enum nl80211_tx_power_setting {
1679 NL80211_TX_POWER_AUTOMATIC,
1680 NL80211_TX_POWER_LIMITED,
1681 NL80211_TX_POWER_FIXED,
1682};
1683
1662#endif /* __LINUX_NL80211_H */ 1684#endif /* __LINUX_NL80211_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9c45b905aefc..168fe530b214 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -875,19 +875,6 @@ enum wiphy_params_flags {
875 WIPHY_PARAM_COVERAGE_CLASS = 1 << 4, 875 WIPHY_PARAM_COVERAGE_CLASS = 1 << 4,
876}; 876};
877 877
878/**
879 * enum tx_power_setting - TX power adjustment
880 *
881 * @TX_POWER_AUTOMATIC: the dbm parameter is ignored
882 * @TX_POWER_LIMITED: limit TX power by the dbm parameter
883 * @TX_POWER_FIXED: fix TX power to the dbm parameter
884 */
885enum tx_power_setting {
886 TX_POWER_AUTOMATIC,
887 TX_POWER_LIMITED,
888 TX_POWER_FIXED,
889};
890
891/* 878/*
892 * cfg80211_bitrate_mask - masks for bitrate control 879 * cfg80211_bitrate_mask - masks for bitrate control
893 */ 880 */
@@ -1149,7 +1136,7 @@ struct cfg80211_ops {
1149 int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed); 1136 int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
1150 1137
1151 int (*set_tx_power)(struct wiphy *wiphy, 1138 int (*set_tx_power)(struct wiphy *wiphy,
1152 enum tx_power_setting type, int dbm); 1139 enum nl80211_tx_power_setting type, int mbm);
1153 int (*get_tx_power)(struct wiphy *wiphy, int *dbm); 1140 int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
1154 1141
1155 int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev, 1142 int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index fe1a3a603375..7f256e23c57f 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1271,6 +1271,15 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
1271 * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS 1271 * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS
1272 * enabled whenever user has enabled powersave. 1272 * enabled whenever user has enabled powersave.
1273 * 1273 *
1274 * Some hardware need to toggle a single shared antenna between WLAN and
1275 * Bluetooth to facilitate co-existence. These types of hardware set
1276 * limitations on the use of host controlled dynamic powersave whenever there
1277 * is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the
1278 * driver may request temporarily going into full power save, in order to
1279 * enable toggling the antenna between BT and WLAN. If the driver requests
1280 * disabling dynamic powersave, the @dynamic_ps_timeout value will be
1281 * temporarily set to zero until the driver re-enables dynamic powersave.
1282 *
1274 * Driver informs U-APSD client support by enabling 1283 * Driver informs U-APSD client support by enabling
1275 * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the 1284 * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
1276 * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS 1285 * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
@@ -2447,6 +2456,36 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
2447void ieee80211_connection_loss(struct ieee80211_vif *vif); 2456void ieee80211_connection_loss(struct ieee80211_vif *vif);
2448 2457
2449/** 2458/**
2459 * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
2460 *
2461 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
2462 *
2463 * Some hardware require full power save to manage simultaneous BT traffic
2464 * on the WLAN frequency. Full PSM is required periodically, whenever there are
2465 * burst of BT traffic. The hardware gets information of BT traffic via
2466 * hardware co-existence lines, and consequentially requests mac80211 to
2467 * (temporarily) enter full psm.
2468 * This function will only temporarily disable dynamic PS, not enable PSM if
2469 * it was not already enabled.
2470 * The driver must make sure to re-enable dynamic PS using
2471 * ieee80211_enable_dyn_ps() if the driver has disabled it.
2472 *
2473 */
2474void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif);
2475
2476/**
2477 * ieee80211_enable_dyn_ps - restore dynamic psm after being disabled
2478 *
2479 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
2480 *
2481 * This function restores dynamic PS after being temporarily disabled via
2482 * ieee80211_disable_dyn_ps(). Each ieee80211_disable_dyn_ps() call must
2483 * be coupled with an eventual call to this function.
2484 *
2485 */
2486void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif);
2487
2488/**
2450 * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring 2489 * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring
2451 * rssi threshold triggered 2490 * rssi threshold triggered
2452 * 2491 *
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 83eec7a8bd1f..4d6f8653ec88 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -69,6 +69,7 @@ endchoice
69 69
70config MAC80211_RC_DEFAULT 70config MAC80211_RC_DEFAULT
71 string 71 string
72 default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
72 default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL 73 default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
73 default "pid" if MAC80211_RC_DEFAULT_PID 74 default "pid" if MAC80211_RC_DEFAULT_PID
74 default "" 75 default ""
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ed8c9f5be94f..9eb02a340889 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -413,9 +413,6 @@ static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
413{ 413{
414 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 414 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
415 415
416 if (!local->ops->get_survey)
417 return -EOPNOTSUPP;
418
419 return drv_get_survey(local, idx, survey); 416 return drv_get_survey(local, idx, survey);
420} 417}
421 418
@@ -1329,28 +1326,28 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1329} 1326}
1330 1327
1331static int ieee80211_set_tx_power(struct wiphy *wiphy, 1328static int ieee80211_set_tx_power(struct wiphy *wiphy,
1332 enum tx_power_setting type, int dbm) 1329 enum nl80211_tx_power_setting type, int mbm)
1333{ 1330{
1334 struct ieee80211_local *local = wiphy_priv(wiphy); 1331 struct ieee80211_local *local = wiphy_priv(wiphy);
1335 struct ieee80211_channel *chan = local->hw.conf.channel; 1332 struct ieee80211_channel *chan = local->hw.conf.channel;
1336 u32 changes = 0; 1333 u32 changes = 0;
1337 1334
1338 switch (type) { 1335 switch (type) {
1339 case TX_POWER_AUTOMATIC: 1336 case NL80211_TX_POWER_AUTOMATIC:
1340 local->user_power_level = -1; 1337 local->user_power_level = -1;
1341 break; 1338 break;
1342 case TX_POWER_LIMITED: 1339 case NL80211_TX_POWER_LIMITED:
1343 if (dbm < 0) 1340 if (mbm < 0 || (mbm % 100))
1344 return -EINVAL; 1341 return -EOPNOTSUPP;
1345 local->user_power_level = dbm; 1342 local->user_power_level = MBM_TO_DBM(mbm);
1346 break; 1343 break;
1347 case TX_POWER_FIXED: 1344 case NL80211_TX_POWER_FIXED:
1348 if (dbm < 0) 1345 if (mbm < 0 || (mbm % 100))
1349 return -EINVAL; 1346 return -EOPNOTSUPP;
1350 /* TODO: move to cfg80211 when it knows the channel */ 1347 /* TODO: move to cfg80211 when it knows the channel */
1351 if (dbm > chan->max_power) 1348 if (MBM_TO_DBM(mbm) > chan->max_power)
1352 return -EINVAL; 1349 return -EINVAL;
1353 local->user_power_level = dbm; 1350 local->user_power_level = MBM_TO_DBM(mbm);
1354 break; 1351 break;
1355 } 1352 }
1356 1353
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index c33317320eee..14123dce544b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -375,9 +375,14 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
375 struct survey_info *survey) 375 struct survey_info *survey)
376{ 376{
377 int ret = -EOPNOTSUPP; 377 int ret = -EOPNOTSUPP;
378
379 trace_drv_get_survey(local, idx, survey);
380
378 if (local->ops->get_survey) 381 if (local->ops->get_survey)
379 ret = local->ops->get_survey(&local->hw, idx, survey); 382 ret = local->ops->get_survey(&local->hw, idx, survey);
380 /* trace_drv_get_survey(local, idx, survey, ret); */ 383
384 trace_drv_return_int(local, ret);
385
381 return ret; 386 return ret;
382} 387}
383 388
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 8da31caff931..5d5d2a974668 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -761,6 +761,28 @@ TRACE_EVENT(drv_ampdu_action,
761 ) 761 )
762); 762);
763 763
764TRACE_EVENT(drv_get_survey,
765 TP_PROTO(struct ieee80211_local *local, int idx,
766 struct survey_info *survey),
767
768 TP_ARGS(local, idx, survey),
769
770 TP_STRUCT__entry(
771 LOCAL_ENTRY
772 __field(int, idx)
773 ),
774
775 TP_fast_assign(
776 LOCAL_ASSIGN;
777 __entry->idx = idx;
778 ),
779
780 TP_printk(
781 LOCAL_PR_FMT " idx:%d",
782 LOCAL_PR_ARG, __entry->idx
783 )
784);
785
764TRACE_EVENT(drv_flush, 786TRACE_EVENT(drv_flush,
765 TP_PROTO(struct ieee80211_local *local, bool drop), 787 TP_PROTO(struct ieee80211_local *local, bool drop),
766 788
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 6f905f153ed7..a3649a86a784 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -855,6 +855,8 @@ struct ieee80211_local {
855 * this will override whatever chosen by mac80211 internally. 855 * this will override whatever chosen by mac80211 internally.
856 */ 856 */
857 int dynamic_ps_forced_timeout; 857 int dynamic_ps_forced_timeout;
858 int dynamic_ps_user_timeout;
859 bool disable_dynamic_ps;
858 860
859 int user_power_level; /* in dBm */ 861 int user_power_level; /* in dBm */
860 int power_constr_level; /* in dBm */ 862 int power_constr_level; /* in dBm */
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 3cd5f7b5d693..ea13a80a476c 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -65,7 +65,6 @@ void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
65{ 65{
66 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); 66 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
67 mesh_accept_plinks_update(sdata); 67 mesh_accept_plinks_update(sdata);
68 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
69} 68}
70 69
71static inline 70static inline
@@ -73,7 +72,6 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
73{ 72{
74 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); 73 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
75 mesh_accept_plinks_update(sdata); 74 mesh_accept_plinks_update(sdata);
76 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
77} 75}
78 76
79/** 77/**
@@ -115,7 +113,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
115} 113}
116 114
117/** 115/**
118 * mesh_plink_deactivate - deactivate mesh peer link 116 * __mesh_plink_deactivate - deactivate mesh peer link
119 * 117 *
120 * @sta: mesh peer link to deactivate 118 * @sta: mesh peer link to deactivate
121 * 119 *
@@ -123,18 +121,23 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
123 * 121 *
124 * Locking: the caller must hold sta->lock 122 * Locking: the caller must hold sta->lock
125 */ 123 */
126static void __mesh_plink_deactivate(struct sta_info *sta) 124static bool __mesh_plink_deactivate(struct sta_info *sta)
127{ 125{
128 struct ieee80211_sub_if_data *sdata = sta->sdata; 126 struct ieee80211_sub_if_data *sdata = sta->sdata;
127 bool deactivated = false;
129 128
130 if (sta->plink_state == PLINK_ESTAB) 129 if (sta->plink_state == PLINK_ESTAB) {
131 mesh_plink_dec_estab_count(sdata); 130 mesh_plink_dec_estab_count(sdata);
131 deactivated = true;
132 }
132 sta->plink_state = PLINK_BLOCKED; 133 sta->plink_state = PLINK_BLOCKED;
133 mesh_path_flush_by_nexthop(sta); 134 mesh_path_flush_by_nexthop(sta);
135
136 return deactivated;
134} 137}
135 138
136/** 139/**
137 * __mesh_plink_deactivate - deactivate mesh peer link 140 * mesh_plink_deactivate - deactivate mesh peer link
138 * 141 *
139 * @sta: mesh peer link to deactivate 142 * @sta: mesh peer link to deactivate
140 * 143 *
@@ -142,9 +145,15 @@ static void __mesh_plink_deactivate(struct sta_info *sta)
142 */ 145 */
143void mesh_plink_deactivate(struct sta_info *sta) 146void mesh_plink_deactivate(struct sta_info *sta)
144{ 147{
148 struct ieee80211_sub_if_data *sdata = sta->sdata;
149 bool deactivated;
150
145 spin_lock_bh(&sta->lock); 151 spin_lock_bh(&sta->lock);
146 __mesh_plink_deactivate(sta); 152 deactivated = __mesh_plink_deactivate(sta);
147 spin_unlock_bh(&sta->lock); 153 spin_unlock_bh(&sta->lock);
154
155 if (deactivated)
156 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
148} 157}
149 158
150static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, 159static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
@@ -381,10 +390,16 @@ int mesh_plink_open(struct sta_info *sta)
381 390
382void mesh_plink_block(struct sta_info *sta) 391void mesh_plink_block(struct sta_info *sta)
383{ 392{
393 struct ieee80211_sub_if_data *sdata = sta->sdata;
394 bool deactivated;
395
384 spin_lock_bh(&sta->lock); 396 spin_lock_bh(&sta->lock);
385 __mesh_plink_deactivate(sta); 397 deactivated = __mesh_plink_deactivate(sta);
386 sta->plink_state = PLINK_BLOCKED; 398 sta->plink_state = PLINK_BLOCKED;
387 spin_unlock_bh(&sta->lock); 399 spin_unlock_bh(&sta->lock);
400
401 if (deactivated)
402 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
388} 403}
389 404
390 405
@@ -397,6 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
397 enum plink_event event; 412 enum plink_event event;
398 enum plink_frame_type ftype; 413 enum plink_frame_type ftype;
399 size_t baselen; 414 size_t baselen;
415 bool deactivated;
400 u8 ie_len; 416 u8 ie_len;
401 u8 *baseaddr; 417 u8 *baseaddr;
402 __le16 plid, llid, reason; 418 __le16 plid, llid, reason;
@@ -651,8 +667,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
651 case CNF_ACPT: 667 case CNF_ACPT:
652 del_timer(&sta->plink_timer); 668 del_timer(&sta->plink_timer);
653 sta->plink_state = PLINK_ESTAB; 669 sta->plink_state = PLINK_ESTAB;
654 mesh_plink_inc_estab_count(sdata);
655 spin_unlock_bh(&sta->lock); 670 spin_unlock_bh(&sta->lock);
671 mesh_plink_inc_estab_count(sdata);
672 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
656 mpl_dbg("Mesh plink with %pM ESTABLISHED\n", 673 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
657 sta->sta.addr); 674 sta->sta.addr);
658 break; 675 break;
@@ -684,8 +701,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
684 case OPN_ACPT: 701 case OPN_ACPT:
685 del_timer(&sta->plink_timer); 702 del_timer(&sta->plink_timer);
686 sta->plink_state = PLINK_ESTAB; 703 sta->plink_state = PLINK_ESTAB;
687 mesh_plink_inc_estab_count(sdata);
688 spin_unlock_bh(&sta->lock); 704 spin_unlock_bh(&sta->lock);
705 mesh_plink_inc_estab_count(sdata);
706 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
689 mpl_dbg("Mesh plink with %pM ESTABLISHED\n", 707 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
690 sta->sta.addr); 708 sta->sta.addr);
691 mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, 709 mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
@@ -702,11 +720,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
702 case CLS_ACPT: 720 case CLS_ACPT:
703 reason = cpu_to_le16(MESH_CLOSE_RCVD); 721 reason = cpu_to_le16(MESH_CLOSE_RCVD);
704 sta->reason = reason; 722 sta->reason = reason;
705 __mesh_plink_deactivate(sta); 723 deactivated = __mesh_plink_deactivate(sta);
706 sta->plink_state = PLINK_HOLDING; 724 sta->plink_state = PLINK_HOLDING;
707 llid = sta->llid; 725 llid = sta->llid;
708 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); 726 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
709 spin_unlock_bh(&sta->lock); 727 spin_unlock_bh(&sta->lock);
728 if (deactivated)
729 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
710 mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, 730 mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
711 plid, reason); 731 plid, reason);
712 break; 732 break;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 85c3ca33333e..d1962650b254 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -478,6 +478,39 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
478 } 478 }
479} 479}
480 480
481void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
482{
483 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
484 struct ieee80211_local *local = sdata->local;
485 struct ieee80211_conf *conf = &local->hw.conf;
486
487 WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
488 !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
489 (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
490
491 local->disable_dynamic_ps = false;
492 conf->dynamic_ps_timeout = local->dynamic_ps_user_timeout;
493}
494EXPORT_SYMBOL(ieee80211_enable_dyn_ps);
495
496void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif)
497{
498 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
499 struct ieee80211_local *local = sdata->local;
500 struct ieee80211_conf *conf = &local->hw.conf;
501
502 WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
503 !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
504 (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
505
506 local->disable_dynamic_ps = true;
507 conf->dynamic_ps_timeout = 0;
508 del_timer_sync(&local->dynamic_ps_timer);
509 ieee80211_queue_work(&local->hw,
510 &local->dynamic_ps_enable_work);
511}
512EXPORT_SYMBOL(ieee80211_disable_dyn_ps);
513
481/* powersave */ 514/* powersave */
482static void ieee80211_enable_ps(struct ieee80211_local *local, 515static void ieee80211_enable_ps(struct ieee80211_local *local,
483 struct ieee80211_sub_if_data *sdata) 516 struct ieee80211_sub_if_data *sdata)
@@ -553,6 +586,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
553 found->u.mgd.associated->beacon_ies && 586 found->u.mgd.associated->beacon_ies &&
554 !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | 587 !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
555 IEEE80211_STA_CONNECTION_POLL))) { 588 IEEE80211_STA_CONNECTION_POLL))) {
589 struct ieee80211_conf *conf = &local->hw.conf;
556 s32 beaconint_us; 590 s32 beaconint_us;
557 591
558 if (latency < 0) 592 if (latency < 0)
@@ -575,7 +609,10 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
575 else 609 else
576 timeout = 100; 610 timeout = 100;
577 } 611 }
578 local->hw.conf.dynamic_ps_timeout = timeout; 612 local->dynamic_ps_user_timeout = timeout;
613 if (!local->disable_dynamic_ps)
614 conf->dynamic_ps_timeout =
615 local->dynamic_ps_user_timeout;
579 616
580 if (beaconint_us > latency) { 617 if (beaconint_us > latency) {
581 local->ps_sdata = NULL; 618 local->ps_sdata = NULL;
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 7a04951fcb1f..52c85036660d 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -328,7 +328,8 @@ minstrel_next_sample_idx(struct minstrel_ht_sta *mi)
328} 328}
329 329
330static void 330static void
331minstrel_downgrade_rate(struct minstrel_ht_sta *mi, int *idx, bool primary) 331minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
332 bool primary)
332{ 333{
333 int group, orig_group; 334 int group, orig_group;
334 335
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 696c0fc6e0b7..462d2b227ed5 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -29,6 +29,8 @@ struct mcs_group {
29 unsigned int duration[MCS_GROUP_RATES]; 29 unsigned int duration[MCS_GROUP_RATES];
30}; 30};
31 31
32extern const struct mcs_group minstrel_mcs_groups[];
33
32struct minstrel_rate_stats { 34struct minstrel_rate_stats {
33 /* current / last sampling period attempts/success counters */ 35 /* current / last sampling period attempts/success counters */
34 unsigned int attempts, last_attempts; 36 unsigned int attempts, last_attempts;
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 4fb3ccbd8b40..4a5a4b3e7799 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -14,8 +14,6 @@
14#include "rc80211_minstrel.h" 14#include "rc80211_minstrel.h"
15#include "rc80211_minstrel_ht.h" 15#include "rc80211_minstrel_ht.h"
16 16
17extern const struct mcs_group minstrel_mcs_groups[];
18
19static int 17static int
20minstrel_ht_stats_open(struct inode *inode, struct file *file) 18minstrel_ht_stats_open(struct inode *inode, struct file *file)
21{ 19{
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a8aa0f2411a2..fa0f37e4afe4 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -293,7 +293,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
293 skb2 = skb_clone(skb, GFP_ATOMIC); 293 skb2 = skb_clone(skb, GFP_ATOMIC);
294 if (skb2) { 294 if (skb2) {
295 skb2->dev = prev_dev; 295 skb2->dev = prev_dev;
296 netif_rx(skb2); 296 netif_receive_skb(skb2);
297 } 297 }
298 } 298 }
299 299
@@ -304,7 +304,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
304 304
305 if (prev_dev) { 305 if (prev_dev) {
306 skb->dev = prev_dev; 306 skb->dev = prev_dev;
307 netif_rx(skb); 307 netif_receive_skb(skb);
308 } else 308 } else
309 dev_kfree_skb(skb); 309 dev_kfree_skb(skb);
310 310
@@ -1578,7 +1578,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1578 /* deliver to local stack */ 1578 /* deliver to local stack */
1579 skb->protocol = eth_type_trans(skb, dev); 1579 skb->protocol = eth_type_trans(skb, dev);
1580 memset(skb->cb, 0, sizeof(skb->cb)); 1580 memset(skb->cb, 0, sizeof(skb->cb));
1581 netif_rx(skb); 1581 netif_receive_skb(skb);
1582 } 1582 }
1583 } 1583 }
1584 1584
@@ -2056,11 +2056,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2056 nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0, 2056 nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0,
2057 GFP_ATOMIC); 2057 GFP_ATOMIC);
2058 if (nskb) { 2058 if (nskb) {
2059 struct ieee80211_mgmt *mgmt = (void *)nskb->data; 2059 struct ieee80211_mgmt *nmgmt = (void *)nskb->data;
2060 2060
2061 mgmt->u.action.category |= 0x80; 2061 nmgmt->u.action.category |= 0x80;
2062 memcpy(mgmt->da, mgmt->sa, ETH_ALEN); 2062 memcpy(nmgmt->da, nmgmt->sa, ETH_ALEN);
2063 memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN); 2063 memcpy(nmgmt->sa, rx->sdata->vif.addr, ETH_ALEN);
2064 2064
2065 memset(nskb->cb, 0, sizeof(nskb->cb)); 2065 memset(nskb->cb, 0, sizeof(nskb->cb));
2066 2066
@@ -2244,7 +2244,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
2244 skb2 = skb_clone(skb, GFP_ATOMIC); 2244 skb2 = skb_clone(skb, GFP_ATOMIC);
2245 if (skb2) { 2245 if (skb2) {
2246 skb2->dev = prev_dev; 2246 skb2->dev = prev_dev;
2247 netif_rx(skb2); 2247 netif_receive_skb(skb2);
2248 } 2248 }
2249 } 2249 }
2250 2250
@@ -2255,7 +2255,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
2255 2255
2256 if (prev_dev) { 2256 if (prev_dev) {
2257 skb->dev = prev_dev; 2257 skb->dev = prev_dev;
2258 netif_rx(skb); 2258 netif_receive_skb(skb);
2259 skb = NULL; 2259 skb = NULL;
2260 } else 2260 } else
2261 goto out_free_skb; 2261 goto out_free_skb;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index e1b0be7a57b9..439c98d93a79 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -286,6 +286,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
286 local->scanning = 0; 286 local->scanning = 0;
287 local->scan_channel = NULL; 287 local->scan_channel = NULL;
288 288
289 drv_sw_scan_complete(local);
290
289 /* we only have to protect scan_req and hw/sw scan */ 291 /* we only have to protect scan_req and hw/sw scan */
290 mutex_unlock(&local->scan_mtx); 292 mutex_unlock(&local->scan_mtx);
291 293
@@ -295,8 +297,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
295 297
296 ieee80211_configure_filter(local); 298 ieee80211_configure_filter(local);
297 299
298 drv_sw_scan_complete(local);
299
300 ieee80211_offchannel_return(local, true); 300 ieee80211_offchannel_return(local, true);
301 301
302 done: 302 done:
@@ -734,7 +734,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
734{ 734{
735 struct ieee80211_local *local = sdata->local; 735 struct ieee80211_local *local = sdata->local;
736 int ret = -EBUSY; 736 int ret = -EBUSY;
737 enum nl80211_band band; 737 enum ieee80211_band band;
738 738
739 mutex_lock(&local->scan_mtx); 739 mutex_lock(&local->scan_mtx);
740 740
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 10d0fcb417ae..54262e72376d 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -427,20 +427,20 @@ void for_each_sta_info_type_check(struct ieee80211_local *local,
427{ 427{
428} 428}
429 429
430#define for_each_sta_info(local, _addr, sta, nxt) \ 430#define for_each_sta_info(local, _addr, _sta, nxt) \
431 for ( /* initialise loop */ \ 431 for ( /* initialise loop */ \
432 sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ 432 _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
433 nxt = sta ? rcu_dereference(sta->hnext) : NULL; \ 433 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
434 /* typecheck */ \ 434 /* typecheck */ \
435 for_each_sta_info_type_check(local, (_addr), sta, nxt), \ 435 for_each_sta_info_type_check(local, (_addr), _sta, nxt),\
436 /* continue condition */ \ 436 /* continue condition */ \
437 sta; \ 437 _sta; \
438 /* advance loop */ \ 438 /* advance loop */ \
439 sta = nxt, \ 439 _sta = nxt, \
440 nxt = sta ? rcu_dereference(sta->hnext) : NULL \ 440 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
441 ) \ 441 ) \
442 /* compare address and run code only if it matches */ \ 442 /* compare address and run code only if it matches */ \
443 if (memcmp(sta->sta.addr, (_addr), ETH_ALEN) == 0) 443 if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0)
444 444
445/* 445/*
446 * Get STA info by index, BROKEN! 446 * Get STA info by index, BROKEN!
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 34da67995d94..10caec5ea8fa 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -377,7 +377,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
377 skb2 = skb_clone(skb, GFP_ATOMIC); 377 skb2 = skb_clone(skb, GFP_ATOMIC);
378 if (skb2) { 378 if (skb2) {
379 skb2->dev = prev_dev; 379 skb2->dev = prev_dev;
380 netif_rx(skb2); 380 netif_receive_skb(skb2);
381 } 381 }
382 } 382 }
383 383
@@ -386,7 +386,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
386 } 386 }
387 if (prev_dev) { 387 if (prev_dev) {
388 skb->dev = prev_dev; 388 skb->dev = prev_dev;
389 netif_rx(skb); 389 netif_receive_skb(skb);
390 skb = NULL; 390 skb = NULL;
391 } 391 }
392 rcu_read_unlock(); 392 rcu_read_unlock();
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 37d0e0ab4432..47fcfd0eebc2 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -894,7 +894,7 @@ out_fail_pernet:
894} 894}
895subsys_initcall(cfg80211_init); 895subsys_initcall(cfg80211_init);
896 896
897static void cfg80211_exit(void) 897static void __exit cfg80211_exit(void)
898{ 898{
899 debugfs_remove(ieee80211_debugfs_dir); 899 debugfs_remove(ieee80211_debugfs_dir);
900 nl80211_exit(); 900 nl80211_exit();
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6b41d15c4a05..85285b43d374 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -153,6 +153,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
153 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, 153 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
154 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, 154 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
155 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 }, 155 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
156
157 [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 },
158 [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 },
156}; 159};
157 160
158/* policy for the attributes */ 161/* policy for the attributes */
@@ -869,6 +872,34 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
869 goto bad_res; 872 goto bad_res;
870 } 873 }
871 874
875 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
876 enum nl80211_tx_power_setting type;
877 int idx, mbm = 0;
878
879 if (!rdev->ops->set_tx_power) {
880 return -EOPNOTSUPP;
881 goto bad_res;
882 }
883
884 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
885 type = nla_get_u32(info->attrs[idx]);
886
887 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
888 (type != NL80211_TX_POWER_AUTOMATIC)) {
889 result = -EINVAL;
890 goto bad_res;
891 }
892
893 if (type != NL80211_TX_POWER_AUTOMATIC) {
894 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
895 mbm = nla_get_u32(info->attrs[idx]);
896 }
897
898 result = rdev->ops->set_tx_power(&rdev->wiphy, type, mbm);
899 if (result)
900 goto bad_res;
901 }
902
872 changed = 0; 903 changed = 0;
873 904
874 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { 905 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 8f0d97dd3109..1ac2bdd46ecf 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -80,7 +80,7 @@ static const struct ieee80211_regdomain *country_ie_regdomain;
80 * - country_ie_regdomain 80 * - country_ie_regdomain
81 * - last_request 81 * - last_request
82 */ 82 */
83DEFINE_MUTEX(reg_mutex); 83static DEFINE_MUTEX(reg_mutex);
84#define assert_reg_lock() WARN_ON(!mutex_is_locked(&reg_mutex)) 84#define assert_reg_lock() WARN_ON(!mutex_is_locked(&reg_mutex))
85 85
86/* Used to queue up regulatory hints */ 86/* Used to queue up regulatory hints */
@@ -2630,7 +2630,7 @@ out:
2630 mutex_unlock(&reg_mutex); 2630 mutex_unlock(&reg_mutex);
2631} 2631}
2632 2632
2633int regulatory_init(void) 2633int __init regulatory_init(void)
2634{ 2634{
2635 int err = 0; 2635 int err = 0;
2636 2636
@@ -2676,7 +2676,7 @@ int regulatory_init(void)
2676 return 0; 2676 return 0;
2677} 2677}
2678 2678
2679void regulatory_exit(void) 2679void /* __init_or_exit */ regulatory_exit(void)
2680{ 2680{
2681 struct regulatory_request *reg_request, *tmp; 2681 struct regulatory_request *reg_request, *tmp;
2682 struct reg_beacon *reg_beacon, *btmp; 2682 struct reg_beacon *reg_beacon, *btmp;
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index b26224a9f3bc..c4695d07af23 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -10,7 +10,7 @@ int regulatory_hint_user(const char *alpha2);
10 10
11void reg_device_remove(struct wiphy *wiphy); 11void reg_device_remove(struct wiphy *wiphy);
12 12
13int regulatory_init(void); 13int __init regulatory_init(void);
14void regulatory_exit(void); 14void regulatory_exit(void);
15 15
16int set_regdom(const struct ieee80211_regdomain *rd); 16int set_regdom(const struct ieee80211_regdomain *rd);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 96342993cf93..1ff1e9f49136 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -829,7 +829,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
829{ 829{
830 struct wireless_dev *wdev = dev->ieee80211_ptr; 830 struct wireless_dev *wdev = dev->ieee80211_ptr;
831 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 831 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
832 enum tx_power_setting type; 832 enum nl80211_tx_power_setting type;
833 int dbm = 0; 833 int dbm = 0;
834 834
835 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) 835 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
@@ -852,7 +852,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
852 if (data->txpower.value < 0) 852 if (data->txpower.value < 0)
853 return -EINVAL; 853 return -EINVAL;
854 dbm = data->txpower.value; 854 dbm = data->txpower.value;
855 type = TX_POWER_FIXED; 855 type = NL80211_TX_POWER_FIXED;
856 /* TODO: do regulatory check! */ 856 /* TODO: do regulatory check! */
857 } else { 857 } else {
858 /* 858 /*
@@ -860,10 +860,10 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
860 * passed in from userland. 860 * passed in from userland.
861 */ 861 */
862 if (data->txpower.value < 0) { 862 if (data->txpower.value < 0) {
863 type = TX_POWER_AUTOMATIC; 863 type = NL80211_TX_POWER_AUTOMATIC;
864 } else { 864 } else {
865 dbm = data->txpower.value; 865 dbm = data->txpower.value;
866 type = TX_POWER_LIMITED; 866 type = NL80211_TX_POWER_LIMITED;
867 } 867 }
868 } 868 }
869 } else { 869 } else {
@@ -872,7 +872,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
872 return 0; 872 return 0;
873 } 873 }
874 874
875 return rdev->ops->set_tx_power(wdev->wiphy, type, dbm); 875 return rdev->ops->set_tx_power(wdev->wiphy, type, DBM_TO_MBM(dbm));
876} 876}
877EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower); 877EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);
878 878