diff options
96 files changed, 2758 insertions, 797 deletions
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 2232232b7989..d032bba9bc4c 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c | |||
| @@ -65,6 +65,32 @@ void rndis_status(struct usbnet *dev, struct urb *urb) | |||
| 65 | EXPORT_SYMBOL_GPL(rndis_status); | 65 | EXPORT_SYMBOL_GPL(rndis_status); |
| 66 | 66 | ||
| 67 | /* | 67 | /* |
| 68 | * RNDIS indicate messages. | ||
| 69 | */ | ||
| 70 | static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg, | ||
| 71 | int buflen) | ||
| 72 | { | ||
| 73 | struct cdc_state *info = (void *)&dev->data; | ||
| 74 | struct device *udev = &info->control->dev; | ||
| 75 | |||
| 76 | if (dev->driver_info->indication) { | ||
| 77 | dev->driver_info->indication(dev, msg, buflen); | ||
| 78 | } else { | ||
| 79 | switch (msg->status) { | ||
| 80 | case RNDIS_STATUS_MEDIA_CONNECT: | ||
| 81 | dev_info(udev, "rndis media connect\n"); | ||
| 82 | break; | ||
| 83 | case RNDIS_STATUS_MEDIA_DISCONNECT: | ||
| 84 | dev_info(udev, "rndis media disconnect\n"); | ||
| 85 | break; | ||
| 86 | default: | ||
| 87 | dev_info(udev, "rndis indication: 0x%08x\n", | ||
| 88 | le32_to_cpu(msg->status)); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | /* | ||
| 68 | * RPC done RNDIS-style. Caller guarantees: | 94 | * RPC done RNDIS-style. Caller guarantees: |
| 69 | * - message is properly byteswapped | 95 | * - message is properly byteswapped |
| 70 | * - there's no other request pending | 96 | * - there's no other request pending |
| @@ -143,27 +169,9 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) | |||
| 143 | request_id, xid); | 169 | request_id, xid); |
| 144 | /* then likely retry */ | 170 | /* then likely retry */ |
| 145 | } else switch (buf->msg_type) { | 171 | } else switch (buf->msg_type) { |
| 146 | case RNDIS_MSG_INDICATE: { /* fault/event */ | 172 | case RNDIS_MSG_INDICATE: /* fault/event */ |
| 147 | struct rndis_indicate *msg = (void *)buf; | 173 | rndis_msg_indicate(dev, (void *)buf, buflen); |
| 148 | int state = 0; | 174 | |
| 149 | |||
| 150 | switch (msg->status) { | ||
| 151 | case RNDIS_STATUS_MEDIA_CONNECT: | ||
| 152 | state = 1; | ||
| 153 | case RNDIS_STATUS_MEDIA_DISCONNECT: | ||
| 154 | dev_info(&info->control->dev, | ||
| 155 | "rndis media %sconnect\n", | ||
| 156 | !state?"dis":""); | ||
| 157 | if (dev->driver_info->link_change) | ||
| 158 | dev->driver_info->link_change( | ||
| 159 | dev, state); | ||
| 160 | break; | ||
| 161 | default: | ||
| 162 | dev_info(&info->control->dev, | ||
| 163 | "rndis indication: 0x%08x\n", | ||
| 164 | le32_to_cpu(msg->status)); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | break; | 175 | break; |
| 168 | case RNDIS_MSG_KEEPALIVE: { /* ping */ | 176 | case RNDIS_MSG_KEEPALIVE: { /* ping */ |
| 169 | struct rndis_keepalive_c *msg = (void *)buf; | 177 | struct rndis_keepalive_c *msg = (void *)buf; |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 25e435c49040..af1fe4696509 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
| @@ -601,21 +601,25 @@ int usbnet_stop (struct net_device *net) | |||
| 601 | info->description); | 601 | info->description); |
| 602 | } | 602 | } |
| 603 | 603 | ||
| 604 | // ensure there are no more active urbs | 604 | if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) { |
| 605 | add_wait_queue (&unlink_wakeup, &wait); | 605 | /* ensure there are no more active urbs */ |
| 606 | dev->wait = &unlink_wakeup; | 606 | add_wait_queue(&unlink_wakeup, &wait); |
| 607 | temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq); | 607 | dev->wait = &unlink_wakeup; |
| 608 | 608 | temp = unlink_urbs(dev, &dev->txq) + | |
| 609 | // maybe wait for deletions to finish. | 609 | unlink_urbs(dev, &dev->rxq); |
| 610 | while (!skb_queue_empty(&dev->rxq) | 610 | |
| 611 | && !skb_queue_empty(&dev->txq) | 611 | /* maybe wait for deletions to finish. */ |
| 612 | && !skb_queue_empty(&dev->done)) { | 612 | while (!skb_queue_empty(&dev->rxq) |
| 613 | msleep(UNLINK_TIMEOUT_MS); | 613 | && !skb_queue_empty(&dev->txq) |
| 614 | if (netif_msg_ifdown (dev)) | 614 | && !skb_queue_empty(&dev->done)) { |
| 615 | devdbg (dev, "waited for %d urb completions", temp); | 615 | msleep(UNLINK_TIMEOUT_MS); |
| 616 | if (netif_msg_ifdown(dev)) | ||
| 617 | devdbg(dev, "waited for %d urb completions", | ||
| 618 | temp); | ||
| 619 | } | ||
| 620 | dev->wait = NULL; | ||
| 621 | remove_wait_queue(&unlink_wakeup, &wait); | ||
| 616 | } | 622 | } |
| 617 | dev->wait = NULL; | ||
| 618 | remove_wait_queue (&unlink_wakeup, &wait); | ||
| 619 | 623 | ||
| 620 | usb_kill_urb(dev->interrupt); | 624 | usb_kill_urb(dev->interrupt); |
| 621 | 625 | ||
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index ca7a8a31d0b9..dda7cc2e1f57 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | menu "Wireless LAN" | 5 | menu "Wireless LAN" |
| 6 | depends on !S390 | 6 | depends on !S390 |
| 7 | 7 | ||
| 8 | config WLAN_PRE80211 | 8 | menuconfig WLAN_PRE80211 |
| 9 | bool "Wireless LAN (pre-802.11)" | 9 | bool "Wireless LAN (pre-802.11)" |
| 10 | depends on NETDEVICES | 10 | depends on NETDEVICES |
| 11 | ---help--- | 11 | ---help--- |
| @@ -101,7 +101,7 @@ config PCMCIA_NETWAVE | |||
| 101 | called netwave_cs. If unsure, say N. | 101 | called netwave_cs. If unsure, say N. |
| 102 | 102 | ||
| 103 | 103 | ||
| 104 | config WLAN_80211 | 104 | menuconfig WLAN_80211 |
| 105 | bool "Wireless LAN (IEEE 802.11)" | 105 | bool "Wireless LAN (IEEE 802.11)" |
| 106 | depends on NETDEVICES | 106 | depends on NETDEVICES |
| 107 | ---help--- | 107 | ---help--- |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 13303fa34734..7218dbabad3e 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
| @@ -1773,6 +1773,9 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw) | |||
| 1773 | 1773 | ||
| 1774 | at76_dbg(DBG_MAC80211, "%s()", __func__); | 1774 | at76_dbg(DBG_MAC80211, "%s()", __func__); |
| 1775 | 1775 | ||
| 1776 | cancel_delayed_work(&priv->dwork_hw_scan); | ||
| 1777 | cancel_work_sync(&priv->work_set_promisc); | ||
| 1778 | |||
| 1776 | mutex_lock(&priv->mtx); | 1779 | mutex_lock(&priv->mtx); |
| 1777 | 1780 | ||
| 1778 | if (!priv->device_unplugged) { | 1781 | if (!priv->device_unplugged) { |
| @@ -1872,8 +1875,8 @@ static void at76_dwork_hw_scan(struct work_struct *work) | |||
| 1872 | /* FIXME: add maximum time for scan to complete */ | 1875 | /* FIXME: add maximum time for scan to complete */ |
| 1873 | 1876 | ||
| 1874 | if (ret != CMD_STATUS_COMPLETE) { | 1877 | if (ret != CMD_STATUS_COMPLETE) { |
| 1875 | queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan, | 1878 | ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan, |
| 1876 | SCAN_POLL_INTERVAL); | 1879 | SCAN_POLL_INTERVAL); |
| 1877 | mutex_unlock(&priv->mtx); | 1880 | mutex_unlock(&priv->mtx); |
| 1878 | return; | 1881 | return; |
| 1879 | } | 1882 | } |
| @@ -1934,8 +1937,8 @@ static int at76_hw_scan(struct ieee80211_hw *hw, | |||
| 1934 | goto exit; | 1937 | goto exit; |
| 1935 | } | 1938 | } |
| 1936 | 1939 | ||
| 1937 | queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan, | 1940 | ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan, |
| 1938 | SCAN_POLL_INTERVAL); | 1941 | SCAN_POLL_INTERVAL); |
| 1939 | 1942 | ||
| 1940 | exit: | 1943 | exit: |
| 1941 | mutex_unlock(&priv->mtx); | 1944 | mutex_unlock(&priv->mtx); |
| @@ -2024,7 +2027,7 @@ static void at76_configure_filter(struct ieee80211_hw *hw, | |||
| 2024 | } else | 2027 | } else |
| 2025 | return; | 2028 | return; |
| 2026 | 2029 | ||
| 2027 | queue_work(hw->workqueue, &priv->work_set_promisc); | 2030 | ieee80211_queue_work(hw, &priv->work_set_promisc); |
| 2028 | } | 2031 | } |
| 2029 | 2032 | ||
| 2030 | static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2033 | static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
| @@ -2295,11 +2298,8 @@ static void at76_delete_device(struct at76_priv *priv) | |||
| 2295 | 2298 | ||
| 2296 | tasklet_kill(&priv->rx_tasklet); | 2299 | tasklet_kill(&priv->rx_tasklet); |
| 2297 | 2300 | ||
| 2298 | if (priv->mac80211_registered) { | 2301 | if (priv->mac80211_registered) |
| 2299 | cancel_delayed_work(&priv->dwork_hw_scan); | ||
| 2300 | flush_workqueue(priv->hw->workqueue); | ||
| 2301 | ieee80211_unregister_hw(priv->hw); | 2302 | ieee80211_unregister_hw(priv->hw); |
| 2302 | } | ||
| 2303 | 2303 | ||
| 2304 | if (priv->tx_urb) { | 2304 | if (priv->tx_urb) { |
| 2305 | usb_kill_urb(priv->tx_urb); | 2305 | usb_kill_urb(priv->tx_urb); |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index eb0337c49546..253b95a264b1 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
| @@ -1,9 +1,24 @@ | |||
| 1 | config ATH_COMMON | 1 | menuconfig ATH_COMMON |
| 2 | tristate "Atheros Wireless Cards" | 2 | tristate "Atheros Wireless Cards" |
| 3 | depends on WLAN_80211 | 3 | depends on WLAN_80211 |
| 4 | depends on ATH5K || ATH9K || AR9170_USB | 4 | depends on CFG80211 |
| 5 | ---help--- | ||
| 6 | This will enable the support for the Atheros wireless drivers. | ||
| 7 | ath5k, ath9k and ar9170 drivers share some common code, this option | ||
| 8 | enables the common ath.ko module which currently shares just common | ||
| 9 | regulatory EEPROM helpers but will likely be extended later to share | ||
| 10 | more between modules. | ||
| 5 | 11 | ||
| 12 | For more information and documentation on this module you can visit: | ||
| 13 | |||
| 14 | http://wireless.kernel.org/en/users/Drivers/ath | ||
| 15 | |||
| 16 | For information on all Atheros wireless drivers visit: | ||
| 17 | |||
| 18 | http://wireless.kernel.org/en/users/Drivers/Atheros | ||
| 19 | |||
| 20 | if ATH_COMMON | ||
| 6 | source "drivers/net/wireless/ath/ath5k/Kconfig" | 21 | source "drivers/net/wireless/ath/ath5k/Kconfig" |
| 7 | source "drivers/net/wireless/ath/ath9k/Kconfig" | 22 | source "drivers/net/wireless/ath/ath9k/Kconfig" |
| 8 | source "drivers/net/wireless/ath/ar9170/Kconfig" | 23 | source "drivers/net/wireless/ath/ar9170/Kconfig" |
| 9 | 24 | endif | |
diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig index b99e3263ee6d..05918f1e685a 100644 --- a/drivers/net/wireless/ath/ar9170/Kconfig +++ b/drivers/net/wireless/ath/ar9170/Kconfig | |||
| @@ -1,13 +1,13 @@ | |||
| 1 | config AR9170_USB | 1 | config AR9170_USB |
| 2 | tristate "Atheros AR9170 802.11n USB support" | 2 | tristate "Atheros AR9170 802.11n USB support" |
| 3 | depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL | 3 | depends on USB && MAC80211 && WLAN_80211 |
| 4 | select FW_LOADER | 4 | select FW_LOADER |
| 5 | select ATH_COMMON | ||
| 6 | help | 5 | help |
| 7 | This is a driver for the Atheros "otus" 802.11n USB devices. | 6 | This is a driver for the Atheros "otus" 802.11n USB devices. |
| 8 | 7 | ||
| 9 | These devices require additional firmware (2 files). | 8 | These devices require additional firmware (2 files). |
| 10 | For now, these files can be downloaded from here: | 9 | For now, these files can be downloaded from here: |
| 10 | |||
| 11 | http://wireless.kernel.org/en/users/Drivers/ar9170 | 11 | http://wireless.kernel.org/en/users/Drivers/ar9170 |
| 12 | 12 | ||
| 13 | If you choose to build a module, it'll be called ar9170usb. | 13 | If you choose to build a module, it'll be called ar9170usb. |
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c index 63fda6cd2101..86c4e79f6bc8 100644 --- a/drivers/net/wireless/ath/ar9170/led.c +++ b/drivers/net/wireless/ath/ar9170/led.c | |||
| @@ -90,9 +90,12 @@ static void ar9170_update_leds(struct work_struct *work) | |||
| 90 | ar9170_set_leds_state(ar, led_val); | 90 | ar9170_set_leds_state(ar, led_val); |
| 91 | mutex_unlock(&ar->mutex); | 91 | mutex_unlock(&ar->mutex); |
| 92 | 92 | ||
| 93 | if (rerun) | 93 | if (!rerun) |
| 94 | queue_delayed_work(ar->hw->workqueue, &ar->led_work, | 94 | return; |
| 95 | msecs_to_jiffies(blink_delay)); | 95 | |
| 96 | ieee80211_queue_delayed_work(ar->hw, | ||
| 97 | &ar->led_work, | ||
| 98 | msecs_to_jiffies(blink_delay)); | ||
| 96 | } | 99 | } |
| 97 | 100 | ||
| 98 | static void ar9170_led_brightness_set(struct led_classdev *led, | 101 | static void ar9170_led_brightness_set(struct led_classdev *led, |
| @@ -110,7 +113,7 @@ static void ar9170_led_brightness_set(struct led_classdev *led, | |||
| 110 | } | 113 | } |
| 111 | 114 | ||
| 112 | if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) | 115 | if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) |
| 113 | queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10); | 116 | ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); |
| 114 | } | 117 | } |
| 115 | 118 | ||
| 116 | static int ar9170_register_led(struct ar9170 *ar, int i, char *name, | 119 | static int ar9170_register_led(struct ar9170 *ar, int i, char *name, |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 85a1452a7c3c..4fc389ae74b4 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
| @@ -595,10 +595,12 @@ static void ar9170_tx_janitor(struct work_struct *work) | |||
| 595 | 595 | ||
| 596 | ar9170_tx_fake_ampdu_status(ar); | 596 | ar9170_tx_fake_ampdu_status(ar); |
| 597 | 597 | ||
| 598 | if (resched) | 598 | if (!resched) |
| 599 | queue_delayed_work(ar->hw->workqueue, | 599 | return; |
| 600 | &ar->tx_janitor, | 600 | |
| 601 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | 601 | ieee80211_queue_delayed_work(ar->hw, |
| 602 | &ar->tx_janitor, | ||
| 603 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | ||
| 602 | } | 604 | } |
| 603 | 605 | ||
| 604 | void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | 606 | void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) |
| @@ -648,7 +650,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | |||
| 648 | * pre-TBTT event | 650 | * pre-TBTT event |
| 649 | */ | 651 | */ |
| 650 | if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) | 652 | if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) |
| 651 | queue_work(ar->hw->workqueue, &ar->beacon_work); | 653 | ieee80211_queue_work(ar->hw, &ar->beacon_work); |
| 652 | break; | 654 | break; |
| 653 | 655 | ||
| 654 | case 0xc2: | 656 | case 0xc2: |
| @@ -1290,14 +1292,13 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) | |||
| 1290 | if (IS_STARTED(ar)) | 1292 | if (IS_STARTED(ar)) |
| 1291 | ar->state = AR9170_IDLE; | 1293 | ar->state = AR9170_IDLE; |
| 1292 | 1294 | ||
| 1293 | flush_workqueue(ar->hw->workqueue); | ||
| 1294 | |||
| 1295 | cancel_delayed_work_sync(&ar->tx_janitor); | 1295 | cancel_delayed_work_sync(&ar->tx_janitor); |
| 1296 | #ifdef CONFIG_AR9170_LEDS | 1296 | #ifdef CONFIG_AR9170_LEDS |
| 1297 | cancel_delayed_work_sync(&ar->led_work); | 1297 | cancel_delayed_work_sync(&ar->led_work); |
| 1298 | #endif | 1298 | #endif |
| 1299 | cancel_work_sync(&ar->filter_config_work); | 1299 | cancel_work_sync(&ar->filter_config_work); |
| 1300 | cancel_work_sync(&ar->beacon_work); | 1300 | cancel_work_sync(&ar->beacon_work); |
| 1301 | |||
| 1301 | mutex_lock(&ar->mutex); | 1302 | mutex_lock(&ar->mutex); |
| 1302 | 1303 | ||
| 1303 | if (IS_ACCEPTING_CMD(ar)) { | 1304 | if (IS_ACCEPTING_CMD(ar)) { |
| @@ -1826,10 +1827,12 @@ static void ar9170_tx(struct ar9170 *ar) | |||
| 1826 | } | 1827 | } |
| 1827 | } | 1828 | } |
| 1828 | 1829 | ||
| 1829 | if (schedule_garbagecollector) | 1830 | if (!schedule_garbagecollector) |
| 1830 | queue_delayed_work(ar->hw->workqueue, | 1831 | return; |
| 1831 | &ar->tx_janitor, | 1832 | |
| 1832 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | 1833 | ieee80211_queue_delayed_work(ar->hw, |
| 1834 | &ar->tx_janitor, | ||
| 1835 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | ||
| 1833 | } | 1836 | } |
| 1834 | 1837 | ||
| 1835 | static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) | 1838 | static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) |
| @@ -2158,7 +2161,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, | |||
| 2158 | } | 2161 | } |
| 2159 | 2162 | ||
| 2160 | if (likely(IS_STARTED(ar))) | 2163 | if (likely(IS_STARTED(ar))) |
| 2161 | queue_work(ar->hw->workqueue, &ar->filter_config_work); | 2164 | ieee80211_queue_work(ar->hw, &ar->filter_config_work); |
| 2162 | } | 2165 | } |
| 2163 | 2166 | ||
| 2164 | static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, | 2167 | static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, |
| @@ -2416,7 +2419,7 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, | |||
| 2416 | } | 2419 | } |
| 2417 | 2420 | ||
| 2418 | if (IS_STARTED(ar) && ar->filter_changed) | 2421 | if (IS_STARTED(ar) && ar->filter_changed) |
| 2419 | queue_work(ar->hw->workqueue, &ar->filter_config_work); | 2422 | ieee80211_queue_work(ar->hw, &ar->filter_config_work); |
| 2420 | } | 2423 | } |
| 2421 | 2424 | ||
| 2422 | static int ar9170_get_stats(struct ieee80211_hw *hw, | 2425 | static int ar9170_get_stats(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index daf0c83527d8..06d006675d7d 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | config ATH5K | 1 | config ATH5K |
| 2 | tristate "Atheros 5xxx wireless cards support" | 2 | tristate "Atheros 5xxx wireless cards support" |
| 3 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL | 3 | depends on PCI && MAC80211 && WLAN_80211 |
| 4 | select ATH_COMMON | ||
| 5 | select MAC80211_LEDS | 4 | select MAC80211_LEDS |
| 6 | select LEDS_CLASS | 5 | select LEDS_CLASS |
| 7 | select NEW_LEDS | 6 | select NEW_LEDS |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7db32ce3dbd8..3a1c156d275f 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
| @@ -1117,6 +1117,8 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
| 1117 | struct ath5k_hw *ah = sc->ah; | 1117 | struct ath5k_hw *ah = sc->ah; |
| 1118 | u32 rfilt; | 1118 | u32 rfilt; |
| 1119 | 1119 | ||
| 1120 | ah->ah_op_mode = sc->opmode; | ||
| 1121 | |||
| 1120 | /* configure rx filter */ | 1122 | /* configure rx filter */ |
| 1121 | rfilt = sc->filter_flags; | 1123 | rfilt = sc->filter_flags; |
| 1122 | ath5k_hw_set_rx_filter(ah, rfilt); | 1124 | ath5k_hw_set_rx_filter(ah, rfilt); |
| @@ -1998,9 +2000,12 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
| 1998 | static void | 2000 | static void |
| 1999 | ath5k_tasklet_tx(unsigned long data) | 2001 | ath5k_tasklet_tx(unsigned long data) |
| 2000 | { | 2002 | { |
| 2003 | int i; | ||
| 2001 | struct ath5k_softc *sc = (void *)data; | 2004 | struct ath5k_softc *sc = (void *)data; |
| 2002 | 2005 | ||
| 2003 | ath5k_tx_processq(sc, sc->txq); | 2006 | for (i=0; i < AR5K_NUM_TX_QUEUES; i++) |
| 2007 | if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) | ||
| 2008 | ath5k_tx_processq(sc, &sc->txqs[i]); | ||
| 2004 | } | 2009 | } |
| 2005 | 2010 | ||
| 2006 | 2011 | ||
| @@ -2768,6 +2773,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
| 2768 | } | 2773 | } |
| 2769 | 2774 | ||
| 2770 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); | 2775 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); |
| 2776 | ath5k_mode_setup(sc); | ||
| 2771 | 2777 | ||
| 2772 | ret = 0; | 2778 | ret = 0; |
| 2773 | end: | 2779 | end: |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 0f4a6d862d3a..2cb72f8c32d7 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | config ATH9K | 1 | config ATH9K |
| 2 | tristate "Atheros 802.11n wireless cards support" | 2 | tristate "Atheros 802.11n wireless cards support" |
| 3 | depends on PCI && MAC80211 && WLAN_80211 | 3 | depends on PCI && MAC80211 && WLAN_80211 |
| 4 | select ATH_COMMON | ||
| 5 | select MAC80211_LEDS | 4 | select MAC80211_LEDS |
| 6 | select LEDS_CLASS | 5 | select LEDS_CLASS |
| 7 | select NEW_LEDS | 6 | select NEW_LEDS |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 0e65c51ba176..5618fc25d52f 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
| @@ -119,7 +119,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
| 119 | sc->bus_ops = &ath_ahb_bus_ops; | 119 | sc->bus_ops = &ath_ahb_bus_ops; |
| 120 | sc->irq = irq; | 120 | sc->irq = irq; |
| 121 | 121 | ||
| 122 | ret = ath_attach(AR5416_AR9100_DEVID, sc); | 122 | ret = ath_init_device(AR5416_AR9100_DEVID, sc); |
| 123 | if (ret != 0) { | 123 | if (ret != 0) { |
| 124 | dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); | 124 | dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); |
| 125 | ret = -ENODEV; | 125 | ret = -ENODEV; |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index aad259b4c197..b7093126dbb8 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
| @@ -777,7 +777,7 @@ void ath9k_hw_ani_setup(struct ath_hw *ah) | |||
| 777 | } | 777 | } |
| 778 | } | 778 | } |
| 779 | 779 | ||
| 780 | void ath9k_hw_ani_attach(struct ath_hw *ah) | 780 | void ath9k_hw_ani_init(struct ath_hw *ah) |
| 781 | { | 781 | { |
| 782 | int i; | 782 | int i; |
| 783 | 783 | ||
| @@ -822,9 +822,9 @@ void ath9k_hw_ani_attach(struct ath_hw *ah) | |||
| 822 | ah->proc_phyerr |= HAL_PROCESS_ANI; | 822 | ah->proc_phyerr |= HAL_PROCESS_ANI; |
| 823 | } | 823 | } |
| 824 | 824 | ||
| 825 | void ath9k_hw_ani_detach(struct ath_hw *ah) | 825 | void ath9k_hw_ani_disable(struct ath_hw *ah) |
| 826 | { | 826 | { |
| 827 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n"); | 827 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n"); |
| 828 | 828 | ||
| 829 | if (ah->has_hw_phycounters) { | 829 | if (ah->has_hw_phycounters) { |
| 830 | ath9k_hw_disable_mib_counters(ah); | 830 | ath9k_hw_disable_mib_counters(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 08b4e7ed5ff0..a36b7bb7c42a 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
| @@ -132,7 +132,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, | |||
| 132 | void ath9k_hw_procmibevent(struct ath_hw *ah, | 132 | void ath9k_hw_procmibevent(struct ath_hw *ah, |
| 133 | const struct ath9k_node_stats *stats); | 133 | const struct ath9k_node_stats *stats); |
| 134 | void ath9k_hw_ani_setup(struct ath_hw *ah); | 134 | void ath9k_hw_ani_setup(struct ath_hw *ah); |
| 135 | void ath9k_hw_ani_attach(struct ath_hw *ah); | 135 | void ath9k_hw_ani_init(struct ath_hw *ah); |
| 136 | void ath9k_hw_ani_detach(struct ath_hw *ah); | 136 | void ath9k_hw_ani_disable(struct ath_hw *ah); |
| 137 | 137 | ||
| 138 | #endif /* ANI_H */ | 138 | #endif /* ANI_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bda0f302340c..7a5a157e15c4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
| @@ -642,7 +642,7 @@ extern struct ieee80211_ops ath9k_ops; | |||
| 642 | 642 | ||
| 643 | irqreturn_t ath_isr(int irq, void *dev); | 643 | irqreturn_t ath_isr(int irq, void *dev); |
| 644 | void ath_cleanup(struct ath_softc *sc); | 644 | void ath_cleanup(struct ath_softc *sc); |
| 645 | int ath_attach(u16 devid, struct ath_softc *sc); | 645 | int ath_init_device(u16 devid, struct ath_softc *sc); |
| 646 | void ath_detach(struct ath_softc *sc); | 646 | void ath_detach(struct ath_softc *sc); |
| 647 | const char *ath_mac_bb_name(u32 mac_bb_version); | 647 | const char *ath_mac_bb_name(u32 mac_bb_version); |
| 648 | const char *ath_rf_name(u16 rf_version); | 648 | const char *ath_rf_name(u16 rf_version); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index d1bbb02af8de..26d87527acbd 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
| @@ -753,6 +753,98 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah) | |||
| 753 | } | 753 | } |
| 754 | } | 754 | } |
| 755 | 755 | ||
| 756 | static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) | ||
| 757 | { | ||
| 758 | u32 regVal; | ||
| 759 | unsigned int i; | ||
| 760 | u32 regList [][2] = { | ||
| 761 | { 0x786c, 0 }, | ||
| 762 | { 0x7854, 0 }, | ||
| 763 | { 0x7820, 0 }, | ||
| 764 | { 0x7824, 0 }, | ||
| 765 | { 0x7868, 0 }, | ||
| 766 | { 0x783c, 0 }, | ||
| 767 | { 0x7838, 0 } , | ||
| 768 | { 0x7828, 0 } , | ||
| 769 | }; | ||
| 770 | |||
| 771 | for (i = 0; i < ARRAY_SIZE(regList); i++) | ||
| 772 | regList[i][1] = REG_READ(ah, regList[i][0]); | ||
| 773 | |||
| 774 | regVal = REG_READ(ah, 0x7834); | ||
| 775 | regVal &= (~(0x1)); | ||
| 776 | REG_WRITE(ah, 0x7834, regVal); | ||
| 777 | regVal = REG_READ(ah, 0x9808); | ||
| 778 | regVal |= (0x1 << 27); | ||
| 779 | REG_WRITE(ah, 0x9808, regVal); | ||
| 780 | |||
| 781 | /* 786c,b23,1, pwddac=1 */ | ||
| 782 | REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); | ||
| 783 | /* 7854, b5,1, pdrxtxbb=1 */ | ||
| 784 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); | ||
| 785 | /* 7854, b7,1, pdv2i=1 */ | ||
| 786 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); | ||
| 787 | /* 7854, b8,1, pddacinterface=1 */ | ||
| 788 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); | ||
| 789 | /* 7824,b12,0, offcal=0 */ | ||
| 790 | REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); | ||
| 791 | /* 7838, b1,0, pwddb=0 */ | ||
| 792 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); | ||
| 793 | /* 7820,b11,0, enpacal=0 */ | ||
| 794 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); | ||
| 795 | /* 7820,b25,1, pdpadrv1=0 */ | ||
| 796 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); | ||
| 797 | /* 7820,b24,0, pdpadrv2=0 */ | ||
| 798 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0); | ||
| 799 | /* 7820,b23,0, pdpaout=0 */ | ||
| 800 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); | ||
| 801 | /* 783c,b14-16,7, padrvgn2tab_0=7 */ | ||
| 802 | REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7); | ||
| 803 | /* | ||
| 804 | * 7838,b29-31,0, padrvgn1tab_0=0 | ||
| 805 | * does not matter since we turn it off | ||
| 806 | */ | ||
| 807 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0); | ||
| 808 | |||
| 809 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); | ||
| 810 | |||
| 811 | /* Set: | ||
| 812 | * localmode=1,bmode=1,bmoderxtx=1,synthon=1, | ||
| 813 | * txon=1,paon=1,oscon=1,synthon_force=1 | ||
| 814 | */ | ||
| 815 | REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); | ||
| 816 | udelay(30); | ||
| 817 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); | ||
| 818 | |||
| 819 | /* find off_6_1; */ | ||
| 820 | for (i = 6; i >= 0; i--) { | ||
| 821 | regVal = REG_READ(ah, 0x7834); | ||
| 822 | regVal |= (1 << (20 + i)); | ||
| 823 | REG_WRITE(ah, 0x7834, regVal); | ||
| 824 | udelay(1); | ||
| 825 | //regVal = REG_READ(ah, 0x7834); | ||
| 826 | regVal &= (~(0x1 << (20 + i))); | ||
| 827 | regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) | ||
| 828 | << (20 + i)); | ||
| 829 | REG_WRITE(ah, 0x7834, regVal); | ||
| 830 | } | ||
| 831 | |||
| 832 | /* Empirical offset correction */ | ||
| 833 | #if 0 | ||
| 834 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20); | ||
| 835 | #endif | ||
| 836 | |||
| 837 | regVal = REG_READ(ah, 0x7834); | ||
| 838 | regVal |= 0x1; | ||
| 839 | REG_WRITE(ah, 0x7834, regVal); | ||
| 840 | regVal = REG_READ(ah, 0x9808); | ||
| 841 | regVal &= (~(0x1 << 27)); | ||
| 842 | REG_WRITE(ah, 0x9808, regVal); | ||
| 843 | |||
| 844 | for (i = 0; i < ARRAY_SIZE(regList); i++) | ||
| 845 | REG_WRITE(ah, regList[i][0], regList[i][1]); | ||
| 846 | } | ||
| 847 | |||
| 756 | static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) | 848 | static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) |
| 757 | { | 849 | { |
| 758 | 850 | ||
| @@ -869,14 +961,26 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 869 | } | 961 | } |
| 870 | } | 962 | } |
| 871 | 963 | ||
| 964 | /* Do NF cal only at longer intervals */ | ||
| 872 | if (longcal) { | 965 | if (longcal) { |
| 873 | if (AR_SREV_9285_11_OR_LATER(ah)) | 966 | /* Do periodic PAOffset Cal */ |
| 967 | if (AR_SREV_9271(ah)) | ||
| 968 | ath9k_hw_9271_pa_cal(ah); | ||
| 969 | else if (AR_SREV_9285_11_OR_LATER(ah)) | ||
| 874 | ath9k_hw_9285_pa_cal(ah); | 970 | ath9k_hw_9285_pa_cal(ah); |
| 875 | 971 | ||
| 876 | if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) | 972 | if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) |
| 877 | ath9k_olc_temp_compensation(ah); | 973 | ath9k_olc_temp_compensation(ah); |
| 974 | |||
| 975 | /* Get the value from the previous NF cal and update history buffer */ | ||
| 878 | ath9k_hw_getnf(ah, chan); | 976 | ath9k_hw_getnf(ah, chan); |
| 977 | |||
| 978 | /* | ||
| 979 | * Load the NF from history buffer of the current channel. | ||
| 980 | * NF is slow time-variant, so it is OK to use a historical value. | ||
| 981 | */ | ||
| 879 | ath9k_hw_loadnf(ah, ah->curchan); | 982 | ath9k_hw_loadnf(ah, ah->curchan); |
| 983 | |||
| 880 | ath9k_hw_start_nfcal(ah); | 984 | ath9k_hw_start_nfcal(ah); |
| 881 | } | 985 | } |
| 882 | 986 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 6fb1a8034b3c..4cb64a0900bb 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
| @@ -1237,6 +1237,10 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | |||
| 1237 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | 1237 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); |
| 1238 | } | 1238 | } |
| 1239 | 1239 | ||
| 1240 | /* | ||
| 1241 | * Read EEPROM header info and program the device for correct operation | ||
| 1242 | * given the channel value. | ||
| 1243 | */ | ||
| 1240 | static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | 1244 | static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, |
| 1241 | struct ath9k_channel *chan) | 1245 | struct ath9k_channel *chan) |
| 1242 | { | 1246 | { |
| @@ -1313,38 +1317,110 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
| 1313 | } | 1317 | } |
| 1314 | } | 1318 | } |
| 1315 | 1319 | ||
| 1316 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, | 1320 | if (AR_SREV_9271(ah)) { |
| 1317 | AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]); | 1321 | ath9k_hw_analog_shift_rmw(ah, |
| 1318 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, | 1322 | AR9285_AN_RF2G3, |
| 1319 | AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]); | 1323 | AR9271_AN_RF2G3_OB_cck, |
| 1320 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, | 1324 | AR9271_AN_RF2G3_OB_cck_S, |
| 1321 | AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]); | 1325 | ob[0]); |
| 1322 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, | 1326 | ath9k_hw_analog_shift_rmw(ah, |
| 1323 | AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]); | 1327 | AR9285_AN_RF2G3, |
| 1324 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, | 1328 | AR9271_AN_RF2G3_OB_psk, |
| 1325 | AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]); | 1329 | AR9271_AN_RF2G3_OB_psk_S, |
| 1326 | 1330 | ob[1]); | |
| 1327 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, | 1331 | ath9k_hw_analog_shift_rmw(ah, |
| 1328 | AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]); | 1332 | AR9285_AN_RF2G3, |
| 1329 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, | 1333 | AR9271_AN_RF2G3_OB_qam, |
| 1330 | AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]); | 1334 | AR9271_AN_RF2G3_OB_qam_S, |
| 1331 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, | 1335 | ob[2]); |
| 1332 | AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]); | 1336 | ath9k_hw_analog_shift_rmw(ah, |
| 1333 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, | 1337 | AR9285_AN_RF2G3, |
| 1334 | AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]); | 1338 | AR9271_AN_RF2G3_DB_1, |
| 1335 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, | 1339 | AR9271_AN_RF2G3_DB_1_S, |
| 1336 | AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]); | 1340 | db1[0]); |
| 1337 | 1341 | ath9k_hw_analog_shift_rmw(ah, | |
| 1338 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, | 1342 | AR9285_AN_RF2G4, |
| 1339 | AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]); | 1343 | AR9271_AN_RF2G4_DB_2, |
| 1340 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, | 1344 | AR9271_AN_RF2G4_DB_2_S, |
| 1341 | AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]); | 1345 | db2[0]); |
| 1342 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, | 1346 | } else { |
| 1343 | AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]); | 1347 | ath9k_hw_analog_shift_rmw(ah, |
| 1344 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, | 1348 | AR9285_AN_RF2G3, |
| 1345 | AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]); | 1349 | AR9285_AN_RF2G3_OB_0, |
| 1346 | ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, | 1350 | AR9285_AN_RF2G3_OB_0_S, |
| 1347 | AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]); | 1351 | ob[0]); |
| 1352 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1353 | AR9285_AN_RF2G3, | ||
| 1354 | AR9285_AN_RF2G3_OB_1, | ||
| 1355 | AR9285_AN_RF2G3_OB_1_S, | ||
| 1356 | ob[1]); | ||
| 1357 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1358 | AR9285_AN_RF2G3, | ||
| 1359 | AR9285_AN_RF2G3_OB_2, | ||
| 1360 | AR9285_AN_RF2G3_OB_2_S, | ||
| 1361 | ob[2]); | ||
| 1362 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1363 | AR9285_AN_RF2G3, | ||
| 1364 | AR9285_AN_RF2G3_OB_3, | ||
| 1365 | AR9285_AN_RF2G3_OB_3_S, | ||
| 1366 | ob[3]); | ||
| 1367 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1368 | AR9285_AN_RF2G3, | ||
| 1369 | AR9285_AN_RF2G3_OB_4, | ||
| 1370 | AR9285_AN_RF2G3_OB_4_S, | ||
| 1371 | ob[4]); | ||
| 1372 | |||
| 1373 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1374 | AR9285_AN_RF2G3, | ||
| 1375 | AR9285_AN_RF2G3_DB1_0, | ||
| 1376 | AR9285_AN_RF2G3_DB1_0_S, | ||
| 1377 | db1[0]); | ||
| 1378 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1379 | AR9285_AN_RF2G3, | ||
| 1380 | AR9285_AN_RF2G3_DB1_1, | ||
| 1381 | AR9285_AN_RF2G3_DB1_1_S, | ||
| 1382 | db1[1]); | ||
| 1383 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1384 | AR9285_AN_RF2G3, | ||
| 1385 | AR9285_AN_RF2G3_DB1_2, | ||
| 1386 | AR9285_AN_RF2G3_DB1_2_S, | ||
| 1387 | db1[2]); | ||
| 1388 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1389 | AR9285_AN_RF2G4, | ||
| 1390 | AR9285_AN_RF2G4_DB1_3, | ||
| 1391 | AR9285_AN_RF2G4_DB1_3_S, | ||
| 1392 | db1[3]); | ||
| 1393 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1394 | AR9285_AN_RF2G4, | ||
| 1395 | AR9285_AN_RF2G4_DB1_4, | ||
| 1396 | AR9285_AN_RF2G4_DB1_4_S, db1[4]); | ||
| 1397 | |||
| 1398 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1399 | AR9285_AN_RF2G4, | ||
| 1400 | AR9285_AN_RF2G4_DB2_0, | ||
| 1401 | AR9285_AN_RF2G4_DB2_0_S, | ||
| 1402 | db2[0]); | ||
| 1403 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1404 | AR9285_AN_RF2G4, | ||
| 1405 | AR9285_AN_RF2G4_DB2_1, | ||
| 1406 | AR9285_AN_RF2G4_DB2_1_S, | ||
| 1407 | db2[1]); | ||
| 1408 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1409 | AR9285_AN_RF2G4, | ||
| 1410 | AR9285_AN_RF2G4_DB2_2, | ||
| 1411 | AR9285_AN_RF2G4_DB2_2_S, | ||
| 1412 | db2[2]); | ||
| 1413 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1414 | AR9285_AN_RF2G4, | ||
| 1415 | AR9285_AN_RF2G4_DB2_3, | ||
| 1416 | AR9285_AN_RF2G4_DB2_3_S, | ||
| 1417 | db2[3]); | ||
| 1418 | ath9k_hw_analog_shift_rmw(ah, | ||
| 1419 | AR9285_AN_RF2G4, | ||
| 1420 | AR9285_AN_RF2G4_DB2_4, | ||
| 1421 | AR9285_AN_RF2G4_DB2_4_S, | ||
| 1422 | db2[4]); | ||
| 1423 | } | ||
| 1348 | 1424 | ||
| 1349 | 1425 | ||
| 1350 | if (AR_SREV_9285_11(ah)) | 1426 | if (AR_SREV_9285_11(ah)) |
| @@ -2794,7 +2870,7 @@ static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah) | |||
| 2794 | 2870 | ||
| 2795 | static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | 2871 | static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) |
| 2796 | { | 2872 | { |
| 2797 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | 2873 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
| 2798 | u16 *eep_data; | 2874 | u16 *eep_data; |
| 2799 | int addr, eep_start_loc = AR9287_EEP_START_LOC; | 2875 | int addr, eep_start_loc = AR9287_EEP_START_LOC; |
| 2800 | eep_data = (u16 *)eep; | 2876 | eep_data = (u16 *)eep; |
| @@ -2803,7 +2879,7 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | |||
| 2803 | "Reading from EEPROM, not flash\n"); | 2879 | "Reading from EEPROM, not flash\n"); |
| 2804 | } | 2880 | } |
| 2805 | 2881 | ||
| 2806 | for (addr = 0; addr < sizeof(struct ar9287_eeprom_t) / sizeof(u16); | 2882 | for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16); |
| 2807 | addr++) { | 2883 | addr++) { |
| 2808 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | 2884 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { |
| 2809 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 2885 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, |
| @@ -2816,12 +2892,11 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | |||
| 2816 | } | 2892 | } |
| 2817 | static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | 2893 | static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) |
| 2818 | { | 2894 | { |
| 2819 | #define SIZE_EEPROM_87 (sizeof(struct ar9287_eeprom_t) / sizeof(u16)) | ||
| 2820 | u32 sum = 0, el, integer; | 2895 | u32 sum = 0, el, integer; |
| 2821 | u16 temp, word, magic, magic2, *eepdata; | 2896 | u16 temp, word, magic, magic2, *eepdata; |
| 2822 | int i, addr; | 2897 | int i, addr; |
| 2823 | bool need_swap = false; | 2898 | bool need_swap = false; |
| 2824 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | 2899 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
| 2825 | 2900 | ||
| 2826 | if (!ath9k_hw_use_flash(ah)) { | 2901 | if (!ath9k_hw_use_flash(ah)) { |
| 2827 | if (!ath9k_hw_nvram_read | 2902 | if (!ath9k_hw_nvram_read |
| @@ -2842,7 +2917,9 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
| 2842 | need_swap = true; | 2917 | need_swap = true; |
| 2843 | eepdata = (u16 *)(&ah->eeprom); | 2918 | eepdata = (u16 *)(&ah->eeprom); |
| 2844 | 2919 | ||
| 2845 | for (addr = 0; addr < SIZE_EEPROM_87; addr++) { | 2920 | for (addr = 0; |
| 2921 | addr < sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
| 2922 | addr++) { | ||
| 2846 | temp = swab16(*eepdata); | 2923 | temp = swab16(*eepdata); |
| 2847 | *eepdata = temp; | 2924 | *eepdata = temp; |
| 2848 | eepdata++; | 2925 | eepdata++; |
| @@ -2862,8 +2939,13 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
| 2862 | else | 2939 | else |
| 2863 | el = ah->eeprom.map9287.baseEepHeader.length; | 2940 | el = ah->eeprom.map9287.baseEepHeader.length; |
| 2864 | 2941 | ||
| 2942 | if (el > sizeof(struct ar9287_eeprom)) | ||
| 2943 | el = sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
| 2944 | else | ||
| 2945 | el = el / sizeof(u16); | ||
| 2946 | |||
| 2865 | eepdata = (u16 *)(&ah->eeprom); | 2947 | eepdata = (u16 *)(&ah->eeprom); |
| 2866 | for (i = 0; i < min(el, SIZE_EEPROM_87); i++) | 2948 | for (i = 0; i < el; i++) |
| 2867 | sum ^= *eepdata++; | 2949 | sum ^= *eepdata++; |
| 2868 | 2950 | ||
| 2869 | if (need_swap) { | 2951 | if (need_swap) { |
| @@ -2914,13 +2996,12 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
| 2914 | } | 2996 | } |
| 2915 | 2997 | ||
| 2916 | return 0; | 2998 | return 0; |
| 2917 | #undef SIZE_EEPROM_87 | ||
| 2918 | } | 2999 | } |
| 2919 | 3000 | ||
| 2920 | static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, | 3001 | static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, |
| 2921 | enum eeprom_param param) | 3002 | enum eeprom_param param) |
| 2922 | { | 3003 | { |
| 2923 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | 3004 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
| 2924 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | 3005 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; |
| 2925 | struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; | 3006 | struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; |
| 2926 | u16 ver_minor; | 3007 | u16 ver_minor; |
| @@ -3210,7 +3291,7 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | |||
| 3210 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; | 3291 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; |
| 3211 | u32 reg32, regOffset, regChainOffset; | 3292 | u32 reg32, regOffset, regChainOffset; |
| 3212 | int16_t modalIdx, diff = 0; | 3293 | int16_t modalIdx, diff = 0; |
| 3213 | struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287; | 3294 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
| 3214 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | 3295 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; |
| 3215 | xpdMask = pEepData->modalHeader.xpdGain; | 3296 | xpdMask = pEepData->modalHeader.xpdGain; |
| 3216 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | 3297 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= |
| @@ -3380,7 +3461,7 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
| 3380 | struct chan_centers centers; | 3461 | struct chan_centers centers; |
| 3381 | int tx_chainmask; | 3462 | int tx_chainmask; |
| 3382 | u16 twiceMinEdgePower; | 3463 | u16 twiceMinEdgePower; |
| 3383 | struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287; | 3464 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
| 3384 | tx_chainmask = ah->txchainmask; | 3465 | tx_chainmask = ah->txchainmask; |
| 3385 | 3466 | ||
| 3386 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 3467 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
| @@ -3613,7 +3694,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
| 3613 | { | 3694 | { |
| 3614 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 | 3695 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 |
| 3615 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 | 3696 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 |
| 3616 | struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287; | 3697 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
| 3617 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; | 3698 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; |
| 3618 | int16_t ratesArray[Ar5416RateSize]; | 3699 | int16_t ratesArray[Ar5416RateSize]; |
| 3619 | int16_t txPowerIndexOffset = 0; | 3700 | int16_t txPowerIndexOffset = 0; |
| @@ -3776,7 +3857,7 @@ static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah, | |||
| 3776 | static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, | 3857 | static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, |
| 3777 | struct ath9k_channel *chan) | 3858 | struct ath9k_channel *chan) |
| 3778 | { | 3859 | { |
| 3779 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | 3860 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
| 3780 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | 3861 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; |
| 3781 | 3862 | ||
| 3782 | u16 antWrites[AR9287_ANT_16S]; | 3863 | u16 antWrites[AR9287_ANT_16S]; |
| @@ -3928,7 +4009,7 @@ static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah, | |||
| 3928 | static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, | 4009 | static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, |
| 3929 | struct ath9k_channel *chan) | 4010 | struct ath9k_channel *chan) |
| 3930 | { | 4011 | { |
| 3931 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | 4012 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
| 3932 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | 4013 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; |
| 3933 | return pModal->antCtrlCommon & 0xFFFF; | 4014 | return pModal->antCtrlCommon & 0xFFFF; |
| 3934 | } | 4015 | } |
| @@ -3978,13 +4059,13 @@ static struct eeprom_ops eep_AR9287_ops = { | |||
| 3978 | }; | 4059 | }; |
| 3979 | 4060 | ||
| 3980 | 4061 | ||
| 3981 | int ath9k_hw_eeprom_attach(struct ath_hw *ah) | 4062 | int ath9k_hw_eeprom_init(struct ath_hw *ah) |
| 3982 | { | 4063 | { |
| 3983 | int status; | 4064 | int status; |
| 3984 | if (AR_SREV_9287(ah)) { | 4065 | if (AR_SREV_9287(ah)) { |
| 3985 | ah->eep_map = EEP_MAP_AR9287; | 4066 | ah->eep_map = EEP_MAP_AR9287; |
| 3986 | ah->eep_ops = &eep_AR9287_ops; | 4067 | ah->eep_ops = &eep_AR9287_ops; |
| 3987 | } else if (AR_SREV_9285(ah)) { | 4068 | } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { |
| 3988 | ah->eep_map = EEP_MAP_4KBITS; | 4069 | ah->eep_map = EEP_MAP_4KBITS; |
| 3989 | ah->eep_ops = &eep_4k_ops; | 4070 | ah->eep_ops = &eep_4k_ops; |
| 3990 | } else { | 4071 | } else { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 7ddd016a99ff..db77e90ed9ab 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
| @@ -600,7 +600,7 @@ struct ar5416_eeprom_4k { | |||
| 600 | u8 padding; | 600 | u8 padding; |
| 601 | } __packed; | 601 | } __packed; |
| 602 | 602 | ||
| 603 | struct ar9287_eeprom_t { | 603 | struct ar9287_eeprom { |
| 604 | struct base_eep_ar9287_header baseEepHeader; | 604 | struct base_eep_ar9287_header baseEepHeader; |
| 605 | u8 custData[AR9287_DATA_SZ]; | 605 | u8 custData[AR9287_DATA_SZ]; |
| 606 | struct modal_eep_ar9287_header modalHeader; | 606 | struct modal_eep_ar9287_header modalHeader; |
| @@ -665,6 +665,6 @@ struct eeprom_ops { | |||
| 665 | (((_txchainmask >> 2) & 1) + \ | 665 | (((_txchainmask >> 2) & 1) + \ |
| 666 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) | 666 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) |
| 667 | 667 | ||
| 668 | int ath9k_hw_eeprom_attach(struct ath_hw *ah); | 668 | int ath9k_hw_eeprom_init(struct ath_hw *ah); |
| 669 | 669 | ||
| 670 | #endif /* EEPROM_H */ | 670 | #endif /* EEPROM_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 431854ccb65b..71a3bcc450a2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -388,7 +388,7 @@ static const char *ath9k_hw_devname(u16 devid) | |||
| 388 | return NULL; | 388 | return NULL; |
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | static void ath9k_hw_set_defaults(struct ath_hw *ah) | 391 | static void ath9k_hw_init_config(struct ath_hw *ah) |
| 392 | { | 392 | { |
| 393 | int i; | 393 | int i; |
| 394 | 394 | ||
| @@ -437,27 +437,14 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) | |||
| 437 | ah->config.serialize_regmode = SER_REG_MODE_AUTO; | 437 | ah->config.serialize_regmode = SER_REG_MODE_AUTO; |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc, | 440 | static void ath9k_hw_init_defaults(struct ath_hw *ah) |
| 441 | int *status) | ||
| 442 | { | 441 | { |
| 443 | struct ath_hw *ah; | ||
| 444 | |||
| 445 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | ||
| 446 | if (ah == NULL) { | ||
| 447 | DPRINTF(sc, ATH_DBG_FATAL, | ||
| 448 | "Cannot allocate memory for state block\n"); | ||
| 449 | *status = -ENOMEM; | ||
| 450 | return NULL; | ||
| 451 | } | ||
| 452 | |||
| 453 | ah->ah_sc = sc; | ||
| 454 | ah->hw_version.magic = AR5416_MAGIC; | 442 | ah->hw_version.magic = AR5416_MAGIC; |
| 455 | ah->regulatory.country_code = CTRY_DEFAULT; | 443 | ah->regulatory.country_code = CTRY_DEFAULT; |
| 456 | ah->hw_version.devid = devid; | ||
| 457 | ah->hw_version.subvendorid = 0; | 444 | ah->hw_version.subvendorid = 0; |
| 458 | 445 | ||
| 459 | ah->ah_flags = 0; | 446 | ah->ah_flags = 0; |
| 460 | if ((devid == AR5416_AR9100_DEVID)) | 447 | if (ah->hw_version.devid == AR5416_AR9100_DEVID) |
| 461 | ah->hw_version.macVersion = AR_SREV_VERSION_9100; | 448 | ah->hw_version.macVersion = AR_SREV_VERSION_9100; |
| 462 | if (!AR_SREV_9100(ah)) | 449 | if (!AR_SREV_9100(ah)) |
| 463 | ah->ah_flags = AH_USE_EEPROM; | 450 | ah->ah_flags = AH_USE_EEPROM; |
| @@ -479,8 +466,6 @@ static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc, | |||
| 479 | ah->gbeacon_rate = 0; | 466 | ah->gbeacon_rate = 0; |
| 480 | 467 | ||
| 481 | ah->power_mode = ATH9K_PM_UNDEFINED; | 468 | ah->power_mode = ATH9K_PM_UNDEFINED; |
| 482 | |||
| 483 | return ah; | ||
| 484 | } | 469 | } |
| 485 | 470 | ||
| 486 | static int ath9k_hw_rfattach(struct ath_hw *ah) | 471 | static int ath9k_hw_rfattach(struct ath_hw *ah) |
| @@ -593,7 +578,7 @@ static void ath9k_hw_init_txgain_ini(struct ath_hw *ah) | |||
| 593 | } | 578 | } |
| 594 | } | 579 | } |
| 595 | 580 | ||
| 596 | static int ath9k_hw_post_attach(struct ath_hw *ah) | 581 | static int ath9k_hw_post_init(struct ath_hw *ah) |
| 597 | { | 582 | { |
| 598 | int ecode; | 583 | int ecode; |
| 599 | 584 | ||
| @@ -604,7 +589,7 @@ static int ath9k_hw_post_attach(struct ath_hw *ah) | |||
| 604 | if (ecode != 0) | 589 | if (ecode != 0) |
| 605 | return ecode; | 590 | return ecode; |
| 606 | 591 | ||
| 607 | ecode = ath9k_hw_eeprom_attach(ah); | 592 | ecode = ath9k_hw_eeprom_init(ah); |
| 608 | if (ecode != 0) | 593 | if (ecode != 0) |
| 609 | return ecode; | 594 | return ecode; |
| 610 | 595 | ||
| @@ -617,71 +602,52 @@ static int ath9k_hw_post_attach(struct ath_hw *ah) | |||
| 617 | 602 | ||
| 618 | if (!AR_SREV_9100(ah)) { | 603 | if (!AR_SREV_9100(ah)) { |
| 619 | ath9k_hw_ani_setup(ah); | 604 | ath9k_hw_ani_setup(ah); |
| 620 | ath9k_hw_ani_attach(ah); | 605 | ath9k_hw_ani_init(ah); |
| 621 | } | 606 | } |
| 622 | 607 | ||
| 623 | return 0; | 608 | return 0; |
| 624 | } | 609 | } |
| 625 | 610 | ||
| 626 | static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | 611 | static bool ath9k_hw_devid_supported(u16 devid) |
| 627 | int *status) | ||
| 628 | { | 612 | { |
| 629 | struct ath_hw *ah; | 613 | switch (devid) { |
| 630 | int ecode; | 614 | case AR5416_DEVID_PCI: |
| 631 | u32 i, j; | 615 | case AR5416_DEVID_PCIE: |
| 632 | 616 | case AR5416_AR9100_DEVID: | |
| 633 | ah = ath9k_hw_newstate(devid, sc, status); | 617 | case AR9160_DEVID_PCI: |
| 634 | if (ah == NULL) | 618 | case AR9280_DEVID_PCI: |
| 635 | return NULL; | 619 | case AR9280_DEVID_PCIE: |
| 636 | 620 | case AR9285_DEVID_PCIE: | |
| 637 | ath9k_hw_set_defaults(ah); | 621 | case AR5416_DEVID_AR9287_PCI: |
| 638 | 622 | case AR5416_DEVID_AR9287_PCIE: | |
| 639 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | 623 | return true; |
| 640 | DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); | 624 | default: |
| 641 | ecode = -EIO; | 625 | break; |
| 642 | goto bad; | ||
| 643 | } | ||
| 644 | |||
| 645 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { | ||
| 646 | DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); | ||
| 647 | ecode = -EIO; | ||
| 648 | goto bad; | ||
| 649 | } | ||
| 650 | |||
| 651 | if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { | ||
| 652 | if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || | ||
| 653 | (AR_SREV_9280(ah) && !ah->is_pciexpress)) { | ||
| 654 | ah->config.serialize_regmode = | ||
| 655 | SER_REG_MODE_ON; | ||
| 656 | } else { | ||
| 657 | ah->config.serialize_regmode = | ||
| 658 | SER_REG_MODE_OFF; | ||
| 659 | } | ||
| 660 | } | ||
| 661 | |||
| 662 | DPRINTF(sc, ATH_DBG_RESET, "serialize_regmode is %d\n", | ||
| 663 | ah->config.serialize_regmode); | ||
| 664 | |||
| 665 | if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) && | ||
| 666 | (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) && | ||
| 667 | (ah->hw_version.macVersion != AR_SREV_VERSION_9160) && | ||
| 668 | (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && | ||
| 669 | (!AR_SREV_9285(ah)) && (!AR_SREV_9287(ah))) { | ||
| 670 | DPRINTF(sc, ATH_DBG_FATAL, | ||
| 671 | "Mac Chip Rev 0x%02x.%x is not supported by " | ||
| 672 | "this driver\n", ah->hw_version.macVersion, | ||
| 673 | ah->hw_version.macRev); | ||
| 674 | ecode = -EOPNOTSUPP; | ||
| 675 | goto bad; | ||
| 676 | } | 626 | } |
| 627 | return false; | ||
| 628 | } | ||
| 677 | 629 | ||
| 678 | if (AR_SREV_9100(ah)) { | 630 | static bool ath9k_hw_macversion_supported(u32 macversion) |
| 679 | ah->iq_caldata.calData = &iq_cal_multi_sample; | 631 | { |
| 680 | ah->supp_cals = IQ_MISMATCH_CAL; | 632 | switch (macversion) { |
| 681 | ah->is_pciexpress = false; | 633 | case AR_SREV_VERSION_5416_PCI: |
| 634 | case AR_SREV_VERSION_5416_PCIE: | ||
| 635 | case AR_SREV_VERSION_9160: | ||
| 636 | case AR_SREV_VERSION_9100: | ||
| 637 | case AR_SREV_VERSION_9280: | ||
| 638 | case AR_SREV_VERSION_9285: | ||
| 639 | case AR_SREV_VERSION_9287: | ||
| 640 | return true; | ||
| 641 | /* Not yet */ | ||
| 642 | case AR_SREV_VERSION_9271: | ||
| 643 | default: | ||
| 644 | break; | ||
| 682 | } | 645 | } |
| 683 | ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); | 646 | return false; |
| 647 | } | ||
| 684 | 648 | ||
| 649 | static void ath9k_hw_init_cal_settings(struct ath_hw *ah) | ||
| 650 | { | ||
| 685 | if (AR_SREV_9160_10_OR_LATER(ah)) { | 651 | if (AR_SREV_9160_10_OR_LATER(ah)) { |
| 686 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 652 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
| 687 | ah->iq_caldata.calData = &iq_cal_single_sample; | 653 | ah->iq_caldata.calData = &iq_cal_single_sample; |
| @@ -702,10 +668,18 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
| 702 | } | 668 | } |
| 703 | ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; | 669 | ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; |
| 704 | } | 670 | } |
| 671 | } | ||
| 672 | |||
| 673 | static void ath9k_hw_init_mode_regs(struct ath_hw *ah) | ||
| 674 | { | ||
| 675 | if (AR_SREV_9271(ah)) { | ||
| 676 | INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271_1_0, | ||
| 677 | ARRAY_SIZE(ar9271Modes_9271_1_0), 6); | ||
| 678 | INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271_1_0, | ||
| 679 | ARRAY_SIZE(ar9271Common_9271_1_0), 2); | ||
| 680 | return; | ||
| 681 | } | ||
| 705 | 682 | ||
| 706 | ah->ani_function = ATH9K_ANI_ALL; | ||
| 707 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
| 708 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | ||
| 709 | if (AR_SREV_9287_11_OR_LATER(ah)) { | 683 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
| 710 | INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, | 684 | INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, |
| 711 | ARRAY_SIZE(ar9287Modes_9287_1_1), 6); | 685 | ARRAY_SIZE(ar9287Modes_9287_1_1), 6); |
| @@ -867,16 +841,10 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
| 867 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, | 841 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, |
| 868 | ARRAY_SIZE(ar5416Addac), 2); | 842 | ARRAY_SIZE(ar5416Addac), 2); |
| 869 | } | 843 | } |
| 844 | } | ||
| 870 | 845 | ||
| 871 | if (ah->is_pciexpress) | 846 | static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) |
| 872 | ath9k_hw_configpcipowersave(ah, 0); | 847 | { |
| 873 | else | ||
| 874 | ath9k_hw_disablepcie(ah); | ||
| 875 | |||
| 876 | ecode = ath9k_hw_post_attach(ah); | ||
| 877 | if (ecode != 0) | ||
| 878 | goto bad; | ||
| 879 | |||
| 880 | if (AR_SREV_9287_11(ah)) | 848 | if (AR_SREV_9287_11(ah)) |
| 881 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 849 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 882 | ar9287Modes_rx_gain_9287_1_1, | 850 | ar9287Modes_rx_gain_9287_1_1, |
| @@ -913,8 +881,11 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
| 913 | } | 881 | } |
| 914 | 882 | ||
| 915 | } | 883 | } |
| 884 | } | ||
| 916 | 885 | ||
| 917 | ath9k_hw_fill_cap_info(ah); | 886 | static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah) |
| 887 | { | ||
| 888 | u32 i, j; | ||
| 918 | 889 | ||
| 919 | if ((ah->hw_version.devid == AR9280_DEVID_PCI) && | 890 | if ((ah->hw_version.devid == AR9280_DEVID_PCI) && |
| 920 | test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { | 891 | test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { |
| @@ -933,29 +904,97 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
| 933 | } | 904 | } |
| 934 | } | 905 | } |
| 935 | } | 906 | } |
| 907 | } | ||
| 908 | |||
| 909 | int ath9k_hw_init(struct ath_hw *ah) | ||
| 910 | { | ||
| 911 | int r = 0; | ||
| 912 | |||
| 913 | if (!ath9k_hw_devid_supported(ah->hw_version.devid)) | ||
| 914 | return -EOPNOTSUPP; | ||
| 915 | |||
| 916 | ath9k_hw_init_defaults(ah); | ||
| 917 | ath9k_hw_init_config(ah); | ||
| 918 | |||
| 919 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | ||
| 920 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); | ||
| 921 | return -EIO; | ||
| 922 | } | ||
| 923 | |||
| 924 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { | ||
| 925 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); | ||
| 926 | return -EIO; | ||
| 927 | } | ||
| 928 | |||
| 929 | if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { | ||
| 930 | if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || | ||
| 931 | (AR_SREV_9280(ah) && !ah->is_pciexpress)) { | ||
| 932 | ah->config.serialize_regmode = | ||
| 933 | SER_REG_MODE_ON; | ||
| 934 | } else { | ||
| 935 | ah->config.serialize_regmode = | ||
| 936 | SER_REG_MODE_OFF; | ||
| 937 | } | ||
| 938 | } | ||
| 939 | |||
| 940 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n", | ||
| 941 | ah->config.serialize_regmode); | ||
| 942 | |||
| 943 | if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { | ||
| 944 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
| 945 | "Mac Chip Rev 0x%02x.%x is not supported by " | ||
| 946 | "this driver\n", ah->hw_version.macVersion, | ||
| 947 | ah->hw_version.macRev); | ||
| 948 | return -EOPNOTSUPP; | ||
| 949 | } | ||
| 950 | |||
| 951 | if (AR_SREV_9100(ah)) { | ||
| 952 | ah->iq_caldata.calData = &iq_cal_multi_sample; | ||
| 953 | ah->supp_cals = IQ_MISMATCH_CAL; | ||
| 954 | ah->is_pciexpress = false; | ||
| 955 | } | ||
| 956 | |||
| 957 | if (AR_SREV_9271(ah)) | ||
| 958 | ah->is_pciexpress = false; | ||
| 959 | |||
| 960 | ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); | ||
| 961 | |||
| 962 | ath9k_hw_init_cal_settings(ah); | ||
| 963 | |||
| 964 | ah->ani_function = ATH9K_ANI_ALL; | ||
| 965 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
| 966 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | ||
| 936 | 967 | ||
| 937 | ecode = ath9k_hw_init_macaddr(ah); | 968 | ath9k_hw_init_mode_regs(ah); |
| 938 | if (ecode != 0) { | 969 | |
| 939 | DPRINTF(sc, ATH_DBG_FATAL, | 970 | if (ah->is_pciexpress) |
| 971 | ath9k_hw_configpcipowersave(ah, 0); | ||
| 972 | else | ||
| 973 | ath9k_hw_disablepcie(ah); | ||
| 974 | |||
| 975 | r = ath9k_hw_post_init(ah); | ||
| 976 | if (r) | ||
| 977 | return r; | ||
| 978 | |||
| 979 | ath9k_hw_init_mode_gain_regs(ah); | ||
| 980 | ath9k_hw_fill_cap_info(ah); | ||
| 981 | ath9k_hw_init_11a_eeprom_fix(ah); | ||
| 982 | |||
| 983 | r = ath9k_hw_init_macaddr(ah); | ||
| 984 | if (r) { | ||
| 985 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
| 940 | "Failed to initialize MAC address\n"); | 986 | "Failed to initialize MAC address\n"); |
| 941 | goto bad; | 987 | return r; |
| 942 | } | 988 | } |
| 943 | 989 | ||
| 944 | if (AR_SREV_9285(ah)) | 990 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
| 945 | ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); | 991 | ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); |
| 946 | else | 992 | else |
| 947 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); | 993 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); |
| 948 | 994 | ||
| 949 | ath9k_init_nfcal_hist_buffer(ah); | 995 | ath9k_init_nfcal_hist_buffer(ah); |
| 950 | 996 | ||
| 951 | return ah; | 997 | return 0; |
| 952 | bad: | ||
| 953 | if (ah) | ||
| 954 | ath9k_hw_detach(ah); | ||
| 955 | if (status) | ||
| 956 | *status = ecode; | ||
| 957 | |||
| 958 | return NULL; | ||
| 959 | } | 998 | } |
| 960 | 999 | ||
| 961 | static void ath9k_hw_init_bb(struct ath_hw *ah, | 1000 | static void ath9k_hw_init_bb(struct ath_hw *ah, |
| @@ -1194,35 +1233,12 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid) | |||
| 1194 | void ath9k_hw_detach(struct ath_hw *ah) | 1233 | void ath9k_hw_detach(struct ath_hw *ah) |
| 1195 | { | 1234 | { |
| 1196 | if (!AR_SREV_9100(ah)) | 1235 | if (!AR_SREV_9100(ah)) |
| 1197 | ath9k_hw_ani_detach(ah); | 1236 | ath9k_hw_ani_disable(ah); |
| 1198 | 1237 | ||
| 1199 | ath9k_hw_rfdetach(ah); | 1238 | ath9k_hw_rf_free(ah); |
| 1200 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | 1239 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); |
| 1201 | kfree(ah); | 1240 | kfree(ah); |
| 1202 | } | 1241 | ah = NULL; |
| 1203 | |||
| 1204 | struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error) | ||
| 1205 | { | ||
| 1206 | struct ath_hw *ah = NULL; | ||
| 1207 | |||
| 1208 | switch (devid) { | ||
| 1209 | case AR5416_DEVID_PCI: | ||
| 1210 | case AR5416_DEVID_PCIE: | ||
| 1211 | case AR5416_AR9100_DEVID: | ||
| 1212 | case AR9160_DEVID_PCI: | ||
| 1213 | case AR9280_DEVID_PCI: | ||
| 1214 | case AR9280_DEVID_PCIE: | ||
| 1215 | case AR9285_DEVID_PCIE: | ||
| 1216 | case AR5416_DEVID_AR9287_PCI: | ||
| 1217 | case AR5416_DEVID_AR9287_PCIE: | ||
| 1218 | ah = ath9k_hw_do_attach(devid, sc, error); | ||
| 1219 | break; | ||
| 1220 | default: | ||
| 1221 | *error = -ENXIO; | ||
| 1222 | break; | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | return ah; | ||
| 1226 | } | 1242 | } |
| 1227 | 1243 | ||
| 1228 | /*******/ | 1244 | /*******/ |
| @@ -1232,6 +1248,27 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error) | |||
| 1232 | static void ath9k_hw_override_ini(struct ath_hw *ah, | 1248 | static void ath9k_hw_override_ini(struct ath_hw *ah, |
| 1233 | struct ath9k_channel *chan) | 1249 | struct ath9k_channel *chan) |
| 1234 | { | 1250 | { |
| 1251 | u32 val; | ||
| 1252 | |||
| 1253 | if (AR_SREV_9271(ah)) { | ||
| 1254 | /* | ||
| 1255 | * Enable spectral scan to solution for issues with stuck | ||
| 1256 | * beacons on AR9271 1.0. The beacon stuck issue is not seeon on | ||
| 1257 | * AR9271 1.1 | ||
| 1258 | */ | ||
| 1259 | if (AR_SREV_9271_10(ah)) { | ||
| 1260 | val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | AR_PHY_SPECTRAL_SCAN_ENABLE; | ||
| 1261 | REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); | ||
| 1262 | } | ||
| 1263 | else if (AR_SREV_9271_11(ah)) | ||
| 1264 | /* | ||
| 1265 | * change AR_PHY_RF_CTL3 setting to fix MAC issue | ||
| 1266 | * present on AR9271 1.1 | ||
| 1267 | */ | ||
| 1268 | REG_WRITE(ah, AR_PHY_RF_CTL3, 0x3a020001); | ||
| 1269 | return; | ||
| 1270 | } | ||
| 1271 | |||
| 1235 | /* | 1272 | /* |
| 1236 | * Set the RX_ABORT and RX_DIS and clear if off only after | 1273 | * Set the RX_ABORT and RX_DIS and clear if off only after |
| 1237 | * RXE is set for MAC. This prevents frames with corrupted | 1274 | * RXE is set for MAC. This prevents frames with corrupted |
| @@ -1243,7 +1280,10 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, | |||
| 1243 | if (!AR_SREV_5416_20_OR_LATER(ah) || | 1280 | if (!AR_SREV_5416_20_OR_LATER(ah) || |
| 1244 | AR_SREV_9280_10_OR_LATER(ah)) | 1281 | AR_SREV_9280_10_OR_LATER(ah)) |
| 1245 | return; | 1282 | return; |
| 1246 | 1283 | /* | |
| 1284 | * Disable BB clock gating | ||
| 1285 | * Necessary to avoid issues on AR5416 2.0 | ||
| 1286 | */ | ||
| 1247 | REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); | 1287 | REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); |
| 1248 | } | 1288 | } |
| 1249 | 1289 | ||
| @@ -1475,23 +1515,48 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) | |||
| 1475 | { | 1515 | { |
| 1476 | u32 regval; | 1516 | u32 regval; |
| 1477 | 1517 | ||
| 1518 | /* | ||
| 1519 | * set AHB_MODE not to do cacheline prefetches | ||
| 1520 | */ | ||
| 1478 | regval = REG_READ(ah, AR_AHB_MODE); | 1521 | regval = REG_READ(ah, AR_AHB_MODE); |
| 1479 | REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); | 1522 | REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); |
| 1480 | 1523 | ||
| 1524 | /* | ||
| 1525 | * let mac dma reads be in 128 byte chunks | ||
| 1526 | */ | ||
| 1481 | regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; | 1527 | regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; |
| 1482 | REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); | 1528 | REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); |
| 1483 | 1529 | ||
| 1530 | /* | ||
| 1531 | * Restore TX Trigger Level to its pre-reset value. | ||
| 1532 | * The initial value depends on whether aggregation is enabled, and is | ||
| 1533 | * adjusted whenever underruns are detected. | ||
| 1534 | */ | ||
| 1484 | REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); | 1535 | REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); |
| 1485 | 1536 | ||
| 1537 | /* | ||
| 1538 | * let mac dma writes be in 128 byte chunks | ||
| 1539 | */ | ||
| 1486 | regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; | 1540 | regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; |
| 1487 | REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); | 1541 | REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); |
| 1488 | 1542 | ||
| 1543 | /* | ||
| 1544 | * Setup receive FIFO threshold to hold off TX activities | ||
| 1545 | */ | ||
| 1489 | REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); | 1546 | REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); |
| 1490 | 1547 | ||
| 1548 | /* | ||
| 1549 | * reduce the number of usable entries in PCU TXBUF to avoid | ||
| 1550 | * wrap around issues. | ||
| 1551 | */ | ||
| 1491 | if (AR_SREV_9285(ah)) { | 1552 | if (AR_SREV_9285(ah)) { |
| 1553 | /* For AR9285 the number of Fifos are reduced to half. | ||
| 1554 | * So set the usable tx buf size also to half to | ||
| 1555 | * avoid data/delimiter underruns | ||
| 1556 | */ | ||
| 1492 | REG_WRITE(ah, AR_PCU_TXBUF_CTRL, | 1557 | REG_WRITE(ah, AR_PCU_TXBUF_CTRL, |
| 1493 | AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); | 1558 | AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); |
| 1494 | } else { | 1559 | } else if (!AR_SREV_9271(ah)) { |
| 1495 | REG_WRITE(ah, AR_PCU_TXBUF_CTRL, | 1560 | REG_WRITE(ah, AR_PCU_TXBUF_CTRL, |
| 1496 | AR_PCU_TXBUF_CTRL_USABLE_SIZE); | 1561 | AR_PCU_TXBUF_CTRL_USABLE_SIZE); |
| 1497 | } | 1562 | } |
| @@ -2297,11 +2362,26 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2297 | 2362 | ||
| 2298 | ath9k_hw_mark_phy_inactive(ah); | 2363 | ath9k_hw_mark_phy_inactive(ah); |
| 2299 | 2364 | ||
| 2365 | if (AR_SREV_9271(ah) && ah->htc_reset_init) { | ||
| 2366 | REG_WRITE(ah, | ||
| 2367 | AR9271_RESET_POWER_DOWN_CONTROL, | ||
| 2368 | AR9271_RADIO_RF_RST); | ||
| 2369 | udelay(50); | ||
| 2370 | } | ||
| 2371 | |||
| 2300 | if (!ath9k_hw_chip_reset(ah, chan)) { | 2372 | if (!ath9k_hw_chip_reset(ah, chan)) { |
| 2301 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); | 2373 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); |
| 2302 | return -EINVAL; | 2374 | return -EINVAL; |
| 2303 | } | 2375 | } |
| 2304 | 2376 | ||
| 2377 | if (AR_SREV_9271(ah) && ah->htc_reset_init) { | ||
| 2378 | ah->htc_reset_init = false; | ||
| 2379 | REG_WRITE(ah, | ||
| 2380 | AR9271_RESET_POWER_DOWN_CONTROL, | ||
| 2381 | AR9271_GATE_MAC_CTL); | ||
| 2382 | udelay(50); | ||
| 2383 | } | ||
| 2384 | |||
| 2305 | if (AR_SREV_9280_10_OR_LATER(ah)) | 2385 | if (AR_SREV_9280_10_OR_LATER(ah)) |
| 2306 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | 2386 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); |
| 2307 | 2387 | ||
| @@ -2437,6 +2517,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2437 | 2517 | ||
| 2438 | REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); | 2518 | REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); |
| 2439 | 2519 | ||
| 2520 | /* | ||
| 2521 | * For big endian systems turn on swapping for descriptors | ||
| 2522 | */ | ||
| 2440 | if (AR_SREV_9100(ah)) { | 2523 | if (AR_SREV_9100(ah)) { |
| 2441 | u32 mask; | 2524 | u32 mask; |
| 2442 | mask = REG_READ(ah, AR_CFG); | 2525 | mask = REG_READ(ah, AR_CFG); |
| @@ -2451,8 +2534,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2451 | "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); | 2534 | "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); |
| 2452 | } | 2535 | } |
| 2453 | } else { | 2536 | } else { |
| 2537 | /* Configure AR9271 target WLAN */ | ||
| 2538 | if (AR_SREV_9271(ah)) | ||
| 2539 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | ||
| 2454 | #ifdef __BIG_ENDIAN | 2540 | #ifdef __BIG_ENDIAN |
| 2455 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | 2541 | else |
| 2542 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
| 2456 | #endif | 2543 | #endif |
| 2457 | } | 2544 | } |
| 2458 | 2545 | ||
| @@ -2494,9 +2581,6 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) | |||
| 2494 | 2581 | ||
| 2495 | } | 2582 | } |
| 2496 | 2583 | ||
| 2497 | if (ah->curchan == NULL) | ||
| 2498 | return true; | ||
| 2499 | |||
| 2500 | return true; | 2584 | return true; |
| 2501 | } | 2585 | } |
| 2502 | 2586 | ||
| @@ -2921,7 +3005,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) | |||
| 2921 | /* | 3005 | /* |
| 2922 | * AR9280 2.0 or later chips use SerDes values from the | 3006 | * AR9280 2.0 or later chips use SerDes values from the |
| 2923 | * initvals.h initialized depending on chipset during | 3007 | * initvals.h initialized depending on chipset during |
| 2924 | * ath9k_hw_do_attach() | 3008 | * ath9k_hw_init() |
| 2925 | */ | 3009 | */ |
| 2926 | for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { | 3010 | for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { |
| 2927 | REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), | 3011 | REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), |
| @@ -2982,7 +3066,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) | |||
| 2982 | if (ah->config.pcie_waen) { | 3066 | if (ah->config.pcie_waen) { |
| 2983 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); | 3067 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); |
| 2984 | } else { | 3068 | } else { |
| 2985 | if (AR_SREV_9285(ah)) | 3069 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
| 2986 | REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); | 3070 | REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); |
| 2987 | /* | 3071 | /* |
| 2988 | * On AR9280 chips bit 22 of 0x4004 needs to be set to | 3072 | * On AR9280 chips bit 22 of 0x4004 needs to be set to |
| @@ -3152,11 +3236,6 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
| 3152 | return true; | 3236 | return true; |
| 3153 | } | 3237 | } |
| 3154 | 3238 | ||
| 3155 | enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah) | ||
| 3156 | { | ||
| 3157 | return ah->mask_reg; | ||
| 3158 | } | ||
| 3159 | |||
| 3160 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | 3239 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) |
| 3161 | { | 3240 | { |
| 3162 | u32 omask = ah->mask_reg; | 3241 | u32 omask = ah->mask_reg; |
| @@ -3451,10 +3530,17 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
| 3451 | } | 3530 | } |
| 3452 | 3531 | ||
| 3453 | pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); | 3532 | pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); |
| 3533 | /* | ||
| 3534 | * For AR9271 we will temporarilly uses the rx chainmax as read from | ||
| 3535 | * the EEPROM. | ||
| 3536 | */ | ||
| 3454 | if ((ah->hw_version.devid == AR5416_DEVID_PCI) && | 3537 | if ((ah->hw_version.devid == AR5416_DEVID_PCI) && |
| 3455 | !(eeval & AR5416_OPFLAGS_11A)) | 3538 | !(eeval & AR5416_OPFLAGS_11A) && |
| 3539 | !(AR_SREV_9271(ah))) | ||
| 3540 | /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ | ||
| 3456 | pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; | 3541 | pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; |
| 3457 | else | 3542 | else |
| 3543 | /* Use rx_chainmask from EEPROM. */ | ||
| 3458 | pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); | 3544 | pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); |
| 3459 | 3545 | ||
| 3460 | if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0))) | 3546 | if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0))) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 2e196df10894..d4aaf4f8db29 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
| @@ -403,7 +403,7 @@ struct ath_hw { | |||
| 403 | union { | 403 | union { |
| 404 | struct ar5416_eeprom_def def; | 404 | struct ar5416_eeprom_def def; |
| 405 | struct ar5416_eeprom_4k map4k; | 405 | struct ar5416_eeprom_4k map4k; |
| 406 | struct ar9287_eeprom_t map9287; | 406 | struct ar9287_eeprom map9287; |
| 407 | } eeprom; | 407 | } eeprom; |
| 408 | const struct eeprom_ops *eep_ops; | 408 | const struct eeprom_ops *eep_ops; |
| 409 | enum ath9k_eep_map eep_map; | 409 | enum ath9k_eep_map eep_map; |
| @@ -419,6 +419,8 @@ struct ath_hw { | |||
| 419 | u32 wlanactive_gpio; | 419 | u32 wlanactive_gpio; |
| 420 | u32 ah_flags; | 420 | u32 ah_flags; |
| 421 | 421 | ||
| 422 | bool htc_reset_init; | ||
| 423 | |||
| 422 | enum nl80211_iftype opmode; | 424 | enum nl80211_iftype opmode; |
| 423 | enum ath9k_power_mode power_mode; | 425 | enum ath9k_power_mode power_mode; |
| 424 | 426 | ||
| @@ -541,11 +543,11 @@ struct ath_hw { | |||
| 541 | struct ar5416IniArray iniModesTxGain; | 543 | struct ar5416IniArray iniModesTxGain; |
| 542 | }; | 544 | }; |
| 543 | 545 | ||
| 544 | /* Attach, Detach, Reset */ | 546 | /* Initialization, Detach, Reset */ |
| 545 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); | 547 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); |
| 546 | void ath9k_hw_detach(struct ath_hw *ah); | 548 | void ath9k_hw_detach(struct ath_hw *ah); |
| 547 | struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error); | 549 | int ath9k_hw_init(struct ath_hw *ah); |
| 548 | void ath9k_hw_rfdetach(struct ath_hw *ah); | 550 | void ath9k_hw_rf_free(struct ath_hw *ah); |
| 549 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 551 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
| 550 | bool bChannelChange); | 552 | bool bChannelChange); |
| 551 | void ath9k_hw_fill_cap_info(struct ath_hw *ah); | 553 | void ath9k_hw_fill_cap_info(struct ath_hw *ah); |
| @@ -612,7 +614,6 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore); | |||
| 612 | /* Interrupt Handling */ | 614 | /* Interrupt Handling */ |
| 613 | bool ath9k_hw_intrpend(struct ath_hw *ah); | 615 | bool ath9k_hw_intrpend(struct ath_hw *ah); |
| 614 | bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); | 616 | bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); |
| 615 | enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah); | ||
| 616 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); | 617 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); |
| 617 | 618 | ||
| 618 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); | 619 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index af4a1bafa7e7..27a86bb7c4c8 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h | |||
| @@ -6365,3 +6365,669 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { | |||
| 6365 | }; | 6365 | }; |
| 6366 | 6366 | ||
| 6367 | 6367 | ||
| 6368 | /* AR9271 initialization values automaticaly created: 03/23/09 */ | ||
| 6369 | static const u_int32_t ar9271Modes_9271_1_0[][6] = { | ||
| 6370 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | ||
| 6371 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | ||
| 6372 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | ||
| 6373 | { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, | ||
| 6374 | { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, | ||
| 6375 | { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, | ||
| 6376 | { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, | ||
| 6377 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, | ||
| 6378 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, | ||
| 6379 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
| 6380 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | ||
| 6381 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
| 6382 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, | ||
| 6383 | { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, | ||
| 6384 | { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, | ||
| 6385 | { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, | ||
| 6386 | { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, | ||
| 6387 | { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, | ||
| 6388 | { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, | ||
| 6389 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, | ||
| 6390 | { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18 }, | ||
| 6391 | { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | ||
| 6392 | { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, | ||
| 6393 | { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, | ||
| 6394 | { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, | ||
| 6395 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, | ||
| 6396 | { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, | ||
| 6397 | { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, | ||
| 6398 | { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
| 6399 | { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
| 6400 | { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, | ||
| 6401 | { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, | ||
| 6402 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, | ||
| 6403 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | ||
| 6404 | { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, | ||
| 6405 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, | ||
| 6406 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | ||
| 6407 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
| 6408 | { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
| 6409 | { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, | ||
| 6410 | { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, | ||
| 6411 | { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, | ||
| 6412 | { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, | ||
| 6413 | { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, | ||
| 6414 | { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, | ||
| 6415 | { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, | ||
| 6416 | { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, | ||
| 6417 | { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, | ||
| 6418 | { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, | ||
| 6419 | { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, | ||
| 6420 | { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, | ||
| 6421 | { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, | ||
| 6422 | { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, | ||
| 6423 | { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, | ||
| 6424 | { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, | ||
| 6425 | { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, | ||
| 6426 | { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, | ||
| 6427 | { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, | ||
| 6428 | { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, | ||
| 6429 | { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, | ||
| 6430 | { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, | ||
| 6431 | { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, | ||
| 6432 | { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, | ||
| 6433 | { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, | ||
| 6434 | { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, | ||
| 6435 | { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, | ||
| 6436 | { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, | ||
| 6437 | { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, | ||
| 6438 | { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, | ||
| 6439 | { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, | ||
| 6440 | { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, | ||
| 6441 | { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, | ||
| 6442 | { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, | ||
| 6443 | { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, | ||
| 6444 | { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | ||
| 6445 | { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | ||
| 6446 | { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, | ||
| 6447 | { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, | ||
| 6448 | { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, | ||
| 6449 | { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, | ||
| 6450 | { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, | ||
| 6451 | { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, | ||
| 6452 | { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, | ||
| 6453 | { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, | ||
| 6454 | { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, | ||
| 6455 | { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, | ||
| 6456 | { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, | ||
| 6457 | { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, | ||
| 6458 | { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, | ||
| 6459 | { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, | ||
| 6460 | { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, | ||
| 6461 | { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, | ||
| 6462 | { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, | ||
| 6463 | { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, | ||
| 6464 | { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, | ||
| 6465 | { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, | ||
| 6466 | { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, | ||
| 6467 | { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, | ||
| 6468 | { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, | ||
| 6469 | { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, | ||
| 6470 | { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, | ||
| 6471 | { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, | ||
| 6472 | { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, | ||
| 6473 | { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, | ||
| 6474 | { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, | ||
| 6475 | { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, | ||
| 6476 | { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, | ||
| 6477 | { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, | ||
| 6478 | { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, | ||
| 6479 | { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, | ||
| 6480 | { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, | ||
| 6481 | { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, | ||
| 6482 | { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, | ||
| 6483 | { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, | ||
| 6484 | { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, | ||
| 6485 | { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, | ||
| 6486 | { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, | ||
| 6487 | { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, | ||
| 6488 | { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, | ||
| 6489 | { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, | ||
| 6490 | { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, | ||
| 6491 | { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, | ||
| 6492 | { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, | ||
| 6493 | { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, | ||
| 6494 | { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, | ||
| 6495 | { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, | ||
| 6496 | { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, | ||
| 6497 | { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, | ||
| 6498 | { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6499 | { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6500 | { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6501 | { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6502 | { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6503 | { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6504 | { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6505 | { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6506 | { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6507 | { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6508 | { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6509 | { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6510 | { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6511 | { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6512 | { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6513 | { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6514 | { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6515 | { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6516 | { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6517 | { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6518 | { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6519 | { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6520 | { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6521 | { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6522 | { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6523 | { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6524 | { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6525 | { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6526 | { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6527 | { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6528 | { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6529 | { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6530 | { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6531 | { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6532 | { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6533 | { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6534 | { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6535 | { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6536 | { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6537 | { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, | ||
| 6538 | { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, | ||
| 6539 | { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, | ||
| 6540 | { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, | ||
| 6541 | { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, | ||
| 6542 | { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, | ||
| 6543 | { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, | ||
| 6544 | { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, | ||
| 6545 | { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, | ||
| 6546 | { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, | ||
| 6547 | { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, | ||
| 6548 | { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, | ||
| 6549 | { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, | ||
| 6550 | { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, | ||
| 6551 | { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, | ||
| 6552 | { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, | ||
| 6553 | { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, | ||
| 6554 | { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, | ||
| 6555 | { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, | ||
| 6556 | { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, | ||
| 6557 | { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, | ||
| 6558 | { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, | ||
| 6559 | { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, | ||
| 6560 | { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, | ||
| 6561 | { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, | ||
| 6562 | { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, | ||
| 6563 | { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, | ||
| 6564 | { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, | ||
| 6565 | { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, | ||
| 6566 | { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, | ||
| 6567 | { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, | ||
| 6568 | { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, | ||
| 6569 | { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, | ||
| 6570 | { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, | ||
| 6571 | { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, | ||
| 6572 | { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | ||
| 6573 | { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | ||
| 6574 | { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, | ||
| 6575 | { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, | ||
| 6576 | { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, | ||
| 6577 | { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, | ||
| 6578 | { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, | ||
| 6579 | { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, | ||
| 6580 | { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, | ||
| 6581 | { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, | ||
| 6582 | { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, | ||
| 6583 | { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, | ||
| 6584 | { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, | ||
| 6585 | { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, | ||
| 6586 | { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, | ||
| 6587 | { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, | ||
| 6588 | { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, | ||
| 6589 | { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, | ||
| 6590 | { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, | ||
| 6591 | { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, | ||
| 6592 | { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, | ||
| 6593 | { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, | ||
| 6594 | { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, | ||
| 6595 | { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, | ||
| 6596 | { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, | ||
| 6597 | { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, | ||
| 6598 | { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, | ||
| 6599 | { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, | ||
| 6600 | { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, | ||
| 6601 | { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, | ||
| 6602 | { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, | ||
| 6603 | { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, | ||
| 6604 | { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, | ||
| 6605 | { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, | ||
| 6606 | { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, | ||
| 6607 | { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, | ||
| 6608 | { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, | ||
| 6609 | { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, | ||
| 6610 | { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, | ||
| 6611 | { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, | ||
| 6612 | { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, | ||
| 6613 | { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, | ||
| 6614 | { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, | ||
| 6615 | { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, | ||
| 6616 | { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, | ||
| 6617 | { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, | ||
| 6618 | { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, | ||
| 6619 | { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, | ||
| 6620 | { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, | ||
| 6621 | { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, | ||
| 6622 | { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, | ||
| 6623 | { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, | ||
| 6624 | { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, | ||
| 6625 | { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, | ||
| 6626 | { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6627 | { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6628 | { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6629 | { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6630 | { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6631 | { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6632 | { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6633 | { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6634 | { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6635 | { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6636 | { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6637 | { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6638 | { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6639 | { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6640 | { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6641 | { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6642 | { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6643 | { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6644 | { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6645 | { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6646 | { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6647 | { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6648 | { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6649 | { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6650 | { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6651 | { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6652 | { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6653 | { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6654 | { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6655 | { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6656 | { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6657 | { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6658 | { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6659 | { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6660 | { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6661 | { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6662 | { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6663 | { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6664 | { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | ||
| 6665 | { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, | ||
| 6666 | { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, | ||
| 6667 | { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, | ||
| 6668 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | ||
| 6669 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | ||
| 6670 | { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, | ||
| 6671 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 }, | ||
| 6672 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
| 6673 | { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, | ||
| 6674 | { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, | ||
| 6675 | { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, | ||
| 6676 | { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 }, | ||
| 6677 | { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 }, | ||
| 6678 | { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 }, | ||
| 6679 | { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 }, | ||
| 6680 | { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 }, | ||
| 6681 | { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 }, | ||
| 6682 | { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 }, | ||
| 6683 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 }, | ||
| 6684 | { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 }, | ||
| 6685 | { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, | ||
| 6686 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
| 6687 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
| 6688 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
| 6689 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
| 6690 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, | ||
| 6691 | }; | ||
| 6692 | |||
| 6693 | static const u_int32_t ar9271Common_9271_1_0[][2] = { | ||
| 6694 | { 0x0000000c, 0x00000000 }, | ||
| 6695 | { 0x00000030, 0x00020045 }, | ||
| 6696 | { 0x00000034, 0x00000005 }, | ||
| 6697 | { 0x00000040, 0x00000000 }, | ||
| 6698 | { 0x00000044, 0x00000008 }, | ||
| 6699 | { 0x00000048, 0x00000008 }, | ||
| 6700 | { 0x0000004c, 0x00000010 }, | ||
| 6701 | { 0x00000050, 0x00000000 }, | ||
| 6702 | { 0x00000054, 0x0000001f }, | ||
| 6703 | { 0x00000800, 0x00000000 }, | ||
| 6704 | { 0x00000804, 0x00000000 }, | ||
| 6705 | { 0x00000808, 0x00000000 }, | ||
| 6706 | { 0x0000080c, 0x00000000 }, | ||
| 6707 | { 0x00000810, 0x00000000 }, | ||
| 6708 | { 0x00000814, 0x00000000 }, | ||
| 6709 | { 0x00000818, 0x00000000 }, | ||
| 6710 | { 0x0000081c, 0x00000000 }, | ||
| 6711 | { 0x00000820, 0x00000000 }, | ||
| 6712 | { 0x00000824, 0x00000000 }, | ||
| 6713 | { 0x00001040, 0x002ffc0f }, | ||
| 6714 | { 0x00001044, 0x002ffc0f }, | ||
| 6715 | { 0x00001048, 0x002ffc0f }, | ||
| 6716 | { 0x0000104c, 0x002ffc0f }, | ||
| 6717 | { 0x00001050, 0x002ffc0f }, | ||
| 6718 | { 0x00001054, 0x002ffc0f }, | ||
| 6719 | { 0x00001058, 0x002ffc0f }, | ||
| 6720 | { 0x0000105c, 0x002ffc0f }, | ||
| 6721 | { 0x00001060, 0x002ffc0f }, | ||
| 6722 | { 0x00001064, 0x002ffc0f }, | ||
| 6723 | { 0x00001230, 0x00000000 }, | ||
| 6724 | { 0x00001270, 0x00000000 }, | ||
| 6725 | { 0x00001038, 0x00000000 }, | ||
| 6726 | { 0x00001078, 0x00000000 }, | ||
| 6727 | { 0x000010b8, 0x00000000 }, | ||
| 6728 | { 0x000010f8, 0x00000000 }, | ||
| 6729 | { 0x00001138, 0x00000000 }, | ||
| 6730 | { 0x00001178, 0x00000000 }, | ||
| 6731 | { 0x000011b8, 0x00000000 }, | ||
| 6732 | { 0x000011f8, 0x00000000 }, | ||
| 6733 | { 0x00001238, 0x00000000 }, | ||
| 6734 | { 0x00001278, 0x00000000 }, | ||
| 6735 | { 0x000012b8, 0x00000000 }, | ||
| 6736 | { 0x000012f8, 0x00000000 }, | ||
| 6737 | { 0x00001338, 0x00000000 }, | ||
| 6738 | { 0x00001378, 0x00000000 }, | ||
| 6739 | { 0x000013b8, 0x00000000 }, | ||
| 6740 | { 0x000013f8, 0x00000000 }, | ||
| 6741 | { 0x00001438, 0x00000000 }, | ||
| 6742 | { 0x00001478, 0x00000000 }, | ||
| 6743 | { 0x000014b8, 0x00000000 }, | ||
| 6744 | { 0x000014f8, 0x00000000 }, | ||
| 6745 | { 0x00001538, 0x00000000 }, | ||
| 6746 | { 0x00001578, 0x00000000 }, | ||
| 6747 | { 0x000015b8, 0x00000000 }, | ||
| 6748 | { 0x000015f8, 0x00000000 }, | ||
| 6749 | { 0x00001638, 0x00000000 }, | ||
| 6750 | { 0x00001678, 0x00000000 }, | ||
| 6751 | { 0x000016b8, 0x00000000 }, | ||
| 6752 | { 0x000016f8, 0x00000000 }, | ||
| 6753 | { 0x00001738, 0x00000000 }, | ||
| 6754 | { 0x00001778, 0x00000000 }, | ||
| 6755 | { 0x000017b8, 0x00000000 }, | ||
| 6756 | { 0x000017f8, 0x00000000 }, | ||
| 6757 | { 0x0000103c, 0x00000000 }, | ||
| 6758 | { 0x0000107c, 0x00000000 }, | ||
| 6759 | { 0x000010bc, 0x00000000 }, | ||
| 6760 | { 0x000010fc, 0x00000000 }, | ||
| 6761 | { 0x0000113c, 0x00000000 }, | ||
| 6762 | { 0x0000117c, 0x00000000 }, | ||
| 6763 | { 0x000011bc, 0x00000000 }, | ||
| 6764 | { 0x000011fc, 0x00000000 }, | ||
| 6765 | { 0x0000123c, 0x00000000 }, | ||
| 6766 | { 0x0000127c, 0x00000000 }, | ||
| 6767 | { 0x000012bc, 0x00000000 }, | ||
| 6768 | { 0x000012fc, 0x00000000 }, | ||
| 6769 | { 0x0000133c, 0x00000000 }, | ||
| 6770 | { 0x0000137c, 0x00000000 }, | ||
| 6771 | { 0x000013bc, 0x00000000 }, | ||
| 6772 | { 0x000013fc, 0x00000000 }, | ||
| 6773 | { 0x0000143c, 0x00000000 }, | ||
| 6774 | { 0x0000147c, 0x00000000 }, | ||
| 6775 | { 0x00004030, 0x00000002 }, | ||
| 6776 | { 0x0000403c, 0x00000002 }, | ||
| 6777 | { 0x00004024, 0x0000001f }, | ||
| 6778 | { 0x00004060, 0x00000000 }, | ||
| 6779 | { 0x00004064, 0x00000000 }, | ||
| 6780 | { 0x00008004, 0x00000000 }, | ||
| 6781 | { 0x00008008, 0x00000000 }, | ||
| 6782 | { 0x0000800c, 0x00000000 }, | ||
| 6783 | { 0x00008018, 0x00000700 }, | ||
| 6784 | { 0x00008020, 0x00000000 }, | ||
| 6785 | { 0x00008038, 0x00000000 }, | ||
| 6786 | { 0x0000803c, 0x00000000 }, | ||
| 6787 | { 0x00008048, 0x00000000 }, | ||
| 6788 | { 0x00008054, 0x00000000 }, | ||
| 6789 | { 0x00008058, 0x02000000 }, | ||
| 6790 | { 0x0000805c, 0x000fc78f }, | ||
| 6791 | { 0x00008060, 0x0000000f }, | ||
| 6792 | { 0x00008064, 0x00000000 }, | ||
| 6793 | { 0x00008070, 0x00000000 }, | ||
| 6794 | { 0x000080b0, 0x00000000 }, | ||
| 6795 | { 0x000080b4, 0x00000000 }, | ||
| 6796 | { 0x000080b8, 0x00000000 }, | ||
| 6797 | { 0x000080bc, 0x00000000 }, | ||
| 6798 | { 0x000080c0, 0x2a80001a }, | ||
| 6799 | { 0x000080c4, 0x05dc01e0 }, | ||
| 6800 | { 0x000080c8, 0x1f402710 }, | ||
| 6801 | { 0x000080cc, 0x01f40000 }, | ||
| 6802 | { 0x000080d0, 0x00001e00 }, | ||
| 6803 | { 0x000080d4, 0x00000000 }, | ||
| 6804 | { 0x000080d8, 0x00400000 }, | ||
| 6805 | { 0x000080e0, 0xffffffff }, | ||
| 6806 | { 0x000080e4, 0x0000ffff }, | ||
| 6807 | { 0x000080e8, 0x003f3f3f }, | ||
| 6808 | { 0x000080ec, 0x00000000 }, | ||
| 6809 | { 0x000080f0, 0x00000000 }, | ||
| 6810 | { 0x000080f4, 0x00000000 }, | ||
| 6811 | { 0x000080f8, 0x00000000 }, | ||
| 6812 | { 0x000080fc, 0x00020000 }, | ||
| 6813 | { 0x00008100, 0x00020000 }, | ||
| 6814 | { 0x00008104, 0x00000001 }, | ||
| 6815 | { 0x00008108, 0x00000052 }, | ||
| 6816 | { 0x0000810c, 0x00000000 }, | ||
| 6817 | { 0x00008110, 0x00000168 }, | ||
| 6818 | { 0x00008118, 0x000100aa }, | ||
| 6819 | { 0x0000811c, 0x00003210 }, | ||
| 6820 | { 0x00008120, 0x08f04814 }, | ||
| 6821 | { 0x00008124, 0x00000000 }, | ||
| 6822 | { 0x00008128, 0x00000000 }, | ||
| 6823 | { 0x0000812c, 0x00000000 }, | ||
| 6824 | { 0x00008130, 0x00000000 }, | ||
| 6825 | { 0x00008134, 0x00000000 }, | ||
| 6826 | { 0x00008138, 0x00000000 }, | ||
| 6827 | { 0x0000813c, 0x00000000 }, | ||
| 6828 | { 0x00008144, 0xffffffff }, | ||
| 6829 | { 0x00008168, 0x00000000 }, | ||
| 6830 | { 0x0000816c, 0x00000000 }, | ||
| 6831 | { 0x00008170, 0x32143320 }, | ||
| 6832 | { 0x00008174, 0xfaa4fa50 }, | ||
| 6833 | { 0x00008178, 0x00000100 }, | ||
| 6834 | { 0x0000817c, 0x00000000 }, | ||
| 6835 | { 0x000081c0, 0x00000000 }, | ||
| 6836 | { 0x000081d0, 0x0000320a }, | ||
| 6837 | { 0x000081ec, 0x00000000 }, | ||
| 6838 | { 0x000081f0, 0x00000000 }, | ||
| 6839 | { 0x000081f4, 0x00000000 }, | ||
| 6840 | { 0x000081f8, 0x00000000 }, | ||
| 6841 | { 0x000081fc, 0x00000000 }, | ||
| 6842 | { 0x00008200, 0x00000000 }, | ||
| 6843 | { 0x00008204, 0x00000000 }, | ||
| 6844 | { 0x00008208, 0x00000000 }, | ||
| 6845 | { 0x0000820c, 0x00000000 }, | ||
| 6846 | { 0x00008210, 0x00000000 }, | ||
| 6847 | { 0x00008214, 0x00000000 }, | ||
| 6848 | { 0x00008218, 0x00000000 }, | ||
| 6849 | { 0x0000821c, 0x00000000 }, | ||
| 6850 | { 0x00008220, 0x00000000 }, | ||
| 6851 | { 0x00008224, 0x00000000 }, | ||
| 6852 | { 0x00008228, 0x00000000 }, | ||
| 6853 | { 0x0000822c, 0x00000000 }, | ||
| 6854 | { 0x00008230, 0x00000000 }, | ||
| 6855 | { 0x00008234, 0x00000000 }, | ||
| 6856 | { 0x00008238, 0x00000000 }, | ||
| 6857 | { 0x0000823c, 0x00000000 }, | ||
| 6858 | { 0x00008240, 0x00100000 }, | ||
| 6859 | { 0x00008244, 0x0010f400 }, | ||
| 6860 | { 0x00008248, 0x00000100 }, | ||
| 6861 | { 0x0000824c, 0x0001e800 }, | ||
| 6862 | { 0x00008250, 0x00000000 }, | ||
| 6863 | { 0x00008254, 0x00000000 }, | ||
| 6864 | { 0x00008258, 0x00000000 }, | ||
| 6865 | { 0x0000825c, 0x400000ff }, | ||
| 6866 | { 0x00008260, 0x00080922 }, | ||
| 6867 | { 0x00008264, 0xa8a00010 }, | ||
| 6868 | { 0x00008270, 0x00000000 }, | ||
| 6869 | { 0x00008274, 0x40000000 }, | ||
| 6870 | { 0x00008278, 0x003e4180 }, | ||
| 6871 | { 0x0000827c, 0x00000000 }, | ||
| 6872 | { 0x00008284, 0x0000002c }, | ||
| 6873 | { 0x00008288, 0x0000002c }, | ||
| 6874 | { 0x0000828c, 0x00000000 }, | ||
| 6875 | { 0x00008294, 0x00000000 }, | ||
| 6876 | { 0x00008298, 0x00000000 }, | ||
| 6877 | { 0x0000829c, 0x00000000 }, | ||
| 6878 | { 0x00008300, 0x00000040 }, | ||
| 6879 | { 0x00008314, 0x00000000 }, | ||
| 6880 | { 0x00008328, 0x00000000 }, | ||
| 6881 | { 0x0000832c, 0x00000001 }, | ||
| 6882 | { 0x00008330, 0x00000302 }, | ||
| 6883 | { 0x00008334, 0x00000e00 }, | ||
| 6884 | { 0x00008338, 0x00ff0000 }, | ||
| 6885 | { 0x0000833c, 0x00000000 }, | ||
| 6886 | { 0x00008340, 0x00010380 }, | ||
| 6887 | { 0x00008344, 0x00581043 }, | ||
| 6888 | { 0x00007010, 0x00000030 }, | ||
| 6889 | { 0x00007034, 0x00000002 }, | ||
| 6890 | { 0x00007038, 0x000004c2 }, | ||
| 6891 | { 0x00007800, 0x00140000 }, | ||
| 6892 | { 0x00007804, 0x0e4548d8 }, | ||
| 6893 | { 0x00007808, 0x54214514 }, | ||
| 6894 | { 0x0000780c, 0x02025820 }, | ||
| 6895 | { 0x00007810, 0x71c0d388 }, | ||
| 6896 | { 0x00007814, 0x924934a8 }, | ||
| 6897 | { 0x0000781c, 0x00000000 }, | ||
| 6898 | { 0x00007820, 0x00000c04 }, | ||
| 6899 | { 0x00007824, 0x00d86bff }, | ||
| 6900 | { 0x00007828, 0x66964300 }, | ||
| 6901 | { 0x0000782c, 0x8db6d961 }, | ||
| 6902 | { 0x00007830, 0x8db6d96c }, | ||
| 6903 | { 0x00007834, 0x6140008b }, | ||
| 6904 | { 0x00007838, 0x00000029 }, | ||
| 6905 | { 0x0000783c, 0x72ee0a72 }, | ||
| 6906 | { 0x00007840, 0xbbfffffc }, | ||
| 6907 | { 0x00007844, 0x000c0db6 }, | ||
| 6908 | { 0x00007848, 0x6db61b6f }, | ||
| 6909 | { 0x0000784c, 0x6d9b66db }, | ||
| 6910 | { 0x00007850, 0x6d8c6dba }, | ||
| 6911 | { 0x00007854, 0x00040000 }, | ||
| 6912 | { 0x00007858, 0xdb003012 }, | ||
| 6913 | { 0x0000785c, 0x04924914 }, | ||
| 6914 | { 0x00007860, 0x21084210 }, | ||
| 6915 | { 0x00007864, 0xf7d7ffde }, | ||
| 6916 | { 0x00007868, 0xc2034080 }, | ||
| 6917 | { 0x0000786c, 0x48609eb4 }, | ||
| 6918 | { 0x00007870, 0x10142c00 }, | ||
| 6919 | { 0x00009808, 0x00000000 }, | ||
| 6920 | { 0x0000980c, 0xafe68e30 }, | ||
| 6921 | { 0x00009810, 0xfd14e000 }, | ||
| 6922 | { 0x00009814, 0x9c0a9f6b }, | ||
| 6923 | { 0x0000981c, 0x00000000 }, | ||
| 6924 | { 0x0000982c, 0x0000a000 }, | ||
| 6925 | { 0x00009830, 0x00000000 }, | ||
| 6926 | { 0x0000983c, 0x00200400 }, | ||
| 6927 | { 0x0000984c, 0x0040233c }, | ||
| 6928 | { 0x00009854, 0x00000044 }, | ||
| 6929 | { 0x00009900, 0x00000000 }, | ||
| 6930 | { 0x00009904, 0x00000000 }, | ||
| 6931 | { 0x00009908, 0x00000000 }, | ||
| 6932 | { 0x0000990c, 0x00000000 }, | ||
| 6933 | { 0x00009910, 0x30002310 }, | ||
| 6934 | { 0x0000991c, 0x10000fff }, | ||
| 6935 | { 0x00009920, 0x04900000 }, | ||
| 6936 | { 0x00009928, 0x00000001 }, | ||
| 6937 | { 0x0000992c, 0x00000004 }, | ||
| 6938 | { 0x00009934, 0x1e1f2022 }, | ||
| 6939 | { 0x00009938, 0x0a0b0c0d }, | ||
| 6940 | { 0x0000993c, 0x00000000 }, | ||
| 6941 | { 0x00009940, 0x14750604 }, | ||
| 6942 | { 0x00009948, 0x9280c00a }, | ||
| 6943 | { 0x0000994c, 0x00020028 }, | ||
| 6944 | { 0x00009954, 0x5f3ca3de }, | ||
| 6945 | { 0x00009958, 0x0108ecff }, | ||
| 6946 | { 0x00009968, 0x000003ce }, | ||
| 6947 | { 0x00009970, 0x192bb515 }, | ||
| 6948 | { 0x00009974, 0x00000000 }, | ||
| 6949 | { 0x00009978, 0x00000001 }, | ||
| 6950 | { 0x0000997c, 0x00000000 }, | ||
| 6951 | { 0x00009980, 0x00000000 }, | ||
| 6952 | { 0x00009984, 0x00000000 }, | ||
| 6953 | { 0x00009988, 0x00000000 }, | ||
| 6954 | { 0x0000998c, 0x00000000 }, | ||
| 6955 | { 0x00009990, 0x00000000 }, | ||
| 6956 | { 0x00009994, 0x00000000 }, | ||
| 6957 | { 0x00009998, 0x00000000 }, | ||
| 6958 | { 0x0000999c, 0x00000000 }, | ||
| 6959 | { 0x000099a0, 0x00000000 }, | ||
| 6960 | { 0x000099a4, 0x00000001 }, | ||
| 6961 | { 0x000099a8, 0x201fff00 }, | ||
| 6962 | { 0x000099ac, 0x2def0400 }, | ||
| 6963 | { 0x000099b0, 0x03051000 }, | ||
| 6964 | { 0x000099b4, 0x00000820 }, | ||
| 6965 | { 0x000099dc, 0x00000000 }, | ||
| 6966 | { 0x000099e0, 0x00000000 }, | ||
| 6967 | { 0x000099e4, 0xaaaaaaaa }, | ||
| 6968 | { 0x000099e8, 0x3c466478 }, | ||
| 6969 | { 0x000099ec, 0x0cc80caa }, | ||
| 6970 | { 0x000099f0, 0x00000000 }, | ||
| 6971 | { 0x0000a1f4, 0x00000000 }, | ||
| 6972 | { 0x0000a1f8, 0x71733d01 }, | ||
| 6973 | { 0x0000a1fc, 0xd0ad5c12 }, | ||
| 6974 | { 0x0000a208, 0x803e68c8 }, | ||
| 6975 | { 0x0000a210, 0x4080a333 }, | ||
| 6976 | { 0x0000a214, 0x00206c10 }, | ||
| 6977 | { 0x0000a218, 0x009c4060 }, | ||
| 6978 | { 0x0000a220, 0x01834061 }, | ||
| 6979 | { 0x0000a224, 0x00000400 }, | ||
| 6980 | { 0x0000a228, 0x000003b5 }, | ||
| 6981 | { 0x0000a22c, 0x00000000 }, | ||
| 6982 | { 0x0000a234, 0x20202020 }, | ||
| 6983 | { 0x0000a238, 0x20202020 }, | ||
| 6984 | { 0x0000a244, 0x00000000 }, | ||
| 6985 | { 0x0000a248, 0xfffffffc }, | ||
| 6986 | { 0x0000a24c, 0x00000000 }, | ||
| 6987 | { 0x0000a254, 0x00000000 }, | ||
| 6988 | { 0x0000a258, 0x0ccb5380 }, | ||
| 6989 | { 0x0000a25c, 0x15151501 }, | ||
| 6990 | { 0x0000a260, 0xdfa90f01 }, | ||
| 6991 | { 0x0000a268, 0x00000000 }, | ||
| 6992 | { 0x0000a26c, 0x0ebae9e6 }, | ||
| 6993 | { 0x0000a278, 0x3bdef7bd }, | ||
| 6994 | { 0x0000a27c, 0x050e83bd }, | ||
| 6995 | { 0x0000a388, 0x0c000000 }, | ||
| 6996 | { 0x0000a38c, 0x20202020 }, | ||
| 6997 | { 0x0000a390, 0x20202020 }, | ||
| 6998 | { 0x0000a394, 0x3bdef7bd }, | ||
| 6999 | { 0x0000a398, 0x000003bd }, | ||
| 7000 | { 0x0000a39c, 0x00000001 }, | ||
| 7001 | { 0x0000a3a0, 0x00000000 }, | ||
| 7002 | { 0x0000a3a4, 0x00000000 }, | ||
| 7003 | { 0x0000a3a8, 0x00000000 }, | ||
| 7004 | { 0x0000a3ac, 0x00000000 }, | ||
| 7005 | { 0x0000a3b0, 0x00000000 }, | ||
| 7006 | { 0x0000a3b4, 0x00000000 }, | ||
| 7007 | { 0x0000a3b8, 0x00000000 }, | ||
| 7008 | { 0x0000a3bc, 0x00000000 }, | ||
| 7009 | { 0x0000a3c0, 0x00000000 }, | ||
| 7010 | { 0x0000a3c4, 0x00000000 }, | ||
| 7011 | { 0x0000a3cc, 0x20202020 }, | ||
| 7012 | { 0x0000a3d0, 0x20202020 }, | ||
| 7013 | { 0x0000a3d4, 0x20202020 }, | ||
| 7014 | { 0x0000a3dc, 0x3bdef7bd }, | ||
| 7015 | { 0x0000a3e0, 0x000003bd }, | ||
| 7016 | { 0x0000a3e4, 0x00000000 }, | ||
| 7017 | { 0x0000a3e8, 0x18c43433 }, | ||
| 7018 | { 0x0000a3ec, 0x00f70081 }, | ||
| 7019 | { 0x0000a3f0, 0x01036a2f }, | ||
| 7020 | { 0x0000a3f4, 0x00000000 }, | ||
| 7021 | { 0x0000d270, 0x0d820820 }, | ||
| 7022 | { 0x0000d35c, 0x07ffffef }, | ||
| 7023 | { 0x0000d360, 0x0fffffe7 }, | ||
| 7024 | { 0x0000d364, 0x17ffffe5 }, | ||
| 7025 | { 0x0000d368, 0x1fffffe4 }, | ||
| 7026 | { 0x0000d36c, 0x37ffffe3 }, | ||
| 7027 | { 0x0000d370, 0x3fffffe3 }, | ||
| 7028 | { 0x0000d374, 0x57ffffe3 }, | ||
| 7029 | { 0x0000d378, 0x5fffffe2 }, | ||
| 7030 | { 0x0000d37c, 0x7fffffe2 }, | ||
| 7031 | { 0x0000d380, 0x7f3c7bba }, | ||
| 7032 | { 0x0000d384, 0xf3307ff0 }, | ||
| 7033 | }; | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 75ddb2acb644..a9e43f7a23f6 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -973,10 +973,11 @@ static void ath_led_blink_work(struct work_struct *work) | |||
| 973 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, | 973 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, |
| 974 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | 974 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); |
| 975 | 975 | ||
| 976 | queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work, | 976 | ieee80211_queue_delayed_work(sc->hw, |
| 977 | (sc->sc_flags & SC_OP_LED_ON) ? | 977 | &sc->ath_led_blink_work, |
| 978 | msecs_to_jiffies(sc->led_off_duration) : | 978 | (sc->sc_flags & SC_OP_LED_ON) ? |
| 979 | msecs_to_jiffies(sc->led_on_duration)); | 979 | msecs_to_jiffies(sc->led_off_duration) : |
| 980 | msecs_to_jiffies(sc->led_on_duration)); | ||
| 980 | 981 | ||
| 981 | sc->led_on_duration = sc->led_on_cnt ? | 982 | sc->led_on_duration = sc->led_on_cnt ? |
| 982 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : | 983 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : |
| @@ -1013,8 +1014,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev, | |||
| 1013 | case LED_FULL: | 1014 | case LED_FULL: |
| 1014 | if (led->led_type == ATH_LED_ASSOC) { | 1015 | if (led->led_type == ATH_LED_ASSOC) { |
| 1015 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; | 1016 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; |
| 1016 | queue_delayed_work(sc->hw->workqueue, | 1017 | ieee80211_queue_delayed_work(sc->hw, |
| 1017 | &sc->ath_led_blink_work, 0); | 1018 | &sc->ath_led_blink_work, 0); |
| 1018 | } else if (led->led_type == ATH_LED_RADIO) { | 1019 | } else if (led->led_type == ATH_LED_RADIO) { |
| 1019 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); | 1020 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); |
| 1020 | sc->sc_flags |= SC_OP_LED_ON; | 1021 | sc->sc_flags |= SC_OP_LED_ON; |
| @@ -1056,7 +1057,6 @@ static void ath_unregister_led(struct ath_led *led) | |||
| 1056 | 1057 | ||
| 1057 | static void ath_deinit_leds(struct ath_softc *sc) | 1058 | static void ath_deinit_leds(struct ath_softc *sc) |
| 1058 | { | 1059 | { |
| 1059 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
| 1060 | ath_unregister_led(&sc->assoc_led); | 1060 | ath_unregister_led(&sc->assoc_led); |
| 1061 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | 1061 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; |
| 1062 | ath_unregister_led(&sc->tx_led); | 1062 | ath_unregister_led(&sc->tx_led); |
| @@ -1113,6 +1113,7 @@ static void ath_init_leds(struct ath_softc *sc) | |||
| 1113 | return; | 1113 | return; |
| 1114 | 1114 | ||
| 1115 | fail: | 1115 | fail: |
| 1116 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
| 1116 | ath_deinit_leds(sc); | 1117 | ath_deinit_leds(sc); |
| 1117 | } | 1118 | } |
| 1118 | 1119 | ||
| @@ -1252,9 +1253,6 @@ void ath_detach(struct ath_softc *sc) | |||
| 1252 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); | 1253 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); |
| 1253 | 1254 | ||
| 1254 | ath_deinit_leds(sc); | 1255 | ath_deinit_leds(sc); |
| 1255 | cancel_work_sync(&sc->chan_work); | ||
| 1256 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
| 1257 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
| 1258 | 1256 | ||
| 1259 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 1257 | for (i = 0; i < sc->num_sec_wiphy; i++) { |
| 1260 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 1258 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
| @@ -1280,6 +1278,7 @@ void ath_detach(struct ath_softc *sc) | |||
| 1280 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 1278 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
| 1281 | 1279 | ||
| 1282 | ath9k_hw_detach(sc->sc_ah); | 1280 | ath9k_hw_detach(sc->sc_ah); |
| 1281 | sc->sc_ah = NULL; | ||
| 1283 | ath9k_exit_debug(sc); | 1282 | ath9k_exit_debug(sc); |
| 1284 | } | 1283 | } |
| 1285 | 1284 | ||
| @@ -1294,11 +1293,16 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
| 1294 | return ath_reg_notifier_apply(wiphy, request, reg); | 1293 | return ath_reg_notifier_apply(wiphy, request, reg); |
| 1295 | } | 1294 | } |
| 1296 | 1295 | ||
| 1297 | static int ath_init(u16 devid, struct ath_softc *sc) | 1296 | /* |
| 1297 | * Initialize and fill ath_softc, ath_sofct is the | ||
| 1298 | * "Software Carrier" struct. Historically it has existed | ||
| 1299 | * to allow the separation between hardware specific | ||
| 1300 | * variables (now in ath_hw) and driver specific variables. | ||
| 1301 | */ | ||
| 1302 | static int ath_init_softc(u16 devid, struct ath_softc *sc) | ||
| 1298 | { | 1303 | { |
| 1299 | struct ath_hw *ah = NULL; | 1304 | struct ath_hw *ah = NULL; |
| 1300 | int status; | 1305 | int r = 0, i; |
| 1301 | int error = 0, i; | ||
| 1302 | int csz = 0; | 1306 | int csz = 0; |
| 1303 | 1307 | ||
| 1304 | /* XXX: hardware will not be ready until ath_open() being called */ | 1308 | /* XXX: hardware will not be ready until ath_open() being called */ |
| @@ -1325,14 +1329,23 @@ static int ath_init(u16 devid, struct ath_softc *sc) | |||
| 1325 | /* XXX assert csz is non-zero */ | 1329 | /* XXX assert csz is non-zero */ |
| 1326 | sc->cachelsz = csz << 2; /* convert to bytes */ | 1330 | sc->cachelsz = csz << 2; /* convert to bytes */ |
| 1327 | 1331 | ||
| 1328 | ah = ath9k_hw_attach(devid, sc, &status); | 1332 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); |
| 1329 | if (ah == NULL) { | 1333 | if (!ah) { |
| 1334 | r = -ENOMEM; | ||
| 1335 | goto bad_no_ah; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | ah->ah_sc = sc; | ||
| 1339 | ah->hw_version.devid = devid; | ||
| 1340 | sc->sc_ah = ah; | ||
| 1341 | |||
| 1342 | r = ath9k_hw_init(ah); | ||
| 1343 | if (r) { | ||
| 1330 | DPRINTF(sc, ATH_DBG_FATAL, | 1344 | DPRINTF(sc, ATH_DBG_FATAL, |
| 1331 | "Unable to attach hardware; HAL status %d\n", status); | 1345 | "Unable to initialize hardware; " |
| 1332 | error = -ENXIO; | 1346 | "initialization status: %d\n", r); |
| 1333 | goto bad; | 1347 | goto bad; |
| 1334 | } | 1348 | } |
| 1335 | sc->sc_ah = ah; | ||
| 1336 | 1349 | ||
| 1337 | /* Get the hardware key cache size. */ | 1350 | /* Get the hardware key cache size. */ |
| 1338 | sc->keymax = ah->caps.keycache_size; | 1351 | sc->keymax = ah->caps.keycache_size; |
| @@ -1350,9 +1363,6 @@ static int ath_init(u16 devid, struct ath_softc *sc) | |||
| 1350 | for (i = 0; i < sc->keymax; i++) | 1363 | for (i = 0; i < sc->keymax; i++) |
| 1351 | ath9k_hw_keyreset(ah, (u16) i); | 1364 | ath9k_hw_keyreset(ah, (u16) i); |
| 1352 | 1365 | ||
| 1353 | if (error) | ||
| 1354 | goto bad; | ||
| 1355 | |||
| 1356 | /* default to MONITOR mode */ | 1366 | /* default to MONITOR mode */ |
| 1357 | sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; | 1367 | sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; |
| 1358 | 1368 | ||
| @@ -1372,14 +1382,14 @@ static int ath_init(u16 devid, struct ath_softc *sc) | |||
| 1372 | if (sc->beacon.beaconq == -1) { | 1382 | if (sc->beacon.beaconq == -1) { |
| 1373 | DPRINTF(sc, ATH_DBG_FATAL, | 1383 | DPRINTF(sc, ATH_DBG_FATAL, |
| 1374 | "Unable to setup a beacon xmit queue\n"); | 1384 | "Unable to setup a beacon xmit queue\n"); |
| 1375 | error = -EIO; | 1385 | r = -EIO; |
| 1376 | goto bad2; | 1386 | goto bad2; |
| 1377 | } | 1387 | } |
| 1378 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | 1388 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); |
| 1379 | if (sc->beacon.cabq == NULL) { | 1389 | if (sc->beacon.cabq == NULL) { |
| 1380 | DPRINTF(sc, ATH_DBG_FATAL, | 1390 | DPRINTF(sc, ATH_DBG_FATAL, |
| 1381 | "Unable to setup CAB xmit queue\n"); | 1391 | "Unable to setup CAB xmit queue\n"); |
| 1382 | error = -EIO; | 1392 | r = -EIO; |
| 1383 | goto bad2; | 1393 | goto bad2; |
| 1384 | } | 1394 | } |
| 1385 | 1395 | ||
| @@ -1394,26 +1404,26 @@ static int ath_init(u16 devid, struct ath_softc *sc) | |||
| 1394 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | 1404 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { |
| 1395 | DPRINTF(sc, ATH_DBG_FATAL, | 1405 | DPRINTF(sc, ATH_DBG_FATAL, |
| 1396 | "Unable to setup xmit queue for BK traffic\n"); | 1406 | "Unable to setup xmit queue for BK traffic\n"); |
| 1397 | error = -EIO; | 1407 | r = -EIO; |
| 1398 | goto bad2; | 1408 | goto bad2; |
| 1399 | } | 1409 | } |
| 1400 | 1410 | ||
| 1401 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | 1411 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { |
| 1402 | DPRINTF(sc, ATH_DBG_FATAL, | 1412 | DPRINTF(sc, ATH_DBG_FATAL, |
| 1403 | "Unable to setup xmit queue for BE traffic\n"); | 1413 | "Unable to setup xmit queue for BE traffic\n"); |
| 1404 | error = -EIO; | 1414 | r = -EIO; |
| 1405 | goto bad2; | 1415 | goto bad2; |
| 1406 | } | 1416 | } |
| 1407 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | 1417 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { |
| 1408 | DPRINTF(sc, ATH_DBG_FATAL, | 1418 | DPRINTF(sc, ATH_DBG_FATAL, |
| 1409 | "Unable to setup xmit queue for VI traffic\n"); | 1419 | "Unable to setup xmit queue for VI traffic\n"); |
| 1410 | error = -EIO; | 1420 | r = -EIO; |
| 1411 | goto bad2; | 1421 | goto bad2; |
| 1412 | } | 1422 | } |
| 1413 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | 1423 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { |
| 1414 | DPRINTF(sc, ATH_DBG_FATAL, | 1424 | DPRINTF(sc, ATH_DBG_FATAL, |
| 1415 | "Unable to setup xmit queue for VO traffic\n"); | 1425 | "Unable to setup xmit queue for VO traffic\n"); |
| 1416 | error = -EIO; | 1426 | r = -EIO; |
| 1417 | goto bad2; | 1427 | goto bad2; |
| 1418 | } | 1428 | } |
| 1419 | 1429 | ||
| @@ -1507,11 +1517,12 @@ bad2: | |||
| 1507 | if (ATH_TXQ_SETUP(sc, i)) | 1517 | if (ATH_TXQ_SETUP(sc, i)) |
| 1508 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 1518 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
| 1509 | bad: | 1519 | bad: |
| 1510 | if (ah) | 1520 | ath9k_hw_detach(ah); |
| 1511 | ath9k_hw_detach(ah); | 1521 | sc->sc_ah = NULL; |
| 1522 | bad_no_ah: | ||
| 1512 | ath9k_exit_debug(sc); | 1523 | ath9k_exit_debug(sc); |
| 1513 | 1524 | ||
| 1514 | return error; | 1525 | return r; |
| 1515 | } | 1526 | } |
| 1516 | 1527 | ||
| 1517 | void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 1528 | void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
| @@ -1551,7 +1562,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
| 1551 | &sc->sbands[IEEE80211_BAND_5GHZ]; | 1562 | &sc->sbands[IEEE80211_BAND_5GHZ]; |
| 1552 | } | 1563 | } |
| 1553 | 1564 | ||
| 1554 | int ath_attach(u16 devid, struct ath_softc *sc) | 1565 | /* Device driver core initialization */ |
| 1566 | int ath_init_device(u16 devid, struct ath_softc *sc) | ||
| 1555 | { | 1567 | { |
| 1556 | struct ieee80211_hw *hw = sc->hw; | 1568 | struct ieee80211_hw *hw = sc->hw; |
| 1557 | int error = 0, i; | 1569 | int error = 0, i; |
| @@ -1559,7 +1571,7 @@ int ath_attach(u16 devid, struct ath_softc *sc) | |||
| 1559 | 1571 | ||
| 1560 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); | 1572 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); |
| 1561 | 1573 | ||
| 1562 | error = ath_init(devid, sc); | 1574 | error = ath_init_softc(devid, sc); |
| 1563 | if (error != 0) | 1575 | if (error != 0) |
| 1564 | return error; | 1576 | return error; |
| 1565 | 1577 | ||
| @@ -1617,6 +1629,7 @@ error_attach: | |||
| 1617 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 1629 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
| 1618 | 1630 | ||
| 1619 | ath9k_hw_detach(sc->sc_ah); | 1631 | ath9k_hw_detach(sc->sc_ah); |
| 1632 | sc->sc_ah = NULL; | ||
| 1620 | ath9k_exit_debug(sc); | 1633 | ath9k_exit_debug(sc); |
| 1621 | 1634 | ||
| 1622 | return error; | 1635 | return error; |
| @@ -1975,7 +1988,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
| 1975 | 1988 | ||
| 1976 | ieee80211_wake_queues(hw); | 1989 | ieee80211_wake_queues(hw); |
| 1977 | 1990 | ||
| 1978 | queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, 0); | 1991 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
| 1979 | 1992 | ||
| 1980 | mutex_unlock: | 1993 | mutex_unlock: |
| 1981 | mutex_unlock(&sc->mutex); | 1994 | mutex_unlock(&sc->mutex); |
| @@ -2089,6 +2102,14 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 2089 | 2102 | ||
| 2090 | aphy->state = ATH_WIPHY_INACTIVE; | 2103 | aphy->state = ATH_WIPHY_INACTIVE; |
| 2091 | 2104 | ||
| 2105 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
| 2106 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
| 2107 | |||
| 2108 | if (!sc->num_sec_wiphy) { | ||
| 2109 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
| 2110 | cancel_work_sync(&sc->chan_work); | ||
| 2111 | } | ||
| 2112 | |||
| 2092 | if (sc->sc_flags & SC_OP_INVALID) { | 2113 | if (sc->sc_flags & SC_OP_INVALID) { |
| 2093 | DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); | 2114 | DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); |
| 2094 | return; | 2115 | return; |
| @@ -2096,6 +2117,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 2096 | 2117 | ||
| 2097 | mutex_lock(&sc->mutex); | 2118 | mutex_lock(&sc->mutex); |
| 2098 | 2119 | ||
| 2120 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
| 2121 | |||
| 2099 | if (ath9k_wiphy_started(sc)) { | 2122 | if (ath9k_wiphy_started(sc)) { |
| 2100 | mutex_unlock(&sc->mutex); | 2123 | mutex_unlock(&sc->mutex); |
| 2101 | return; /* another wiphy still in use */ | 2124 | return; /* another wiphy still in use */ |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index cd4841be80af..3546504a83c4 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
| @@ -178,7 +178,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 178 | sc->mem = mem; | 178 | sc->mem = mem; |
| 179 | sc->bus_ops = &ath_pci_bus_ops; | 179 | sc->bus_ops = &ath_pci_bus_ops; |
| 180 | 180 | ||
| 181 | if (ath_attach(id->device, sc) != 0) { | 181 | if (ath_init_device(id->device, sc) != 0) { |
| 182 | ret = -ENODEV; | 182 | ret = -ENODEV; |
| 183 | goto bad3; | 183 | goto bad3; |
| 184 | } | 184 | } |
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c index aaa941561c36..59bb3ce1e646 100644 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c | |||
| @@ -264,44 +264,23 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | void | 266 | void |
| 267 | ath9k_hw_rfdetach(struct ath_hw *ah) | 267 | ath9k_hw_rf_free(struct ath_hw *ah) |
| 268 | { | 268 | { |
| 269 | if (ah->analogBank0Data != NULL) { | 269 | #define ATH_FREE_BANK(bank) do { \ |
| 270 | kfree(ah->analogBank0Data); | 270 | kfree(bank); \ |
| 271 | ah->analogBank0Data = NULL; | 271 | bank = NULL; \ |
| 272 | } | 272 | } while (0); |
| 273 | if (ah->analogBank1Data != NULL) { | 273 | |
| 274 | kfree(ah->analogBank1Data); | 274 | ATH_FREE_BANK(ah->analogBank0Data); |
| 275 | ah->analogBank1Data = NULL; | 275 | ATH_FREE_BANK(ah->analogBank1Data); |
| 276 | } | 276 | ATH_FREE_BANK(ah->analogBank2Data); |
| 277 | if (ah->analogBank2Data != NULL) { | 277 | ATH_FREE_BANK(ah->analogBank3Data); |
| 278 | kfree(ah->analogBank2Data); | 278 | ATH_FREE_BANK(ah->analogBank6Data); |
| 279 | ah->analogBank2Data = NULL; | 279 | ATH_FREE_BANK(ah->analogBank6TPCData); |
| 280 | } | 280 | ATH_FREE_BANK(ah->analogBank7Data); |
| 281 | if (ah->analogBank3Data != NULL) { | 281 | ATH_FREE_BANK(ah->addac5416_21); |
| 282 | kfree(ah->analogBank3Data); | 282 | ATH_FREE_BANK(ah->bank6Temp); |
| 283 | ah->analogBank3Data = NULL; | 283 | #undef ATH_FREE_BANK |
| 284 | } | ||
| 285 | if (ah->analogBank6Data != NULL) { | ||
| 286 | kfree(ah->analogBank6Data); | ||
| 287 | ah->analogBank6Data = NULL; | ||
| 288 | } | ||
| 289 | if (ah->analogBank6TPCData != NULL) { | ||
| 290 | kfree(ah->analogBank6TPCData); | ||
| 291 | ah->analogBank6TPCData = NULL; | ||
| 292 | } | ||
| 293 | if (ah->analogBank7Data != NULL) { | ||
| 294 | kfree(ah->analogBank7Data); | ||
| 295 | ah->analogBank7Data = NULL; | ||
| 296 | } | ||
| 297 | if (ah->addac5416_21 != NULL) { | ||
| 298 | kfree(ah->addac5416_21); | ||
| 299 | ah->addac5416_21 = NULL; | ||
| 300 | } | ||
| 301 | if (ah->bank6Temp != NULL) { | ||
| 302 | kfree(ah->bank6Temp); | ||
| 303 | ah->bank6Temp = NULL; | ||
| 304 | } | ||
| 305 | } | 284 | } |
| 306 | 285 | ||
| 307 | bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) | 286 | bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index de4fadadbce5..27bd93c6e74d 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
| @@ -185,6 +185,9 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
| 185 | #define AR_PHY_PLL_CTL_44_2133 0xeb | 185 | #define AR_PHY_PLL_CTL_44_2133 0xeb |
| 186 | #define AR_PHY_PLL_CTL_40_2133 0xea | 186 | #define AR_PHY_PLL_CTL_40_2133 0xea |
| 187 | 187 | ||
| 188 | #define AR_PHY_SPECTRAL_SCAN 0x9912 | ||
| 189 | #define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1 | ||
| 190 | |||
| 188 | #define AR_PHY_RX_DELAY 0x9914 | 191 | #define AR_PHY_RX_DELAY 0x9914 |
| 189 | #define AR_PHY_SEARCH_START_DELAY 0x9918 | 192 | #define AR_PHY_SEARCH_START_DELAY 0x9918 |
| 190 | #define AR_PHY_RX_DELAY_DELAY 0x00003FFF | 193 | #define AR_PHY_RX_DELAY_DELAY 0x00003FFF |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a07efa22551e..16a271787b85 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
| @@ -44,7 +44,7 @@ static const struct ath_rate_table ar5416_11na_ratetable = { | |||
| 44 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | 44 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
| 45 | 29300, 0x0c, 0x00, 108, | 45 | 29300, 0x0c, 0x00, 108, |
| 46 | 4, 7, 7, 7, 7, 0 }, | 46 | 4, 7, 7, 7, 7, 0 }, |
| 47 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 47 | { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
| 48 | 6400, 0x80, 0x00, 0, | 48 | 6400, 0x80, 0x00, 0, |
| 49 | 0, 8, 24, 8, 24, 3216 }, | 49 | 0, 8, 24, 8, 24, 3216 }, |
| 50 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ | 50 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ |
| @@ -463,8 +463,6 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) | |||
| 463 | if (!ignore_cw && WLAN_RC_PHY_HT(phy)) | 463 | if (!ignore_cw && WLAN_RC_PHY_HT(phy)) |
| 464 | if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) | 464 | if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) |
| 465 | return 0; | 465 | return 0; |
| 466 | if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) | ||
| 467 | return 0; | ||
| 468 | return 1; | 466 | return 1; |
| 469 | } | 467 | } |
| 470 | 468 | ||
| @@ -1043,9 +1041,6 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
| 1043 | /* Monotonicity is kept only for rates below the current rate. */ | 1041 | /* Monotonicity is kept only for rates below the current rate. */ |
| 1044 | if (ath_rc_priv->per[tx_rate] < last_per) { | 1042 | if (ath_rc_priv->per[tx_rate] < last_per) { |
| 1045 | for (rate = tx_rate - 1; rate >= 0; rate--) { | 1043 | for (rate = tx_rate - 1; rate >= 0; rate--) { |
| 1046 | if (rate_table->info[rate].phy != | ||
| 1047 | rate_table->info[tx_rate].phy) | ||
| 1048 | break; | ||
| 1049 | 1044 | ||
| 1050 | if (ath_rc_priv->per[rate] > | 1045 | if (ath_rc_priv->per[rate] > |
| 1051 | ath_rc_priv->per[rate+1]) { | 1046 | ath_rc_priv->per[rate+1]) { |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 8302aeb62e5d..13fd658b5d33 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
| @@ -744,6 +744,9 @@ | |||
| 744 | #define AR_SREV_VERSION_9287 0x180 | 744 | #define AR_SREV_VERSION_9287 0x180 |
| 745 | #define AR_SREV_REVISION_9287_10 0 | 745 | #define AR_SREV_REVISION_9287_10 0 |
| 746 | #define AR_SREV_REVISION_9287_11 1 | 746 | #define AR_SREV_REVISION_9287_11 1 |
| 747 | #define AR_SREV_VERSION_9271 0x140 | ||
| 748 | #define AR_SREV_REVISION_9271_10 0 | ||
| 749 | #define AR_SREV_REVISION_9271_11 1 | ||
| 747 | 750 | ||
| 748 | #define AR_SREV_5416(_ah) \ | 751 | #define AR_SREV_5416(_ah) \ |
| 749 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ | 752 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ |
| @@ -815,6 +818,15 @@ | |||
| 815 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | 818 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ |
| 816 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) | 819 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) |
| 817 | 820 | ||
| 821 | #define AR_SREV_9271(_ah) \ | ||
| 822 | (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) | ||
| 823 | #define AR_SREV_9271_10(_ah) \ | ||
| 824 | (AR_SREV_9271(_ah) && \ | ||
| 825 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_10)) | ||
| 826 | #define AR_SREV_9271_11(_ah) \ | ||
| 827 | (AR_SREV_9271(_ah) && \ | ||
| 828 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) | ||
| 829 | |||
| 818 | #define AR_RADIO_SREV_MAJOR 0xf0 | 830 | #define AR_RADIO_SREV_MAJOR 0xf0 |
| 819 | #define AR_RAD5133_SREV_MAJOR 0xc0 | 831 | #define AR_RAD5133_SREV_MAJOR 0xc0 |
| 820 | #define AR_RAD2133_SREV_MAJOR 0xd0 | 832 | #define AR_RAD2133_SREV_MAJOR 0xd0 |
| @@ -1142,12 +1154,32 @@ enum { | |||
| 1142 | #define AR9285_AN_RF2G4_DB2_4 0x00003800 | 1154 | #define AR9285_AN_RF2G4_DB2_4 0x00003800 |
| 1143 | #define AR9285_AN_RF2G4_DB2_4_S 11 | 1155 | #define AR9285_AN_RF2G4_DB2_4_S 11 |
| 1144 | 1156 | ||
| 1157 | /* AR9271 : 0x7828, 0x782c different setting from AR9285 */ | ||
| 1158 | #define AR9271_AN_RF2G3_OB_cck 0x001C0000 | ||
| 1159 | #define AR9271_AN_RF2G3_OB_cck_S 18 | ||
| 1160 | #define AR9271_AN_RF2G3_OB_psk 0x00038000 | ||
| 1161 | #define AR9271_AN_RF2G3_OB_psk_S 15 | ||
| 1162 | #define AR9271_AN_RF2G3_OB_qam 0x00007000 | ||
| 1163 | #define AR9271_AN_RF2G3_OB_qam_S 12 | ||
| 1164 | |||
| 1165 | #define AR9271_AN_RF2G3_DB_1 0x00E00000 | ||
| 1166 | #define AR9271_AN_RF2G3_DB_1_S 21 | ||
| 1167 | |||
| 1168 | #define AR9271_AN_RF2G3_CCOMP 0xFFF | ||
| 1169 | #define AR9271_AN_RF2G3_CCOMP_S 0 | ||
| 1170 | |||
| 1171 | #define AR9271_AN_RF2G4_DB_2 0xE0000000 | ||
| 1172 | #define AR9271_AN_RF2G4_DB_2_S 29 | ||
| 1173 | |||
| 1145 | #define AR9285_AN_RF2G6 0x7834 | 1174 | #define AR9285_AN_RF2G6 0x7834 |
| 1146 | #define AR9285_AN_RF2G6_CCOMP 0x00007800 | 1175 | #define AR9285_AN_RF2G6_CCOMP 0x00007800 |
| 1147 | #define AR9285_AN_RF2G6_CCOMP_S 11 | 1176 | #define AR9285_AN_RF2G6_CCOMP_S 11 |
| 1148 | #define AR9285_AN_RF2G6_OFFS 0x03f00000 | 1177 | #define AR9285_AN_RF2G6_OFFS 0x03f00000 |
| 1149 | #define AR9285_AN_RF2G6_OFFS_S 20 | 1178 | #define AR9285_AN_RF2G6_OFFS_S 20 |
| 1150 | 1179 | ||
| 1180 | #define AR9271_AN_RF2G6_OFFS 0x07f00000 | ||
| 1181 | #define AR9271_AN_RF2G6_OFFS_S 20 | ||
| 1182 | |||
| 1151 | #define AR9285_AN_RF2G7 0x7838 | 1183 | #define AR9285_AN_RF2G7 0x7838 |
| 1152 | #define AR9285_AN_RF2G7_PWDDB 0x00000002 | 1184 | #define AR9285_AN_RF2G7_PWDDB 0x00000002 |
| 1153 | #define AR9285_AN_RF2G7_PWDDB_S 1 | 1185 | #define AR9285_AN_RF2G7_PWDDB_S 1 |
| @@ -1208,6 +1240,11 @@ enum { | |||
| 1208 | #define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000 | 1240 | #define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000 |
| 1209 | #define AR9287_AN_TOP2_XPABIAS_LVL_S 30 | 1241 | #define AR9287_AN_TOP2_XPABIAS_LVL_S 30 |
| 1210 | 1242 | ||
| 1243 | /* AR9271 specific stuff */ | ||
| 1244 | #define AR9271_RESET_POWER_DOWN_CONTROL 0x50044 | ||
| 1245 | #define AR9271_RADIO_RF_RST 0x20 | ||
| 1246 | #define AR9271_GATE_MAC_CTL 0x4000 | ||
| 1247 | |||
| 1211 | #define AR_STA_ID0 0x8000 | 1248 | #define AR_STA_ID0 0x8000 |
| 1212 | #define AR_STA_ID1 0x8004 | 1249 | #define AR_STA_ID1 0x8004 |
| 1213 | #define AR_STA_ID1_SADH_MASK 0x0000FFFF | 1250 | #define AR_STA_ID1_SADH_MASK 0x0000FFFF |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index e1d419e02b4a..19b88f8177fd 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
| @@ -351,7 +351,7 @@ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 351 | * Drop from tasklet to work to allow mutex for channel | 351 | * Drop from tasklet to work to allow mutex for channel |
| 352 | * change. | 352 | * change. |
| 353 | */ | 353 | */ |
| 354 | queue_work(aphy->sc->hw->workqueue, | 354 | ieee80211_queue_work(aphy->sc->hw, |
| 355 | &aphy->sc->chan_work); | 355 | &aphy->sc->chan_work); |
| 356 | } | 356 | } |
| 357 | } | 357 | } |
| @@ -367,7 +367,7 @@ static void ath9k_mark_paused(struct ath_wiphy *aphy) | |||
| 367 | struct ath_softc *sc = aphy->sc; | 367 | struct ath_softc *sc = aphy->sc; |
| 368 | aphy->state = ATH_WIPHY_PAUSED; | 368 | aphy->state = ATH_WIPHY_PAUSED; |
| 369 | if (!__ath9k_wiphy_pausing(sc)) | 369 | if (!__ath9k_wiphy_pausing(sc)) |
| 370 | queue_work(sc->hw->workqueue, &sc->chan_work); | 370 | ieee80211_queue_work(sc->hw, &sc->chan_work); |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | 373 | static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
| @@ -521,7 +521,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy) | |||
| 521 | spin_unlock_bh(&sc->wiphy_lock); | 521 | spin_unlock_bh(&sc->wiphy_lock); |
| 522 | ath_radio_disable(sc); | 522 | ath_radio_disable(sc); |
| 523 | ath_radio_enable(sc); | 523 | ath_radio_enable(sc); |
| 524 | queue_work(aphy->sc->hw->workqueue, | 524 | ieee80211_queue_work(aphy->sc->hw, |
| 525 | &aphy->sc->chan_work); | 525 | &aphy->sc->chan_work); |
| 526 | return -EBUSY; /* previous select still in progress */ | 526 | return -EBUSY; /* previous select still in progress */ |
| 527 | } | 527 | } |
| @@ -541,7 +541,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy) | |||
| 541 | 541 | ||
| 542 | if (now) { | 542 | if (now) { |
| 543 | /* Ready to request channel change immediately */ | 543 | /* Ready to request channel change immediately */ |
| 544 | queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work); | 544 | ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work); |
| 545 | } | 545 | } |
| 546 | 546 | ||
| 547 | /* | 547 | /* |
| @@ -648,8 +648,9 @@ try_again: | |||
| 648 | "change\n"); | 648 | "change\n"); |
| 649 | } | 649 | } |
| 650 | 650 | ||
| 651 | queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, | 651 | ieee80211_queue_delayed_work(sc->hw, |
| 652 | sc->wiphy_scheduler_int); | 652 | &sc->wiphy_work, |
| 653 | sc->wiphy_scheduler_int); | ||
| 653 | } | 654 | } |
| 654 | 655 | ||
| 655 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) | 656 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) |
| @@ -657,8 +658,8 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) | |||
| 657 | cancel_delayed_work_sync(&sc->wiphy_work); | 658 | cancel_delayed_work_sync(&sc->wiphy_work); |
| 658 | sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); | 659 | sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); |
| 659 | if (sc->wiphy_scheduler_int) | 660 | if (sc->wiphy_scheduler_int) |
| 660 | queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, | 661 | ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work, |
| 661 | sc->wiphy_scheduler_int); | 662 | sc->wiphy_scheduler_int); |
| 662 | } | 663 | } |
| 663 | 664 | ||
| 664 | /* caller must hold wiphy_lock */ | 665 | /* caller must hold wiphy_lock */ |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b7806e2ca0e1..87762da0383b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -2063,7 +2063,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work) | |||
| 2063 | ath_reset(sc, false); | 2063 | ath_reset(sc, false); |
| 2064 | } | 2064 | } |
| 2065 | 2065 | ||
| 2066 | queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, | 2066 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, |
| 2067 | msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); | 2067 | msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); |
| 2068 | } | 2068 | } |
| 2069 | 2069 | ||
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 40448067e4cc..b6811cff18ba 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
| @@ -142,6 +142,17 @@ | |||
| 142 | #define B43_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */ | 142 | #define B43_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */ |
| 143 | #define B43_BFL_ALTIQ 0x8000 /* alternate I/Q settings */ | 143 | #define B43_BFL_ALTIQ 0x8000 /* alternate I/Q settings */ |
| 144 | 144 | ||
| 145 | /* SPROM boardflags_hi values */ | ||
| 146 | #define B43_BFH_NOPA 0x0001 /* has no PA */ | ||
| 147 | #define B43_BFH_RSSIINV 0x0002 /* RSSI uses positive slope (not TSSI) */ | ||
| 148 | #define B43_BFH_PAREF 0x0004 /* uses the PARef LDO */ | ||
| 149 | #define B43_BFH_3TSWITCH 0x0008 /* uses a triple throw switch shared | ||
| 150 | * with bluetooth */ | ||
| 151 | #define B43_BFH_PHASESHIFT 0x0010 /* can support phase shifter */ | ||
| 152 | #define B43_BFH_BUCKBOOST 0x0020 /* has buck/booster */ | ||
| 153 | #define B43_BFH_FEM_BT 0x0040 /* has FEM and switch to share antenna | ||
| 154 | * with bluetooth */ | ||
| 155 | |||
| 145 | /* GPIO register offset, in both ChipCommon and PCI core. */ | 156 | /* GPIO register offset, in both ChipCommon and PCI core. */ |
| 146 | #define B43_GPIO_CONTROL 0x6c | 157 | #define B43_GPIO_CONTROL 0x6c |
| 147 | 158 | ||
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 7964cc32b258..41a0e9c2b339 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
| @@ -1334,13 +1334,22 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) | |||
| 1334 | spin_lock_irqsave(&ring->lock, flags); | 1334 | spin_lock_irqsave(&ring->lock, flags); |
| 1335 | 1335 | ||
| 1336 | B43_WARN_ON(!ring->tx); | 1336 | B43_WARN_ON(!ring->tx); |
| 1337 | /* Check if the queue was stopped in mac80211, | ||
| 1338 | * but we got called nevertheless. | ||
| 1339 | * That would be a mac80211 bug. */ | ||
| 1340 | B43_WARN_ON(ring->stopped); | ||
| 1341 | 1337 | ||
| 1342 | if (unlikely(free_slots(ring) < TX_SLOTS_PER_FRAME)) { | 1338 | if (unlikely(ring->stopped)) { |
| 1343 | b43warn(dev->wl, "DMA queue overflow\n"); | 1339 | /* We get here only because of a bug in mac80211. |
| 1340 | * Because of a race, one packet may be queued after | ||
| 1341 | * the queue is stopped, thus we got called when we shouldn't. | ||
| 1342 | * For now, just refuse the transmit. */ | ||
| 1343 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) | ||
| 1344 | b43err(dev->wl, "Packet after queue stopped\n"); | ||
| 1345 | err = -ENOSPC; | ||
| 1346 | goto out_unlock; | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) { | ||
| 1350 | /* If we get here, we have a real error with the queue | ||
| 1351 | * full, but queues not stopped. */ | ||
| 1352 | b43err(dev->wl, "DMA queue overflow\n"); | ||
| 1344 | err = -ENOSPC; | 1353 | err = -ENOSPC; |
| 1345 | goto out_unlock; | 1354 | goto out_unlock; |
| 1346 | } | 1355 | } |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3f4360ad0e4e..925f346ea361 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -395,9 +395,8 @@ u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) | |||
| 395 | /* Unaligned access */ | 395 | /* Unaligned access */ |
| 396 | b43_shm_control_word(dev, routing, offset >> 2); | 396 | b43_shm_control_word(dev, routing, offset >> 2); |
| 397 | ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED); | 397 | ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED); |
| 398 | ret <<= 16; | ||
| 399 | b43_shm_control_word(dev, routing, (offset >> 2) + 1); | 398 | b43_shm_control_word(dev, routing, (offset >> 2) + 1); |
| 400 | ret |= b43_read16(dev, B43_MMIO_SHM_DATA); | 399 | ret |= ((u32)b43_read16(dev, B43_MMIO_SHM_DATA)) << 16; |
| 401 | 400 | ||
| 402 | goto out; | 401 | goto out; |
| 403 | } | 402 | } |
| @@ -464,9 +463,10 @@ void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value | |||
| 464 | /* Unaligned access */ | 463 | /* Unaligned access */ |
| 465 | b43_shm_control_word(dev, routing, offset >> 2); | 464 | b43_shm_control_word(dev, routing, offset >> 2); |
| 466 | b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, | 465 | b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, |
| 467 | (value >> 16) & 0xffff); | 466 | value & 0xFFFF); |
| 468 | b43_shm_control_word(dev, routing, (offset >> 2) + 1); | 467 | b43_shm_control_word(dev, routing, (offset >> 2) + 1); |
| 469 | b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff); | 468 | b43_write16(dev, B43_MMIO_SHM_DATA, |
| 469 | (value >> 16) & 0xFFFF); | ||
| 470 | return; | 470 | return; |
| 471 | } | 471 | } |
| 472 | offset >>= 2; | 472 | offset >>= 2; |
| @@ -1524,10 +1524,13 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev, | |||
| 1524 | /* Looks like PLCP headers plus packet timings are stored for | 1524 | /* Looks like PLCP headers plus packet timings are stored for |
| 1525 | * all possible basic rates | 1525 | * all possible basic rates |
| 1526 | */ | 1526 | */ |
| 1527 | /* FIXME this is the wrong offset : it goes in tkip rx phase1 shm */ | ||
| 1528 | #if 0 | ||
| 1527 | b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]); | 1529 | b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]); |
| 1528 | b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]); | 1530 | b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]); |
| 1529 | b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]); | 1531 | b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]); |
| 1530 | b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]); | 1532 | b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]); |
| 1533 | #endif | ||
| 1531 | 1534 | ||
| 1532 | size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6)); | 1535 | size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6)); |
| 1533 | b43_write_template_common(dev, probe_resp_data, | 1536 | b43_write_template_common(dev, probe_resp_data, |
| @@ -1654,7 +1657,7 @@ static void b43_update_templates(struct b43_wl *wl) | |||
| 1654 | wl->current_beacon = beacon; | 1657 | wl->current_beacon = beacon; |
| 1655 | wl->beacon0_uploaded = 0; | 1658 | wl->beacon0_uploaded = 0; |
| 1656 | wl->beacon1_uploaded = 0; | 1659 | wl->beacon1_uploaded = 0; |
| 1657 | queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); | 1660 | ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); |
| 1658 | } | 1661 | } |
| 1659 | 1662 | ||
| 1660 | static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) | 1663 | static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) |
| @@ -2914,7 +2917,7 @@ out_requeue: | |||
| 2914 | delay = msecs_to_jiffies(50); | 2917 | delay = msecs_to_jiffies(50); |
| 2915 | else | 2918 | else |
| 2916 | delay = round_jiffies_relative(HZ * 15); | 2919 | delay = round_jiffies_relative(HZ * 15); |
| 2917 | queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay); | 2920 | ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay); |
| 2918 | out: | 2921 | out: |
| 2919 | mutex_unlock(&wl->mutex); | 2922 | mutex_unlock(&wl->mutex); |
| 2920 | } | 2923 | } |
| @@ -2925,15 +2928,16 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev) | |||
| 2925 | 2928 | ||
| 2926 | dev->periodic_state = 0; | 2929 | dev->periodic_state = 0; |
| 2927 | INIT_DELAYED_WORK(work, b43_periodic_work_handler); | 2930 | INIT_DELAYED_WORK(work, b43_periodic_work_handler); |
| 2928 | queue_delayed_work(dev->wl->hw->workqueue, work, 0); | 2931 | ieee80211_queue_delayed_work(dev->wl->hw, work, 0); |
| 2929 | } | 2932 | } |
| 2930 | 2933 | ||
| 2931 | /* Check if communication with the device works correctly. */ | 2934 | /* Check if communication with the device works correctly. */ |
| 2932 | static int b43_validate_chipaccess(struct b43_wldev *dev) | 2935 | static int b43_validate_chipaccess(struct b43_wldev *dev) |
| 2933 | { | 2936 | { |
| 2934 | u32 v, backup; | 2937 | u32 v, backup0, backup4; |
| 2935 | 2938 | ||
| 2936 | backup = b43_shm_read32(dev, B43_SHM_SHARED, 0); | 2939 | backup0 = b43_shm_read32(dev, B43_SHM_SHARED, 0); |
| 2940 | backup4 = b43_shm_read32(dev, B43_SHM_SHARED, 4); | ||
| 2937 | 2941 | ||
| 2938 | /* Check for read/write and endianness problems. */ | 2942 | /* Check for read/write and endianness problems. */ |
| 2939 | b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55); | 2943 | b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55); |
| @@ -2943,7 +2947,23 @@ static int b43_validate_chipaccess(struct b43_wldev *dev) | |||
| 2943 | if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA) | 2947 | if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA) |
| 2944 | goto error; | 2948 | goto error; |
| 2945 | 2949 | ||
| 2946 | b43_shm_write32(dev, B43_SHM_SHARED, 0, backup); | 2950 | /* Check if unaligned 32bit SHM_SHARED access works properly. |
| 2951 | * However, don't bail out on failure, because it's noncritical. */ | ||
| 2952 | b43_shm_write16(dev, B43_SHM_SHARED, 0, 0x1122); | ||
| 2953 | b43_shm_write16(dev, B43_SHM_SHARED, 2, 0x3344); | ||
| 2954 | b43_shm_write16(dev, B43_SHM_SHARED, 4, 0x5566); | ||
| 2955 | b43_shm_write16(dev, B43_SHM_SHARED, 6, 0x7788); | ||
| 2956 | if (b43_shm_read32(dev, B43_SHM_SHARED, 2) != 0x55663344) | ||
| 2957 | b43warn(dev->wl, "Unaligned 32bit SHM read access is broken\n"); | ||
| 2958 | b43_shm_write32(dev, B43_SHM_SHARED, 2, 0xAABBCCDD); | ||
| 2959 | if (b43_shm_read16(dev, B43_SHM_SHARED, 0) != 0x1122 || | ||
| 2960 | b43_shm_read16(dev, B43_SHM_SHARED, 2) != 0xCCDD || | ||
| 2961 | b43_shm_read16(dev, B43_SHM_SHARED, 4) != 0xAABB || | ||
| 2962 | b43_shm_read16(dev, B43_SHM_SHARED, 6) != 0x7788) | ||
| 2963 | b43warn(dev->wl, "Unaligned 32bit SHM write access is broken\n"); | ||
| 2964 | |||
| 2965 | b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0); | ||
| 2966 | b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4); | ||
| 2947 | 2967 | ||
| 2948 | if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) { | 2968 | if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) { |
| 2949 | /* The 32bit register shadows the two 16bit registers | 2969 | /* The 32bit register shadows the two 16bit registers |
| @@ -4871,7 +4891,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason) | |||
| 4871 | if (b43_status(dev) < B43_STAT_INITIALIZED) | 4891 | if (b43_status(dev) < B43_STAT_INITIALIZED) |
| 4872 | return; | 4892 | return; |
| 4873 | b43info(dev->wl, "Controller RESET (%s) ...\n", reason); | 4893 | b43info(dev->wl, "Controller RESET (%s) ...\n", reason); |
| 4874 | queue_work(dev->wl->hw->workqueue, &dev->restart_work); | 4894 | ieee80211_queue_work(dev->wl->hw, &dev->restart_work); |
| 4875 | } | 4895 | } |
| 4876 | 4896 | ||
| 4877 | #ifdef CONFIG_PM | 4897 | #ifdef CONFIG_PM |
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 6d241622210e..51686ec96984 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c | |||
| @@ -240,6 +240,13 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) | |||
| 240 | dev->phy.ops->phy_write(dev, reg, value); | 240 | dev->phy.ops->phy_write(dev, reg, value); |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg) | ||
| 244 | { | ||
| 245 | assert_mac_suspended(dev); | ||
| 246 | dev->phy.ops->phy_write(dev, destreg, | ||
| 247 | dev->phy.ops->phy_read(dev, srcreg)); | ||
| 248 | } | ||
| 249 | |||
| 243 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) | 250 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) |
| 244 | { | 251 | { |
| 245 | b43_phy_write(dev, offset, | 252 | b43_phy_write(dev, offset, |
| @@ -352,7 +359,7 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) | |||
| 352 | 359 | ||
| 353 | /* We must adjust the transmission power in hardware. | 360 | /* We must adjust the transmission power in hardware. |
| 354 | * Schedule b43_phy_txpower_adjust_work(). */ | 361 | * Schedule b43_phy_txpower_adjust_work(). */ |
| 355 | queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work); | 362 | ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work); |
| 356 | } | 363 | } |
| 357 | 364 | ||
| 358 | int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset) | 365 | int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset) |
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 44cc918e4fc6..9f9f23cab72a 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h | |||
| @@ -291,6 +291,11 @@ u16 b43_phy_read(struct b43_wldev *dev, u16 reg); | |||
| 291 | void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value); | 291 | void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value); |
| 292 | 292 | ||
| 293 | /** | 293 | /** |
| 294 | * b43_phy_copy - copy contents of 16bit PHY register to another | ||
| 295 | */ | ||
| 296 | void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg); | ||
| 297 | |||
| 298 | /** | ||
| 294 | * b43_phy_mask - Mask a PHY register with a mask | 299 | * b43_phy_mask - Mask a PHY register with a mask |
| 295 | */ | 300 | */ |
| 296 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask); | 301 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask); |
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index ea0d3a3a6a64..aa1486a1354b 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
| @@ -66,7 +66,99 @@ static void lpphy_table_init(struct b43_wldev *dev) | |||
| 66 | 66 | ||
| 67 | static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) | 67 | static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) |
| 68 | { | 68 | { |
| 69 | B43_WARN_ON(1);//TODO rev < 2 not supported, yet. | 69 | struct ssb_bus *bus = dev->dev->bus; |
| 70 | u16 tmp, tmp2; | ||
| 71 | |||
| 72 | if (dev->phy.rev == 1 && | ||
| 73 | (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) { | ||
| 74 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A); | ||
| 75 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900); | ||
| 76 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A); | ||
| 77 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00); | ||
| 78 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x000A); | ||
| 79 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0400); | ||
| 80 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x000A); | ||
| 81 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0B00); | ||
| 82 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xFFC0, 0x000A); | ||
| 83 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xC0FF, 0x0900); | ||
| 84 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xFFC0, 0x000A); | ||
| 85 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xC0FF, 0x0B00); | ||
| 86 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xFFC0, 0x000A); | ||
| 87 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xC0FF, 0x0900); | ||
| 88 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A); | ||
| 89 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00); | ||
| 90 | } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ || | ||
| 91 | (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) && | ||
| 92 | (bus->sprom.boardflags_lo & B43_BFL_FEM))) { | ||
| 93 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001); | ||
| 94 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400); | ||
| 95 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001); | ||
| 96 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0500); | ||
| 97 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002); | ||
| 98 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0800); | ||
| 99 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002); | ||
| 100 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00); | ||
| 101 | } else if (dev->phy.rev == 1 || | ||
| 102 | (bus->sprom.boardflags_lo & B43_BFL_FEM)) { | ||
| 103 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004); | ||
| 104 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800); | ||
| 105 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004); | ||
| 106 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0C00); | ||
| 107 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002); | ||
| 108 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0100); | ||
| 109 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002); | ||
| 110 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0300); | ||
| 111 | } else { | ||
| 112 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A); | ||
| 113 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0900); | ||
| 114 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A); | ||
| 115 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00); | ||
| 116 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0006); | ||
| 117 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0500); | ||
| 118 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006); | ||
| 119 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700); | ||
| 120 | } | ||
| 121 | if (dev->phy.rev == 1) { | ||
| 122 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1); | ||
| 123 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2); | ||
| 124 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3); | ||
| 125 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4); | ||
| 126 | } | ||
| 127 | if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) && | ||
| 128 | (bus->chip_id == 0x5354) && | ||
| 129 | (bus->chip_package == SSB_CHIPPACK_BCM4712S)) { | ||
| 130 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006); | ||
| 131 | b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005); | ||
| 132 | b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); | ||
| 133 | b43_hf_write(dev, b43_hf_read(dev) | 0x0800ULL << 32); | ||
| 134 | } | ||
| 135 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
| 136 | b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000); | ||
| 137 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0040); | ||
| 138 | b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0xA400); | ||
| 139 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0x0B00); | ||
| 140 | b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x0007); | ||
| 141 | b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFF8, 0x0003); | ||
| 142 | b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFC7, 0x0020); | ||
| 143 | b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF); | ||
| 144 | } else { /* 5GHz */ | ||
| 145 | b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0x7FFF); | ||
| 146 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFBF); | ||
| 147 | } | ||
| 148 | if (dev->phy.rev == 1) { | ||
| 149 | tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH); | ||
| 150 | tmp2 = (tmp & 0x03E0) >> 5; | ||
| 151 | tmp2 |= tmp << 5; | ||
| 152 | b43_phy_write(dev, B43_LPPHY_4C3, tmp2); | ||
| 153 | tmp = b43_phy_read(dev, B43_LPPHY_OFDMSYNCTHRESH0); | ||
| 154 | tmp2 = (tmp & 0x1F00) >> 8; | ||
| 155 | tmp2 |= tmp << 5; | ||
| 156 | b43_phy_write(dev, B43_LPPHY_4C4, tmp2); | ||
| 157 | tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB); | ||
| 158 | tmp2 = tmp & 0x00FF; | ||
| 159 | tmp2 |= tmp << 8; | ||
| 160 | b43_phy_write(dev, B43_LPPHY_4C5, tmp2); | ||
| 161 | } | ||
| 70 | } | 162 | } |
| 71 | 163 | ||
| 72 | static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | 164 | static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) |
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index 18370b4ac38e..829b2bba3ee1 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h | |||
| @@ -273,12 +273,19 @@ | |||
| 273 | #define B43_LPPHY_AFE_DDFS_POINTER_INIT B43_PHY_OFDM(0xB8) /* AFE DDFS pointer init */ | 273 | #define B43_LPPHY_AFE_DDFS_POINTER_INIT B43_PHY_OFDM(0xB8) /* AFE DDFS pointer init */ |
| 274 | #define B43_LPPHY_AFE_DDFS_INCR_INIT B43_PHY_OFDM(0xB9) /* AFE DDFS incr init */ | 274 | #define B43_LPPHY_AFE_DDFS_INCR_INIT B43_PHY_OFDM(0xB9) /* AFE DDFS incr init */ |
| 275 | #define B43_LPPHY_MRCNOISEREDUCTION B43_PHY_OFDM(0xBA) /* mrcNoiseReduction */ | 275 | #define B43_LPPHY_MRCNOISEREDUCTION B43_PHY_OFDM(0xBA) /* mrcNoiseReduction */ |
| 276 | #define B43_LPPHY_TRLOOKUP3 B43_PHY_OFDM(0xBB) /* TRLookup3 */ | 276 | #define B43_LPPHY_TR_LOOKUP_3 B43_PHY_OFDM(0xBB) /* TR Lookup 3 */ |
| 277 | #define B43_LPPHY_TRLOOKUP4 B43_PHY_OFDM(0xBC) /* TRLookup4 */ | 277 | #define B43_LPPHY_TR_LOOKUP_4 B43_PHY_OFDM(0xBC) /* TR Lookup 4 */ |
| 278 | #define B43_LPPHY_RADAR_FIFO_STAT B43_PHY_OFDM(0xBD) /* Radar FIFO Status */ | 278 | #define B43_LPPHY_RADAR_FIFO_STAT B43_PHY_OFDM(0xBD) /* Radar FIFO Status */ |
| 279 | #define B43_LPPHY_GPIO_OUTEN B43_PHY_OFDM(0xBE) /* GPIO Out enable */ | 279 | #define B43_LPPHY_GPIO_OUTEN B43_PHY_OFDM(0xBE) /* GPIO Out enable */ |
| 280 | #define B43_LPPHY_GPIO_SELECT B43_PHY_OFDM(0xBF) /* GPIO Select */ | 280 | #define B43_LPPHY_GPIO_SELECT B43_PHY_OFDM(0xBF) /* GPIO Select */ |
| 281 | #define B43_LPPHY_GPIO_OUT B43_PHY_OFDM(0xC0) /* GPIO Out */ | 281 | #define B43_LPPHY_GPIO_OUT B43_PHY_OFDM(0xC0) /* GPIO Out */ |
| 282 | #define B43_LPPHY_4C3 B43_PHY_OFDM(0xC3) /* unknown, used during BB init */ | ||
| 283 | #define B43_LPPHY_4C4 B43_PHY_OFDM(0xC4) /* unknown, used during BB init */ | ||
| 284 | #define B43_LPPHY_4C5 B43_PHY_OFDM(0xC5) /* unknown, used during BB init */ | ||
| 285 | #define B43_LPPHY_TR_LOOKUP_5 B43_PHY_OFDM(0xC7) /* TR Lookup 5 */ | ||
| 286 | #define B43_LPPHY_TR_LOOKUP_6 B43_PHY_OFDM(0xC8) /* TR Lookup 6 */ | ||
| 287 | #define B43_LPPHY_TR_LOOKUP_7 B43_PHY_OFDM(0xC9) /* TR Lookup 7 */ | ||
| 288 | #define B43_LPPHY_TR_LOOKUP_8 B43_PHY_OFDM(0xCA) /* TR Lookup 8 */ | ||
| 282 | 289 | ||
| 283 | 290 | ||
| 284 | 291 | ||
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index be7b5604947b..992318a78077 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
| @@ -137,7 +137,8 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) | |||
| 137 | 137 | ||
| 138 | b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); | 138 | b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); |
| 139 | msleep(1); | 139 | msleep(1); |
| 140 | if ((sprom->revision != 4) || !(sprom->boardflags_hi & 0x0002)) { | 140 | if ((sprom->revision != 4) || |
| 141 | !(sprom->boardflags_hi & B43_BFH_RSSIINV)) { | ||
| 141 | if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || | 142 | if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || |
| 142 | (binfo->type != 0x46D) || | 143 | (binfo->type != 0x46D) || |
| 143 | (binfo->rev < 0x41)) { | 144 | (binfo->rev < 0x41)) { |
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 69138e8c1db6..73c047d8de40 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c | |||
| @@ -783,7 +783,7 @@ void b43_pio_rx(struct b43_pio_rxqueue *q) | |||
| 783 | { | 783 | { |
| 784 | /* Due to latency issues we must run the RX path in | 784 | /* Due to latency issues we must run the RX path in |
| 785 | * a workqueue to be able to schedule between packets. */ | 785 | * a workqueue to be able to schedule between packets. */ |
| 786 | queue_work(q->dev->wl->hw->workqueue, &q->rx_work); | 786 | ieee80211_queue_work(q->dev->wl->hw, &q->rx_work); |
| 787 | } | 787 | } |
| 788 | 788 | ||
| 789 | static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q) | 789 | static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q) |
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 2f90fb9f5367..866403415811 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
| @@ -1366,15 +1366,25 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, | |||
| 1366 | ring = priority_to_txring(dev, skb_get_queue_mapping(skb)); | 1366 | ring = priority_to_txring(dev, skb_get_queue_mapping(skb)); |
| 1367 | spin_lock_irqsave(&ring->lock, flags); | 1367 | spin_lock_irqsave(&ring->lock, flags); |
| 1368 | B43legacy_WARN_ON(!ring->tx); | 1368 | B43legacy_WARN_ON(!ring->tx); |
| 1369 | if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) { | 1369 | |
| 1370 | b43legacywarn(dev->wl, "DMA queue overflow\n"); | 1370 | if (unlikely(ring->stopped)) { |
| 1371 | /* We get here only because of a bug in mac80211. | ||
| 1372 | * Because of a race, one packet may be queued after | ||
| 1373 | * the queue is stopped, thus we got called when we shouldn't. | ||
| 1374 | * For now, just refuse the transmit. */ | ||
| 1375 | if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) | ||
| 1376 | b43legacyerr(dev->wl, "Packet after queue stopped\n"); | ||
| 1377 | err = -ENOSPC; | ||
| 1378 | goto out_unlock; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | if (unlikely(WARN_ON(free_slots(ring) < SLOTS_PER_PACKET))) { | ||
| 1382 | /* If we get here, we have a real error with the queue | ||
| 1383 | * full, but queues not stopped. */ | ||
| 1384 | b43legacyerr(dev->wl, "DMA queue overflow\n"); | ||
| 1371 | err = -ENOSPC; | 1385 | err = -ENOSPC; |
| 1372 | goto out_unlock; | 1386 | goto out_unlock; |
| 1373 | } | 1387 | } |
| 1374 | /* Check if the queue was stopped in mac80211, | ||
| 1375 | * but we got called nevertheless. | ||
| 1376 | * That would be a mac80211 bug. */ | ||
| 1377 | B43legacy_BUG_ON(ring->stopped); | ||
| 1378 | 1388 | ||
| 1379 | err = dma_tx_fragment(ring, skb); | 1389 | err = dma_tx_fragment(ring, skb); |
| 1380 | if (unlikely(err == -ENOKEY)) { | 1390 | if (unlikely(err == -ENOKEY)) { |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c4973c1942bf..b1435594921a 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
| @@ -1252,7 +1252,7 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl) | |||
| 1252 | wl->current_beacon = beacon; | 1252 | wl->current_beacon = beacon; |
| 1253 | wl->beacon0_uploaded = 0; | 1253 | wl->beacon0_uploaded = 0; |
| 1254 | wl->beacon1_uploaded = 0; | 1254 | wl->beacon1_uploaded = 0; |
| 1255 | queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); | 1255 | ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); |
| 1256 | } | 1256 | } |
| 1257 | 1257 | ||
| 1258 | static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev, | 1258 | static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev, |
| @@ -2300,7 +2300,7 @@ out_requeue: | |||
| 2300 | delay = msecs_to_jiffies(50); | 2300 | delay = msecs_to_jiffies(50); |
| 2301 | else | 2301 | else |
| 2302 | delay = round_jiffies_relative(HZ * 15); | 2302 | delay = round_jiffies_relative(HZ * 15); |
| 2303 | queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay); | 2303 | ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay); |
| 2304 | out: | 2304 | out: |
| 2305 | mutex_unlock(&wl->mutex); | 2305 | mutex_unlock(&wl->mutex); |
| 2306 | } | 2306 | } |
| @@ -2311,7 +2311,7 @@ static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev) | |||
| 2311 | 2311 | ||
| 2312 | dev->periodic_state = 0; | 2312 | dev->periodic_state = 0; |
| 2313 | INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler); | 2313 | INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler); |
| 2314 | queue_delayed_work(dev->wl->hw->workqueue, work, 0); | 2314 | ieee80211_queue_delayed_work(dev->wl->hw, work, 0); |
| 2315 | } | 2315 | } |
| 2316 | 2316 | ||
| 2317 | /* Validate access to the chip (SHM) */ | 2317 | /* Validate access to the chip (SHM) */ |
| @@ -3885,7 +3885,7 @@ void b43legacy_controller_restart(struct b43legacy_wldev *dev, | |||
| 3885 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) | 3885 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) |
| 3886 | return; | 3886 | return; |
| 3887 | b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason); | 3887 | b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason); |
| 3888 | queue_work(dev->wl->hw->workqueue, &dev->restart_work); | 3888 | ieee80211_queue_work(dev->wl->hw, &dev->restart_work); |
| 3889 | } | 3889 | } |
| 3890 | 3890 | ||
| 3891 | #ifdef CONFIG_PM | 3891 | #ifdef CONFIG_PM |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5f7c52053c18..cf3fbc6b98ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
| @@ -73,6 +73,18 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | |||
| 73 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | 73 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | /* NIC configuration for 1000 series */ | ||
| 77 | static void iwl1000_nic_config(struct iwl_priv *priv) | ||
| 78 | { | ||
| 79 | iwl5000_nic_config(priv); | ||
| 80 | |||
| 81 | /* Setting digital SVR for 1000 card to 1.32V */ | ||
| 82 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | ||
| 83 | iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, | ||
| 84 | APMG_SVR_DIGITAL_VOLTAGE_1_32, | ||
| 85 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); | ||
| 86 | } | ||
| 87 | |||
| 76 | static struct iwl_lib_ops iwl1000_lib = { | 88 | static struct iwl_lib_ops iwl1000_lib = { |
| 77 | .set_hw_params = iwl5000_hw_set_hw_params, | 89 | .set_hw_params = iwl5000_hw_set_hw_params, |
| 78 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 90 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
| @@ -95,7 +107,7 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
| 95 | .init = iwl5000_apm_init, | 107 | .init = iwl5000_apm_init, |
| 96 | .reset = iwl5000_apm_reset, | 108 | .reset = iwl5000_apm_reset, |
| 97 | .stop = iwl5000_apm_stop, | 109 | .stop = iwl5000_apm_stop, |
| 98 | .config = iwl5000_nic_config, | 110 | .config = iwl1000_nic_config, |
| 99 | .set_pwr_src = iwl_set_pwr_src, | 111 | .set_pwr_src = iwl_set_pwr_src, |
| 100 | }, | 112 | }, |
| 101 | .eeprom_ops = { | 113 | .eeprom_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ddd64fef3039..87957c052839 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
| @@ -198,6 +198,7 @@ out: | |||
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | 200 | ||
| 201 | /* NIC configuration for 5000 series and up */ | ||
| 201 | void iwl5000_nic_config(struct iwl_priv *priv) | 202 | void iwl5000_nic_config(struct iwl_priv *priv) |
| 202 | { | 203 | { |
| 203 | unsigned long flags; | 204 | unsigned long flags; |
| @@ -239,18 +240,11 @@ void iwl5000_nic_config(struct iwl_priv *priv) | |||
| 239 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, | 240 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, |
| 240 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); | 241 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); |
| 241 | 242 | ||
| 242 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_1000) { | ||
| 243 | /* Setting digital SVR for 1000 card to 1.32V */ | ||
| 244 | iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, | ||
| 245 | APMG_SVR_DIGITAL_VOLTAGE_1_32, | ||
| 246 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); | ||
| 247 | } | ||
| 248 | 243 | ||
| 249 | spin_unlock_irqrestore(&priv->lock, flags); | 244 | spin_unlock_irqrestore(&priv->lock, flags); |
| 250 | } | 245 | } |
| 251 | 246 | ||
| 252 | 247 | ||
| 253 | |||
| 254 | /* | 248 | /* |
| 255 | * EEPROM | 249 | * EEPROM |
| 256 | */ | 250 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 59ff73536f3a..4450943d3dac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
| @@ -68,6 +68,24 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
| 68 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | 68 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | /* NIC configuration for 6000 series */ | ||
| 72 | static void iwl6000_nic_config(struct iwl_priv *priv) | ||
| 73 | { | ||
| 74 | iwl5000_nic_config(priv); | ||
| 75 | |||
| 76 | /* no locking required for register write */ | ||
| 77 | if (priv->cfg->pa_type == IWL_PA_HYBRID) { | ||
| 78 | /* 2x2 hybrid phy type */ | ||
| 79 | iwl_write32(priv, CSR_GP_DRIVER_REG, | ||
| 80 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB); | ||
| 81 | } else if (priv->cfg->pa_type == IWL_PA_INTERNAL) { | ||
| 82 | /* 2x2 IPA phy type */ | ||
| 83 | iwl_write32(priv, CSR_GP_DRIVER_REG, | ||
| 84 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | ||
| 85 | } | ||
| 86 | /* else do nothing, uCode configured */ | ||
| 87 | } | ||
| 88 | |||
| 71 | static struct iwl_lib_ops iwl6000_lib = { | 89 | static struct iwl_lib_ops iwl6000_lib = { |
| 72 | .set_hw_params = iwl5000_hw_set_hw_params, | 90 | .set_hw_params = iwl5000_hw_set_hw_params, |
| 73 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 91 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
| @@ -90,7 +108,7 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
| 90 | .init = iwl5000_apm_init, | 108 | .init = iwl5000_apm_init, |
| 91 | .reset = iwl5000_apm_reset, | 109 | .reset = iwl5000_apm_reset, |
| 92 | .stop = iwl5000_apm_stop, | 110 | .stop = iwl5000_apm_stop, |
| 93 | .config = iwl5000_nic_config, | 111 | .config = iwl6000_nic_config, |
| 94 | .set_pwr_src = iwl_set_pwr_src, | 112 | .set_pwr_src = iwl_set_pwr_src, |
| 95 | }, | 113 | }, |
| 96 | .eeprom_ops = { | 114 | .eeprom_ops = { |
| @@ -132,23 +150,31 @@ static struct iwl_ops iwl6000_ops = { | |||
| 132 | .utils = &iwl6000_hcmd_utils, | 150 | .utils = &iwl6000_hcmd_utils, |
| 133 | }; | 151 | }; |
| 134 | 152 | ||
| 135 | struct iwl_cfg iwl6000_2ag_cfg = { | 153 | |
| 136 | .name = "6000 Series 2x2 AG", | 154 | /* |
| 155 | * "h": Hybrid configuration, use both internal and external Power Amplifier | ||
| 156 | */ | ||
| 157 | struct iwl_cfg iwl6000h_2agn_cfg = { | ||
| 158 | .name = "6000 Series 2x2 AGN", | ||
| 137 | .fw_name_pre = IWL6000_FW_PRE, | 159 | .fw_name_pre = IWL6000_FW_PRE, |
| 138 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 160 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
| 139 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 161 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
| 140 | .sku = IWL_SKU_A|IWL_SKU_G, | 162 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
| 141 | .ops = &iwl6000_ops, | 163 | .ops = &iwl6000_ops, |
| 142 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 164 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
| 143 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 165 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
| 144 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 166 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
| 145 | .mod_params = &iwl50_mod_params, | 167 | .mod_params = &iwl50_mod_params, |
| 146 | .valid_tx_ant = ANT_BC, | 168 | .valid_tx_ant = ANT_AB, |
| 147 | .valid_rx_ant = ANT_BC, | 169 | .valid_rx_ant = ANT_AB, |
| 148 | .need_pll_cfg = false, | 170 | .need_pll_cfg = false, |
| 171 | .pa_type = IWL_PA_HYBRID, | ||
| 149 | }; | 172 | }; |
| 150 | 173 | ||
| 151 | struct iwl_cfg iwl6000_2agn_cfg = { | 174 | /* |
| 175 | * "i": Internal configuration, use internal Power Amplifier | ||
| 176 | */ | ||
| 177 | struct iwl_cfg iwl6000i_2agn_cfg = { | ||
| 152 | .name = "6000 Series 2x2 AGN", | 178 | .name = "6000 Series 2x2 AGN", |
| 153 | .fw_name_pre = IWL6000_FW_PRE, | 179 | .fw_name_pre = IWL6000_FW_PRE, |
| 154 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 180 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
| @@ -159,9 +185,10 @@ struct iwl_cfg iwl6000_2agn_cfg = { | |||
| 159 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 185 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
| 160 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 186 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
| 161 | .mod_params = &iwl50_mod_params, | 187 | .mod_params = &iwl50_mod_params, |
| 162 | .valid_tx_ant = ANT_AB, | 188 | .valid_tx_ant = ANT_BC, |
| 163 | .valid_rx_ant = ANT_AB, | 189 | .valid_rx_ant = ANT_BC, |
| 164 | .need_pll_cfg = false, | 190 | .need_pll_cfg = false, |
| 191 | .pa_type = IWL_PA_INTERNAL, | ||
| 165 | }; | 192 | }; |
| 166 | 193 | ||
| 167 | struct iwl_cfg iwl6050_2agn_cfg = { | 194 | struct iwl_cfg iwl6050_2agn_cfg = { |
| @@ -178,6 +205,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
| 178 | .valid_tx_ant = ANT_AB, | 205 | .valid_tx_ant = ANT_AB, |
| 179 | .valid_rx_ant = ANT_AB, | 206 | .valid_rx_ant = ANT_AB, |
| 180 | .need_pll_cfg = false, | 207 | .need_pll_cfg = false, |
| 208 | .pa_type = IWL_PA_SYSTEM, | ||
| 181 | }; | 209 | }; |
| 182 | 210 | ||
| 183 | struct iwl_cfg iwl6000_3agn_cfg = { | 211 | struct iwl_cfg iwl6000_3agn_cfg = { |
| @@ -194,6 +222,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
| 194 | .valid_tx_ant = ANT_ABC, | 222 | .valid_tx_ant = ANT_ABC, |
| 195 | .valid_rx_ant = ANT_ABC, | 223 | .valid_rx_ant = ANT_ABC, |
| 196 | .need_pll_cfg = false, | 224 | .need_pll_cfg = false, |
| 225 | .pa_type = IWL_PA_SYSTEM, | ||
| 197 | }; | 226 | }; |
| 198 | 227 | ||
| 199 | struct iwl_cfg iwl6050_3agn_cfg = { | 228 | struct iwl_cfg iwl6050_3agn_cfg = { |
| @@ -210,6 +239,7 @@ struct iwl_cfg iwl6050_3agn_cfg = { | |||
| 210 | .valid_tx_ant = ANT_ABC, | 239 | .valid_tx_ant = ANT_ABC, |
| 211 | .valid_rx_ant = ANT_ABC, | 240 | .valid_rx_ant = ANT_ABC, |
| 212 | .need_pll_cfg = false, | 241 | .need_pll_cfg = false, |
| 242 | .pa_type = IWL_PA_SYSTEM, | ||
| 213 | }; | 243 | }; |
| 214 | 244 | ||
| 215 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 245 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4cb1a1b73483..db580cbf5982 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
| @@ -1291,6 +1291,7 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
| 1291 | size_t len; | 1291 | size_t len; |
| 1292 | u32 api_ver, build; | 1292 | u32 api_ver, build; |
| 1293 | u32 inst_size, data_size, init_size, init_data_size, boot_size; | 1293 | u32 inst_size, data_size, init_size, init_data_size, boot_size; |
| 1294 | u16 eeprom_ver; | ||
| 1294 | 1295 | ||
| 1295 | /* Ask kernel firmware_class module to get the boot firmware off disk. | 1296 | /* Ask kernel firmware_class module to get the boot firmware off disk. |
| 1296 | * request_firmware() is synchronous, file is in memory on return. */ | 1297 | * request_firmware() is synchronous, file is in memory on return. */ |
| @@ -1368,6 +1369,11 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
| 1368 | if (build) | 1369 | if (build) |
| 1369 | IWL_DEBUG_INFO(priv, "Build %u\n", build); | 1370 | IWL_DEBUG_INFO(priv, "Build %u\n", build); |
| 1370 | 1371 | ||
| 1372 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
| 1373 | IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", | ||
| 1374 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
| 1375 | ? "OTP" : "EEPROM", eeprom_ver); | ||
| 1376 | |||
| 1371 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | 1377 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", |
| 1372 | priv->ucode_ver); | 1378 | priv->ucode_ver); |
| 1373 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", | 1379 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", |
| @@ -2483,39 +2489,6 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, | |||
| 2483 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 2489 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
| 2484 | 2490 | ||
| 2485 | 2491 | ||
| 2486 | static ssize_t show_version(struct device *d, | ||
| 2487 | struct device_attribute *attr, char *buf) | ||
| 2488 | { | ||
| 2489 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
| 2490 | struct iwl_alive_resp *palive = &priv->card_alive; | ||
| 2491 | ssize_t pos = 0; | ||
| 2492 | u16 eeprom_ver; | ||
| 2493 | |||
| 2494 | if (palive->is_valid) | ||
| 2495 | pos += sprintf(buf + pos, | ||
| 2496 | "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n" | ||
| 2497 | "fw type: 0x%01X 0x%01X\n", | ||
| 2498 | palive->ucode_major, palive->ucode_minor, | ||
| 2499 | palive->sw_rev[0], palive->sw_rev[1], | ||
| 2500 | palive->ver_type, palive->ver_subtype); | ||
| 2501 | else | ||
| 2502 | pos += sprintf(buf + pos, "fw not loaded\n"); | ||
| 2503 | |||
| 2504 | if (priv->eeprom) { | ||
| 2505 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
| 2506 | pos += sprintf(buf + pos, "NVM Type: %s, version: 0x%x\n", | ||
| 2507 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
| 2508 | ? "OTP" : "EEPROM", eeprom_ver); | ||
| 2509 | |||
| 2510 | } else { | ||
| 2511 | pos += sprintf(buf + pos, "EEPROM not initialzed\n"); | ||
| 2512 | } | ||
| 2513 | |||
| 2514 | return pos; | ||
| 2515 | } | ||
| 2516 | |||
| 2517 | static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL); | ||
| 2518 | |||
| 2519 | static ssize_t show_temperature(struct device *d, | 2492 | static ssize_t show_temperature(struct device *d, |
| 2520 | struct device_attribute *attr, char *buf) | 2493 | struct device_attribute *attr, char *buf) |
| 2521 | { | 2494 | { |
| @@ -2779,7 +2752,6 @@ static struct attribute *iwl_sysfs_entries[] = { | |||
| 2779 | #ifdef CONFIG_IWLWIFI_DEBUG | 2752 | #ifdef CONFIG_IWLWIFI_DEBUG |
| 2780 | &dev_attr_debug_level.attr, | 2753 | &dev_attr_debug_level.attr, |
| 2781 | #endif | 2754 | #endif |
| 2782 | &dev_attr_version.attr, | ||
| 2783 | NULL | 2755 | NULL |
| 2784 | }; | 2756 | }; |
| 2785 | 2757 | ||
| @@ -3139,15 +3111,12 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
| 3139 | {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3111 | {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)}, |
| 3140 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3112 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, |
| 3141 | /* 6000/6050 Series */ | 3113 | /* 6000/6050 Series */ |
| 3142 | {IWL_PCI_DEVICE(0x0082, 0x1102, iwl6000_2ag_cfg)}, | 3114 | {IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)}, |
| 3143 | {IWL_PCI_DEVICE(0x0085, 0x1112, iwl6000_2ag_cfg)}, | 3115 | {IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)}, |
| 3144 | {IWL_PCI_DEVICE(0x0082, 0x1122, iwl6000_2ag_cfg)}, | ||
| 3145 | {IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)}, | 3116 | {IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)}, |
| 3146 | {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000_2agn_cfg)}, | 3117 | {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000i_2agn_cfg)}, |
| 3147 | {IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)}, | 3118 | {IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)}, |
| 3148 | {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000_2agn_cfg)}, | 3119 | {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000i_2agn_cfg)}, |
| 3149 | {IWL_PCI_DEVICE(0x0082, PCI_ANY_ID, iwl6000_2agn_cfg)}, | ||
| 3150 | {IWL_PCI_DEVICE(0x0085, PCI_ANY_ID, iwl6000_3agn_cfg)}, | ||
| 3151 | {IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)}, | 3120 | {IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)}, |
| 3152 | {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, | 3121 | {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, |
| 3153 | {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, | 3122 | {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8570d56b3124..6797076bd45f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
| @@ -548,9 +548,6 @@ int iwlcore_init_geos(struct iwl_priv *priv) | |||
| 548 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | 548 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; |
| 549 | } | 549 | } |
| 550 | 550 | ||
| 551 | /* Save flags for reg domain usage */ | ||
| 552 | geo_ch->orig_flags = geo_ch->flags; | ||
| 553 | |||
| 554 | IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", | 551 | IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", |
| 555 | ch->channel, geo_ch->center_freq, | 552 | ch->channel, geo_ch->center_freq, |
| 556 | is_channel_a_band(ch) ? "5.2" : "2.4", | 553 | is_channel_a_band(ch) ? "5.2" : "2.4", |
| @@ -1140,7 +1137,6 @@ void iwl_set_flags_for_band(struct iwl_priv *priv, | |||
| 1140 | priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; | 1137 | priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; |
| 1141 | } | 1138 | } |
| 1142 | } | 1139 | } |
| 1143 | EXPORT_SYMBOL(iwl_set_flags_for_band); | ||
| 1144 | 1140 | ||
| 1145 | /* | 1141 | /* |
| 1146 | * initialize rxon structure with default values from eeprom | 1142 | * initialize rxon structure with default values from eeprom |
| @@ -2291,7 +2287,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) | |||
| 2291 | 2287 | ||
| 2292 | return iwl_send_cmd(priv, &cmd); | 2288 | return iwl_send_cmd(priv, &cmd); |
| 2293 | } | 2289 | } |
| 2294 | EXPORT_SYMBOL(iwl_send_card_state); | ||
| 2295 | 2290 | ||
| 2296 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | 2291 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, |
| 2297 | struct iwl_rx_mem_buffer *rxb) | 2292 | struct iwl_rx_mem_buffer *rxb) |
| @@ -2335,7 +2330,6 @@ void iwl_clear_isr_stats(struct iwl_priv *priv) | |||
| 2335 | { | 2330 | { |
| 2336 | memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); | 2331 | memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); |
| 2337 | } | 2332 | } |
| 2338 | EXPORT_SYMBOL(iwl_clear_isr_stats); | ||
| 2339 | 2333 | ||
| 2340 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 2334 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, |
| 2341 | const struct ieee80211_tx_queue_params *params) | 2335 | const struct ieee80211_tx_queue_params *params) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index febcf76e1d41..10ddcdda1041 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
| @@ -206,6 +206,7 @@ struct iwl_mod_params { | |||
| 206 | * filename is constructed as fw_name_pre<api>.ucode. | 206 | * filename is constructed as fw_name_pre<api>.ucode. |
| 207 | * @ucode_api_max: Highest version of uCode API supported by driver. | 207 | * @ucode_api_max: Highest version of uCode API supported by driver. |
| 208 | * @ucode_api_min: Lowest version of uCode API supported by driver. | 208 | * @ucode_api_min: Lowest version of uCode API supported by driver. |
| 209 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier | ||
| 209 | * | 210 | * |
| 210 | * We enable the driver to be backward compatible wrt API version. The | 211 | * We enable the driver to be backward compatible wrt API version. The |
| 211 | * driver specifies which APIs it supports (with @ucode_api_max being the | 212 | * driver specifies which APIs it supports (with @ucode_api_max being the |
| @@ -226,6 +227,7 @@ struct iwl_mod_params { | |||
| 226 | * iwl_hcmd_utils_ops etc. we accommodate different command structures | 227 | * iwl_hcmd_utils_ops etc. we accommodate different command structures |
| 227 | * and flows between hardware versions (4965/5000) as well as their API | 228 | * and flows between hardware versions (4965/5000) as well as their API |
| 228 | * versions. | 229 | * versions. |
| 230 | * | ||
| 229 | */ | 231 | */ |
| 230 | struct iwl_cfg { | 232 | struct iwl_cfg { |
| 231 | const char *name; | 233 | const char *name; |
| @@ -242,6 +244,7 @@ struct iwl_cfg { | |||
| 242 | u8 valid_rx_ant; | 244 | u8 valid_rx_ant; |
| 243 | bool need_pll_cfg; | 245 | bool need_pll_cfg; |
| 244 | bool use_isr_legacy; | 246 | bool use_isr_legacy; |
| 247 | enum iwl_pa_type pa_type; | ||
| 245 | }; | 248 | }; |
| 246 | 249 | ||
| 247 | /*************************** | 250 | /*************************** |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index f03dae1b2f36..06437d13e73e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
| @@ -91,7 +91,8 @@ | |||
| 91 | #define CSR_EEPROM_GP (CSR_BASE+0x030) | 91 | #define CSR_EEPROM_GP (CSR_BASE+0x030) |
| 92 | #define CSR_OTP_GP_REG (CSR_BASE+0x034) | 92 | #define CSR_OTP_GP_REG (CSR_BASE+0x034) |
| 93 | #define CSR_GIO_REG (CSR_BASE+0x03C) | 93 | #define CSR_GIO_REG (CSR_BASE+0x03C) |
| 94 | #define CSR_GP_UCODE (CSR_BASE+0x044) | 94 | #define CSR_GP_UCODE_REG (CSR_BASE+0x048) |
| 95 | #define CSR_GP_DRIVER_REG (CSR_BASE+0x050) | ||
| 95 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) | 96 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) |
| 96 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) | 97 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) |
| 97 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) | 98 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) |
| @@ -245,6 +246,13 @@ | |||
| 245 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) | 246 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) |
| 246 | #define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) | 247 | #define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) |
| 247 | 248 | ||
| 249 | /* GP Driver */ | ||
| 250 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003) | ||
| 251 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) | ||
| 252 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) | ||
| 253 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) | ||
| 254 | |||
| 255 | |||
| 248 | /* GI Chicken Bits */ | 256 | /* GI Chicken Bits */ |
| 249 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | 257 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) |
| 250 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) | 258 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0ee3ad245697..cab6255210d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
| @@ -56,8 +56,8 @@ extern struct iwl_cfg iwl5350_agn_cfg; | |||
| 56 | extern struct iwl_cfg iwl5100_bg_cfg; | 56 | extern struct iwl_cfg iwl5100_bg_cfg; |
| 57 | extern struct iwl_cfg iwl5100_abg_cfg; | 57 | extern struct iwl_cfg iwl5100_abg_cfg; |
| 58 | extern struct iwl_cfg iwl5150_agn_cfg; | 58 | extern struct iwl_cfg iwl5150_agn_cfg; |
| 59 | extern struct iwl_cfg iwl6000_2ag_cfg; | 59 | extern struct iwl_cfg iwl6000h_2agn_cfg; |
| 60 | extern struct iwl_cfg iwl6000_2agn_cfg; | 60 | extern struct iwl_cfg iwl6000i_2agn_cfg; |
| 61 | extern struct iwl_cfg iwl6000_3agn_cfg; | 61 | extern struct iwl_cfg iwl6000_3agn_cfg; |
| 62 | extern struct iwl_cfg iwl6050_2agn_cfg; | 62 | extern struct iwl_cfg iwl6050_2agn_cfg; |
| 63 | extern struct iwl_cfg iwl6050_3agn_cfg; | 63 | extern struct iwl_cfg iwl6050_3agn_cfg; |
| @@ -888,6 +888,19 @@ enum iwl_nvm_type { | |||
| 888 | NVM_DEVICE_TYPE_OTP, | 888 | NVM_DEVICE_TYPE_OTP, |
| 889 | }; | 889 | }; |
| 890 | 890 | ||
| 891 | |||
| 892 | /** | ||
| 893 | * enum iwl_pa_type - Power Amplifier type | ||
| 894 | * @IWL_PA_SYSTEM: based on uCode configuration | ||
| 895 | * @IWL_PA_HYBRID: use both Internal and external PA | ||
| 896 | * @IWL_PA_INTERNAL: use Internal only | ||
| 897 | */ | ||
| 898 | enum iwl_pa_type { | ||
| 899 | IWL_PA_SYSTEM = 0, | ||
| 900 | IWL_PA_HYBRID = 1, | ||
| 901 | IWL_PA_INTERNAL = 2, | ||
| 902 | }; | ||
| 903 | |||
| 891 | /* interrupt statistics */ | 904 | /* interrupt statistics */ |
| 892 | struct isr_statistics { | 905 | struct isr_statistics { |
| 893 | u32 hw; | 906 | u32 hw; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 7cce8f85bcc6..3d61cb43151c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
| @@ -335,7 +335,6 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
| 335 | priv->last_blink_time = jiffies; | 335 | priv->last_blink_time = jiffies; |
| 336 | priv->last_blink_rate = blink_idx; | 336 | priv->last_blink_rate = blink_idx; |
| 337 | } | 337 | } |
| 338 | EXPORT_SYMBOL(iwl_leds_background); | ||
| 339 | 338 | ||
| 340 | /* Register all led handler */ | 339 | /* Register all led handler */ |
| 341 | int iwl_leds_register(struct iwl_priv *priv) | 340 | int iwl_leds_register(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 5d5f2153f445..e002c8b56c49 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
| @@ -406,7 +406,6 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
| 406 | rxq->free_count = 0; | 406 | rxq->free_count = 0; |
| 407 | spin_unlock_irqrestore(&rxq->lock, flags); | 407 | spin_unlock_irqrestore(&rxq->lock, flags); |
| 408 | } | 408 | } |
| 409 | EXPORT_SYMBOL(iwl_rx_queue_reset); | ||
| 410 | 409 | ||
| 411 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | 410 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) |
| 412 | { | 411 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 79ea5cc2c89a..efcae0d5e193 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
| @@ -464,7 +464,6 @@ out: | |||
| 464 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 464 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
| 465 | return ret; | 465 | return ret; |
| 466 | } | 466 | } |
| 467 | EXPORT_SYMBOL(iwl_remove_station); | ||
| 468 | 467 | ||
| 469 | /** | 468 | /** |
| 470 | * iwl_clear_stations_table - Clear the driver's station table | 469 | * iwl_clear_stations_table - Clear the driver's station table |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 6bb9602f3477..288b871e974b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
| @@ -970,6 +970,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
| 970 | out_cmd = txq->cmd[idx]; | 970 | out_cmd = txq->cmd[idx]; |
| 971 | out_meta = &txq->meta[idx]; | 971 | out_meta = &txq->meta[idx]; |
| 972 | 972 | ||
| 973 | memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ | ||
| 973 | out_meta->flags = cmd->flags; | 974 | out_meta->flags = cmd->flags; |
| 974 | if (cmd->flags & CMD_WANT_SKB) | 975 | if (cmd->flags & CMD_WANT_SKB) |
| 975 | out_meta->source = cmd; | 976 | out_meta->source = cmd; |
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 3f5a08fa401f..a6e852f4f92c 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
| @@ -484,6 +484,8 @@ static int iwm_set_auth_type(struct iwm_priv *iwm, | |||
| 484 | 484 | ||
| 485 | static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) | 485 | static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) |
| 486 | { | 486 | { |
| 487 | IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version); | ||
| 488 | |||
| 487 | if (!wpa_version) { | 489 | if (!wpa_version) { |
| 488 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; | 490 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; |
| 489 | return 0; | 491 | return 0; |
| @@ -508,6 +510,9 @@ static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) | |||
| 508 | return 0; | 510 | return 0; |
| 509 | } | 511 | } |
| 510 | 512 | ||
| 513 | IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm', | ||
| 514 | cipher); | ||
| 515 | |||
| 511 | switch (cipher) { | 516 | switch (cipher) { |
| 512 | case IW_AUTH_CIPHER_NONE: | 517 | case IW_AUTH_CIPHER_NONE: |
| 513 | *profile_cipher = UMAC_CIPHER_TYPE_NONE; | 518 | *profile_cipher = UMAC_CIPHER_TYPE_NONE; |
| @@ -584,11 +589,11 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
| 584 | iwm->umac_profile->bss_num = 0; | 589 | iwm->umac_profile->bss_num = 0; |
| 585 | } | 590 | } |
| 586 | 591 | ||
| 587 | ret = iwm_set_auth_type(iwm, sme->auth_type); | 592 | ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); |
| 588 | if (ret < 0) | 593 | if (ret < 0) |
| 589 | return ret; | 594 | return ret; |
| 590 | 595 | ||
| 591 | ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); | 596 | ret = iwm_set_auth_type(iwm, sme->auth_type); |
| 592 | if (ret < 0) | 597 | if (ret < 0) |
| 593 | return ret; | 598 | return ret; |
| 594 | 599 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 0d6637005f42..f0c8acdb71a4 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c | |||
| @@ -526,19 +526,6 @@ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) | |||
| 526 | return 0; | 526 | return 0; |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx) | ||
| 530 | { | ||
| 531 | struct iwm_umac_tx_key_id tx_key_id; | ||
| 532 | |||
| 533 | tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; | ||
| 534 | tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - | ||
| 535 | sizeof(struct iwm_umac_wifi_if)); | ||
| 536 | |||
| 537 | tx_key_id.key_idx = key_idx; | ||
| 538 | |||
| 539 | return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1); | ||
| 540 | } | ||
| 541 | |||
| 542 | static int iwm_check_profile(struct iwm_priv *iwm) | 529 | static int iwm_check_profile(struct iwm_priv *iwm) |
| 543 | { | 530 | { |
| 544 | if (!iwm->umac_profile_active) | 531 | if (!iwm->umac_profile_active) |
| @@ -572,6 +559,32 @@ static int iwm_check_profile(struct iwm_priv *iwm) | |||
| 572 | return 0; | 559 | return 0; |
| 573 | } | 560 | } |
| 574 | 561 | ||
| 562 | int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx) | ||
| 563 | { | ||
| 564 | struct iwm_umac_tx_key_id tx_key_id; | ||
| 565 | int ret; | ||
| 566 | |||
| 567 | ret = iwm_check_profile(iwm); | ||
| 568 | if (ret < 0) | ||
| 569 | return ret; | ||
| 570 | |||
| 571 | /* UMAC only allows to set default key for WEP and auth type is | ||
| 572 | * NOT 802.1X or RSNA. */ | ||
| 573 | if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 && | ||
| 574 | iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) || | ||
| 575 | iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X || | ||
| 576 | iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK) | ||
| 577 | return 0; | ||
| 578 | |||
| 579 | tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; | ||
| 580 | tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - | ||
| 581 | sizeof(struct iwm_umac_wifi_if)); | ||
| 582 | |||
| 583 | tx_key_id.key_idx = key_idx; | ||
| 584 | |||
| 585 | return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1); | ||
| 586 | } | ||
| 587 | |||
| 575 | int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) | 588 | int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) |
| 576 | { | 589 | { |
| 577 | int ret = 0; | 590 | int ret = 0; |
| @@ -596,6 +609,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) | |||
| 596 | key_idx = key->hdr.key_idx; | 609 | key_idx = key->hdr.key_idx; |
| 597 | 610 | ||
| 598 | if (!remove) { | 611 | if (!remove) { |
| 612 | u8 auth_type = iwm->umac_profile->sec.auth_type; | ||
| 613 | |||
| 599 | IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx); | 614 | IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx); |
| 600 | IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len); | 615 | IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len); |
| 601 | IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n", | 616 | IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n", |
| @@ -618,7 +633,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) | |||
| 618 | memcpy(&wep40->key_hdr, key_hdr, | 633 | memcpy(&wep40->key_hdr, key_hdr, |
| 619 | sizeof(struct iwm_umac_key_hdr)); | 634 | sizeof(struct iwm_umac_key_hdr)); |
| 620 | memcpy(wep40->key, key_data, key_len); | 635 | memcpy(wep40->key, key_data, key_len); |
| 621 | wep40->static_key = 1; | 636 | wep40->static_key = |
| 637 | !!((auth_type != UMAC_AUTH_TYPE_8021X) && | ||
| 638 | (auth_type != UMAC_AUTH_TYPE_RSNA_PSK)); | ||
| 622 | 639 | ||
| 623 | cmd_size = sizeof(struct iwm_umac_key_wep40); | 640 | cmd_size = sizeof(struct iwm_umac_key_wep40); |
| 624 | break; | 641 | break; |
| @@ -632,7 +649,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) | |||
| 632 | memcpy(&wep104->key_hdr, key_hdr, | 649 | memcpy(&wep104->key_hdr, key_hdr, |
| 633 | sizeof(struct iwm_umac_key_hdr)); | 650 | sizeof(struct iwm_umac_key_hdr)); |
| 634 | memcpy(wep104->key, key_data, key_len); | 651 | memcpy(wep104->key, key_data, key_len); |
| 635 | wep104->static_key = 1; | 652 | wep104->static_key = |
| 653 | !!((auth_type != UMAC_AUTH_TYPE_8021X) && | ||
| 654 | (auth_type != UMAC_AUTH_TYPE_RSNA_PSK)); | ||
| 636 | 655 | ||
| 637 | cmd_size = sizeof(struct iwm_umac_key_wep104); | 656 | cmd_size = sizeof(struct iwm_umac_key_wep104); |
| 638 | break; | 657 | break; |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 963c20125fc9..446e327180f8 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
| @@ -376,7 +376,7 @@ static int spu_set_bus_mode(struct if_spi_card *card, u16 mode) | |||
| 376 | err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval); | 376 | err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval); |
| 377 | if (err) | 377 | if (err) |
| 378 | return err; | 378 | return err; |
| 379 | if (rval != mode) { | 379 | if ((rval & 0xF) != mode) { |
| 380 | lbs_pr_err("Can't read bus mode register.\n"); | 380 | lbs_pr_err("Can't read bus mode register.\n"); |
| 381 | return -EIO; | 381 | return -EIO; |
| 382 | } | 382 | } |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index e96451ce470b..be837a0d2517 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
| @@ -1728,6 +1728,8 @@ static int lbs_set_auth(struct net_device *dev, | |||
| 1728 | } | 1728 | } |
| 1729 | 1729 | ||
| 1730 | switch (dwrq->flags & IW_AUTH_INDEX) { | 1730 | switch (dwrq->flags & IW_AUTH_INDEX) { |
| 1731 | case IW_AUTH_PRIVACY_INVOKED: | ||
| 1732 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
| 1731 | case IW_AUTH_TKIP_COUNTERMEASURES: | 1733 | case IW_AUTH_TKIP_COUNTERMEASURES: |
| 1732 | case IW_AUTH_CIPHER_PAIRWISE: | 1734 | case IW_AUTH_CIPHER_PAIRWISE: |
| 1733 | case IW_AUTH_CIPHER_GROUP: | 1735 | case IW_AUTH_CIPHER_GROUP: |
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index 1a87d3a0967c..27f2d3342645 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c | |||
| @@ -156,7 +156,48 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev, | |||
| 156 | return err; | 156 | return err; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | static int orinoco_set_channel(struct wiphy *wiphy, | ||
| 160 | struct ieee80211_channel *chan, | ||
| 161 | enum nl80211_channel_type channel_type) | ||
| 162 | { | ||
| 163 | struct orinoco_private *priv = wiphy_priv(wiphy); | ||
| 164 | int err = 0; | ||
| 165 | unsigned long flags; | ||
| 166 | int channel; | ||
| 167 | |||
| 168 | if (!chan) | ||
| 169 | return -EINVAL; | ||
| 170 | |||
| 171 | if (channel_type != NL80211_CHAN_NO_HT) | ||
| 172 | return -EINVAL; | ||
| 173 | |||
| 174 | if (chan->band != IEEE80211_BAND_2GHZ) | ||
| 175 | return -EINVAL; | ||
| 176 | |||
| 177 | channel = ieee80211_freq_to_dsss_chan(chan->center_freq); | ||
| 178 | |||
| 179 | if ((channel < 1) || (channel > NUM_CHANNELS) || | ||
| 180 | !(priv->channel_mask & (1 << (channel-1)))) | ||
| 181 | return -EINVAL; | ||
| 182 | |||
| 183 | if (orinoco_lock(priv, &flags) != 0) | ||
| 184 | return -EBUSY; | ||
| 185 | |||
| 186 | priv->channel = channel; | ||
| 187 | if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { | ||
| 188 | /* Fast channel change - no commit if successful */ | ||
| 189 | hermes_t *hw = &priv->hw; | ||
| 190 | err = hermes_docmd_wait(hw, HERMES_CMD_TEST | | ||
| 191 | HERMES_TEST_SET_CHANNEL, | ||
| 192 | channel, NULL); | ||
| 193 | } | ||
| 194 | orinoco_unlock(priv, &flags); | ||
| 195 | |||
| 196 | return err; | ||
| 197 | } | ||
| 198 | |||
| 159 | const struct cfg80211_ops orinoco_cfg_ops = { | 199 | const struct cfg80211_ops orinoco_cfg_ops = { |
| 160 | .change_virtual_intf = orinoco_change_vif, | 200 | .change_virtual_intf = orinoco_change_vif, |
| 201 | .set_channel = orinoco_set_channel, | ||
| 161 | .scan = orinoco_scan, | 202 | .scan = orinoco_scan, |
| 162 | }; | 203 | }; |
diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c index c00115b206d4..9575ac033630 100644 --- a/drivers/net/wireless/p54/led.c +++ b/drivers/net/wireless/p54/led.c | |||
| @@ -61,7 +61,7 @@ static void p54_update_leds(struct work_struct *work) | |||
| 61 | wiphy_name(priv->hw->wiphy), err); | 61 | wiphy_name(priv->hw->wiphy), err); |
| 62 | 62 | ||
| 63 | if (rerun) | 63 | if (rerun) |
| 64 | queue_delayed_work(priv->hw->workqueue, &priv->led_work, | 64 | ieee80211_queue_delayed_work(priv->hw, &priv->led_work, |
| 65 | msecs_to_jiffies(blink_delay)); | 65 | msecs_to_jiffies(blink_delay)); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| @@ -78,8 +78,7 @@ static void p54_led_brightness_set(struct led_classdev *led_dev, | |||
| 78 | 78 | ||
| 79 | if ((brightness) && (led->registered)) { | 79 | if ((brightness) && (led->registered)) { |
| 80 | led->toggled++; | 80 | led->toggled++; |
| 81 | queue_delayed_work(priv->hw->workqueue, &priv->led_work, | 81 | ieee80211_queue_delayed_work(priv->hw, &priv->led_work, HZ/10); |
| 82 | HZ/10); | ||
| 83 | } | 82 | } |
| 84 | } | 83 | } |
| 85 | 84 | ||
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 955f6d7ec16a..a0d0e726bc4e 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
| @@ -180,7 +180,7 @@ static int p54_start(struct ieee80211_hw *dev) | |||
| 180 | goto out; | 180 | goto out; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | queue_delayed_work(dev->workqueue, &priv->work, 0); | 183 | ieee80211_queue_delayed_work(dev, &priv->work, 0); |
| 184 | 184 | ||
| 185 | priv->softled_state = 0; | 185 | priv->softled_state = 0; |
| 186 | err = p54_set_leds(priv); | 186 | err = p54_set_leds(priv); |
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index eef532987d05..05458d9249ce 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c | |||
| @@ -391,7 +391,7 @@ static irqreturn_t p54spi_interrupt(int irq, void *config) | |||
| 391 | struct spi_device *spi = config; | 391 | struct spi_device *spi = config; |
| 392 | struct p54s_priv *priv = dev_get_drvdata(&spi->dev); | 392 | struct p54s_priv *priv = dev_get_drvdata(&spi->dev); |
| 393 | 393 | ||
| 394 | queue_work(priv->hw->workqueue, &priv->work); | 394 | ieee80211_queue_work(priv->hw, &priv->work); |
| 395 | 395 | ||
| 396 | return IRQ_HANDLED; | 396 | return IRQ_HANDLED; |
| 397 | } | 397 | } |
| @@ -479,7 +479,7 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 479 | list_add_tail(&di->tx_list, &priv->tx_pending); | 479 | list_add_tail(&di->tx_list, &priv->tx_pending); |
| 480 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 480 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
| 481 | 481 | ||
| 482 | queue_work(priv->hw->workqueue, &priv->work); | 482 | ieee80211_queue_work(priv->hw, &priv->work); |
| 483 | } | 483 | } |
| 484 | 484 | ||
| 485 | static void p54spi_work(struct work_struct *work) | 485 | static void p54spi_work(struct work_struct *work) |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index c32a0d2fa1f7..704685fab177 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
| @@ -380,7 +380,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) | |||
| 380 | 380 | ||
| 381 | ieee80211_rx_irqsafe(priv->hw, skb); | 381 | ieee80211_rx_irqsafe(priv->hw, skb); |
| 382 | 382 | ||
| 383 | queue_delayed_work(priv->hw->workqueue, &priv->work, | 383 | ieee80211_queue_delayed_work(priv->hw, &priv->work, |
| 384 | msecs_to_jiffies(P54_STATISTICS_UPDATE)); | 384 | msecs_to_jiffies(P54_STATISTICS_UPDATE)); |
| 385 | 385 | ||
| 386 | return -1; | 386 | return -1; |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 09c0702ae645..828dc1825bba 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
| @@ -100,7 +100,6 @@ MODULE_PARM_DESC(workaround_interval, | |||
| 100 | #define OID_GEN_RCV_ERROR cpu_to_le32(0x00020104) | 100 | #define OID_GEN_RCV_ERROR cpu_to_le32(0x00020104) |
| 101 | #define OID_GEN_RCV_NO_BUFFER cpu_to_le32(0x00020105) | 101 | #define OID_GEN_RCV_NO_BUFFER cpu_to_le32(0x00020105) |
| 102 | 102 | ||
| 103 | #define OID_802_3_PERMANENT_ADDRESS cpu_to_le32(0x01010101) | ||
| 104 | #define OID_802_3_CURRENT_ADDRESS cpu_to_le32(0x01010102) | 103 | #define OID_802_3_CURRENT_ADDRESS cpu_to_le32(0x01010102) |
| 105 | #define OID_802_3_MULTICAST_LIST cpu_to_le32(0x01010103) | 104 | #define OID_802_3_MULTICAST_LIST cpu_to_le32(0x01010103) |
| 106 | #define OID_802_3_MAXIMUM_LIST_SIZE cpu_to_le32(0x01010104) | 105 | #define OID_802_3_MAXIMUM_LIST_SIZE cpu_to_le32(0x01010104) |
| @@ -202,6 +201,24 @@ enum ndis_80211_priv_filter { | |||
| 202 | NDIS_80211_PRIV_8021X_WEP | 201 | NDIS_80211_PRIV_8021X_WEP |
| 203 | }; | 202 | }; |
| 204 | 203 | ||
| 204 | enum ndis_80211_status_type { | ||
| 205 | NDIS_80211_STATUSTYPE_AUTHENTICATION, | ||
| 206 | NDIS_80211_STATUSTYPE_MEDIASTREAMMODE, | ||
| 207 | NDIS_80211_STATUSTYPE_PMKID_CANDIDATELIST, | ||
| 208 | NDIS_80211_STATUSTYPE_RADIOSTATE, | ||
| 209 | }; | ||
| 210 | |||
| 211 | enum ndis_80211_media_stream_mode { | ||
| 212 | NDIS_80211_MEDIA_STREAM_OFF, | ||
| 213 | NDIS_80211_MEDIA_STREAM_ON | ||
| 214 | }; | ||
| 215 | |||
| 216 | enum ndis_80211_radio_status { | ||
| 217 | NDIS_80211_RADIO_STATUS_ON, | ||
| 218 | NDIS_80211_RADIO_STATUS_HARDWARE_OFF, | ||
| 219 | NDIS_80211_RADIO_STATUS_SOFTWARE_OFF, | ||
| 220 | }; | ||
| 221 | |||
| 205 | enum ndis_80211_addkey_bits { | 222 | enum ndis_80211_addkey_bits { |
| 206 | NDIS_80211_ADDKEY_8021X_AUTH = cpu_to_le32(1 << 28), | 223 | NDIS_80211_ADDKEY_8021X_AUTH = cpu_to_le32(1 << 28), |
| 207 | NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ = cpu_to_le32(1 << 29), | 224 | NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ = cpu_to_le32(1 << 29), |
| @@ -214,6 +231,35 @@ enum ndis_80211_addwep_bits { | |||
| 214 | NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31) | 231 | NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31) |
| 215 | }; | 232 | }; |
| 216 | 233 | ||
| 234 | struct ndis_80211_auth_request { | ||
| 235 | __le32 length; | ||
| 236 | u8 bssid[6]; | ||
| 237 | u8 padding[2]; | ||
| 238 | __le32 flags; | ||
| 239 | } __attribute__((packed)); | ||
| 240 | |||
| 241 | struct ndis_80211_pmkid_candidate { | ||
| 242 | u8 bssid[6]; | ||
| 243 | u8 padding[2]; | ||
| 244 | __le32 flags; | ||
| 245 | } __attribute__((packed)); | ||
| 246 | |||
| 247 | struct ndis_80211_pmkid_cand_list { | ||
| 248 | __le32 version; | ||
| 249 | __le32 num_candidates; | ||
| 250 | struct ndis_80211_pmkid_candidate candidate_list[0]; | ||
| 251 | } __attribute__((packed)); | ||
| 252 | |||
| 253 | struct ndis_80211_status_indication { | ||
| 254 | __le32 status_type; | ||
| 255 | union { | ||
| 256 | enum ndis_80211_media_stream_mode media_stream_mode; | ||
| 257 | enum ndis_80211_radio_status radio_status; | ||
| 258 | struct ndis_80211_auth_request auth_request[0]; | ||
| 259 | struct ndis_80211_pmkid_cand_list cand_list; | ||
| 260 | } u; | ||
| 261 | } __attribute__((packed)); | ||
| 262 | |||
| 217 | struct ndis_80211_ssid { | 263 | struct ndis_80211_ssid { |
| 218 | __le32 length; | 264 | __le32 length; |
| 219 | u8 essid[NDIS_802_11_LENGTH_SSID]; | 265 | u8 essid[NDIS_802_11_LENGTH_SSID]; |
| @@ -281,6 +327,7 @@ struct ndis_80211_remove_key { | |||
| 281 | __le32 size; | 327 | __le32 size; |
| 282 | __le32 index; | 328 | __le32 index; |
| 283 | u8 bssid[6]; | 329 | u8 bssid[6]; |
| 330 | u8 padding[2]; | ||
| 284 | } __attribute__((packed)); | 331 | } __attribute__((packed)); |
| 285 | 332 | ||
| 286 | struct ndis_config_param { | 333 | struct ndis_config_param { |
| @@ -366,6 +413,15 @@ static const struct ieee80211_rate rndis_rates[] = { | |||
| 366 | { .bitrate = 540 } | 413 | { .bitrate = 540 } |
| 367 | }; | 414 | }; |
| 368 | 415 | ||
| 416 | struct rndis_wlan_encr_key { | ||
| 417 | int len; | ||
| 418 | int cipher; | ||
| 419 | u8 material[32]; | ||
| 420 | u8 bssid[ETH_ALEN]; | ||
| 421 | bool pairwise; | ||
| 422 | bool tx_key; | ||
| 423 | }; | ||
| 424 | |||
| 369 | /* RNDIS device private data */ | 425 | /* RNDIS device private data */ |
| 370 | struct rndis_wlan_private { | 426 | struct rndis_wlan_private { |
| 371 | struct usbnet *usbdev; | 427 | struct usbnet *usbdev; |
| @@ -409,9 +465,7 @@ struct rndis_wlan_private { | |||
| 409 | 465 | ||
| 410 | /* encryption stuff */ | 466 | /* encryption stuff */ |
| 411 | int encr_tx_key_index; | 467 | int encr_tx_key_index; |
| 412 | char encr_keys[4][32]; | 468 | struct rndis_wlan_encr_key encr_keys[4]; |
| 413 | int encr_key_len[4]; | ||
| 414 | char encr_key_wpa[4]; | ||
| 415 | int wpa_version; | 469 | int wpa_version; |
| 416 | int wpa_keymgmt; | 470 | int wpa_keymgmt; |
| 417 | int wpa_authalg; | 471 | int wpa_authalg; |
| @@ -478,6 +532,77 @@ static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv) | |||
| 478 | } | 532 | } |
| 479 | 533 | ||
| 480 | 534 | ||
| 535 | static bool is_wpa_key(struct rndis_wlan_private *priv, int idx) | ||
| 536 | { | ||
| 537 | int cipher = priv->encr_keys[idx].cipher; | ||
| 538 | |||
| 539 | return (cipher == WLAN_CIPHER_SUITE_CCMP || | ||
| 540 | cipher == WLAN_CIPHER_SUITE_TKIP); | ||
| 541 | } | ||
| 542 | |||
| 543 | |||
| 544 | #ifdef DEBUG | ||
| 545 | static const char *oid_to_string(__le32 oid) | ||
| 546 | { | ||
| 547 | switch (oid) { | ||
| 548 | #define OID_STR(oid) case oid: return(#oid) | ||
| 549 | /* from rndis_host.h */ | ||
| 550 | OID_STR(OID_802_3_PERMANENT_ADDRESS); | ||
| 551 | OID_STR(OID_GEN_MAXIMUM_FRAME_SIZE); | ||
| 552 | OID_STR(OID_GEN_CURRENT_PACKET_FILTER); | ||
| 553 | OID_STR(OID_GEN_PHYSICAL_MEDIUM); | ||
| 554 | |||
| 555 | /* from rndis_wlan.c */ | ||
| 556 | OID_STR(OID_GEN_LINK_SPEED); | ||
| 557 | OID_STR(OID_GEN_RNDIS_CONFIG_PARAMETER); | ||
| 558 | |||
| 559 | OID_STR(OID_GEN_XMIT_OK); | ||
| 560 | OID_STR(OID_GEN_RCV_OK); | ||
| 561 | OID_STR(OID_GEN_XMIT_ERROR); | ||
| 562 | OID_STR(OID_GEN_RCV_ERROR); | ||
| 563 | OID_STR(OID_GEN_RCV_NO_BUFFER); | ||
| 564 | |||
| 565 | OID_STR(OID_802_3_CURRENT_ADDRESS); | ||
| 566 | OID_STR(OID_802_3_MULTICAST_LIST); | ||
| 567 | OID_STR(OID_802_3_MAXIMUM_LIST_SIZE); | ||
| 568 | |||
| 569 | OID_STR(OID_802_11_BSSID); | ||
| 570 | OID_STR(OID_802_11_SSID); | ||
| 571 | OID_STR(OID_802_11_INFRASTRUCTURE_MODE); | ||
| 572 | OID_STR(OID_802_11_ADD_WEP); | ||
| 573 | OID_STR(OID_802_11_REMOVE_WEP); | ||
| 574 | OID_STR(OID_802_11_DISASSOCIATE); | ||
| 575 | OID_STR(OID_802_11_AUTHENTICATION_MODE); | ||
| 576 | OID_STR(OID_802_11_PRIVACY_FILTER); | ||
| 577 | OID_STR(OID_802_11_BSSID_LIST_SCAN); | ||
| 578 | OID_STR(OID_802_11_ENCRYPTION_STATUS); | ||
| 579 | OID_STR(OID_802_11_ADD_KEY); | ||
| 580 | OID_STR(OID_802_11_REMOVE_KEY); | ||
| 581 | OID_STR(OID_802_11_ASSOCIATION_INFORMATION); | ||
| 582 | OID_STR(OID_802_11_PMKID); | ||
| 583 | OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED); | ||
| 584 | OID_STR(OID_802_11_NETWORK_TYPE_IN_USE); | ||
| 585 | OID_STR(OID_802_11_TX_POWER_LEVEL); | ||
| 586 | OID_STR(OID_802_11_RSSI); | ||
| 587 | OID_STR(OID_802_11_RSSI_TRIGGER); | ||
| 588 | OID_STR(OID_802_11_FRAGMENTATION_THRESHOLD); | ||
| 589 | OID_STR(OID_802_11_RTS_THRESHOLD); | ||
| 590 | OID_STR(OID_802_11_SUPPORTED_RATES); | ||
| 591 | OID_STR(OID_802_11_CONFIGURATION); | ||
| 592 | OID_STR(OID_802_11_BSSID_LIST); | ||
| 593 | #undef OID_STR | ||
| 594 | } | ||
| 595 | |||
| 596 | return "?"; | ||
| 597 | } | ||
| 598 | #else | ||
| 599 | static const char *oid_to_string(__le32 oid) | ||
| 600 | { | ||
| 601 | return "?"; | ||
| 602 | } | ||
| 603 | #endif | ||
| 604 | |||
| 605 | |||
| 481 | /* translate error code */ | 606 | /* translate error code */ |
| 482 | static int rndis_error_status(__le32 rndis_status) | 607 | static int rndis_error_status(__le32 rndis_status) |
| 483 | { | 608 | { |
| @@ -533,11 +658,21 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) | |||
| 533 | u.get->oid = oid; | 658 | u.get->oid = oid; |
| 534 | 659 | ||
| 535 | ret = rndis_command(dev, u.header, buflen); | 660 | ret = rndis_command(dev, u.header, buflen); |
| 661 | if (ret < 0) | ||
| 662 | devdbg(dev, "rndis_query_oid(%s): rndis_command() failed, %d " | ||
| 663 | "(%08x)", oid_to_string(oid), ret, | ||
| 664 | le32_to_cpu(u.get_c->status)); | ||
| 665 | |||
| 536 | if (ret == 0) { | 666 | if (ret == 0) { |
| 537 | ret = le32_to_cpu(u.get_c->len); | 667 | ret = le32_to_cpu(u.get_c->len); |
| 538 | *len = (*len > ret) ? ret : *len; | 668 | *len = (*len > ret) ? ret : *len; |
| 539 | memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); | 669 | memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); |
| 540 | ret = rndis_error_status(u.get_c->status); | 670 | ret = rndis_error_status(u.get_c->status); |
| 671 | |||
| 672 | if (ret < 0) | ||
| 673 | devdbg(dev, "rndis_query_oid(%s): device returned " | ||
| 674 | "error, 0x%08x (%d)", oid_to_string(oid), | ||
| 675 | le32_to_cpu(u.get_c->status), ret); | ||
| 541 | } | 676 | } |
| 542 | 677 | ||
| 543 | mutex_unlock(&priv->command_lock); | 678 | mutex_unlock(&priv->command_lock); |
| @@ -583,9 +718,20 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) | |||
| 583 | memcpy(u.buf + sizeof(*u.set), data, len); | 718 | memcpy(u.buf + sizeof(*u.set), data, len); |
| 584 | 719 | ||
| 585 | ret = rndis_command(dev, u.header, buflen); | 720 | ret = rndis_command(dev, u.header, buflen); |
| 586 | if (ret == 0) | 721 | if (ret < 0) |
| 722 | devdbg(dev, "rndis_set_oid(%s): rndis_command() failed, %d " | ||
| 723 | "(%08x)", oid_to_string(oid), ret, | ||
| 724 | le32_to_cpu(u.set_c->status)); | ||
| 725 | |||
| 726 | if (ret == 0) { | ||
| 587 | ret = rndis_error_status(u.set_c->status); | 727 | ret = rndis_error_status(u.set_c->status); |
| 588 | 728 | ||
| 729 | if (ret < 0) | ||
| 730 | devdbg(dev, "rndis_set_oid(%s): device returned error, " | ||
| 731 | "0x%08x (%d)", oid_to_string(oid), | ||
| 732 | le32_to_cpu(u.set_c->status), ret); | ||
| 733 | } | ||
| 734 | |||
| 589 | mutex_unlock(&priv->command_lock); | 735 | mutex_unlock(&priv->command_lock); |
| 590 | 736 | ||
| 591 | if (u.buf != priv->command_buffer) | 737 | if (u.buf != priv->command_buffer) |
| @@ -594,6 +740,28 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) | |||
| 594 | } | 740 | } |
| 595 | 741 | ||
| 596 | 742 | ||
| 743 | static int rndis_reset(struct usbnet *usbdev) | ||
| 744 | { | ||
| 745 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
| 746 | struct rndis_reset *reset; | ||
| 747 | int ret; | ||
| 748 | |||
| 749 | mutex_lock(&priv->command_lock); | ||
| 750 | |||
| 751 | reset = (void *)priv->command_buffer; | ||
| 752 | memset(reset, 0, sizeof(*reset)); | ||
| 753 | reset->msg_type = RNDIS_MSG_RESET; | ||
| 754 | reset->msg_len = cpu_to_le32(sizeof(*reset)); | ||
| 755 | ret = rndis_command(usbdev, (void *)reset, CONTROL_BUFFER_SIZE); | ||
| 756 | |||
| 757 | mutex_unlock(&priv->command_lock); | ||
| 758 | |||
| 759 | if (ret < 0) | ||
| 760 | return ret; | ||
| 761 | return 0; | ||
| 762 | } | ||
| 763 | |||
| 764 | |||
| 597 | /* | 765 | /* |
| 598 | * Specs say that we can only set config parameters only soon after device | 766 | * Specs say that we can only set config parameters only soon after device |
| 599 | * initialization. | 767 | * initialization. |
| @@ -743,8 +911,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig) | |||
| 743 | /* | 911 | /* |
| 744 | * common functions | 912 | * common functions |
| 745 | */ | 913 | */ |
| 746 | static int | 914 | static void restore_keys(struct usbnet *usbdev); |
| 747 | add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index); | ||
| 748 | 915 | ||
| 749 | static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) | 916 | static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) |
| 750 | { | 917 | { |
| @@ -963,7 +1130,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode) | |||
| 963 | { | 1130 | { |
| 964 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1131 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
| 965 | __le32 tmp; | 1132 | __le32 tmp; |
| 966 | int ret, i; | 1133 | int ret; |
| 967 | 1134 | ||
| 968 | devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode); | 1135 | devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode); |
| 969 | 1136 | ||
| @@ -978,14 +1145,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode) | |||
| 978 | /* NDIS drivers clear keys when infrastructure mode is | 1145 | /* NDIS drivers clear keys when infrastructure mode is |
| 979 | * changed. But Linux tools assume otherwise. So set the | 1146 | * changed. But Linux tools assume otherwise. So set the |
| 980 | * keys */ | 1147 | * keys */ |
| 981 | if (priv->wpa_keymgmt == 0 || | 1148 | restore_keys(usbdev); |
| 982 | priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) { | ||
| 983 | for (i = 0; i < 4; i++) { | ||
| 984 | if (priv->encr_key_len[i] > 0 && !priv->encr_key_wpa[i]) | ||
| 985 | add_wep_key(usbdev, priv->encr_keys[i], | ||
| 986 | priv->encr_key_len[i], i); | ||
| 987 | } | ||
| 988 | } | ||
| 989 | 1149 | ||
| 990 | priv->infra_mode = mode; | 1150 | priv->infra_mode = mode; |
| 991 | return 0; | 1151 | return 0; |
| @@ -1052,11 +1212,16 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) | |||
| 1052 | { | 1212 | { |
| 1053 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1213 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
| 1054 | struct ndis_80211_wep_key ndis_key; | 1214 | struct ndis_80211_wep_key ndis_key; |
| 1055 | int ret; | 1215 | int cipher, ret; |
| 1056 | 1216 | ||
| 1057 | if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4) | 1217 | if ((key_len != 5 || key_len != 13) || index < 0 || index > 3) |
| 1058 | return -EINVAL; | 1218 | return -EINVAL; |
| 1059 | 1219 | ||
| 1220 | if (key_len == 5) | ||
| 1221 | cipher = WLAN_CIPHER_SUITE_WEP40; | ||
| 1222 | else | ||
| 1223 | cipher = WLAN_CIPHER_SUITE_WEP104; | ||
| 1224 | |||
| 1060 | memset(&ndis_key, 0, sizeof(ndis_key)); | 1225 | memset(&ndis_key, 0, sizeof(ndis_key)); |
| 1061 | 1226 | ||
| 1062 | ndis_key.size = cpu_to_le32(sizeof(ndis_key)); | 1227 | ndis_key.size = cpu_to_le32(sizeof(ndis_key)); |
| @@ -1081,30 +1246,44 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) | |||
| 1081 | return ret; | 1246 | return ret; |
| 1082 | } | 1247 | } |
| 1083 | 1248 | ||
| 1084 | priv->encr_key_len[index] = key_len; | 1249 | priv->encr_keys[index].len = key_len; |
| 1085 | priv->encr_key_wpa[index] = 0; | 1250 | priv->encr_keys[index].cipher = cipher; |
| 1086 | memcpy(&priv->encr_keys[index], key, key_len); | 1251 | memcpy(&priv->encr_keys[index].material, key, key_len); |
| 1252 | memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN); | ||
| 1087 | 1253 | ||
| 1088 | return 0; | 1254 | return 0; |
| 1089 | } | 1255 | } |
| 1090 | 1256 | ||
| 1091 | 1257 | ||
| 1092 | static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | 1258 | static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, |
| 1093 | int index, const struct sockaddr *addr, | 1259 | int index, const u8 *addr, const u8 *rx_seq, int cipher, |
| 1094 | const u8 *rx_seq, int alg, int flags) | 1260 | int flags) |
| 1095 | { | 1261 | { |
| 1096 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1262 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
| 1097 | struct ndis_80211_key ndis_key; | 1263 | struct ndis_80211_key ndis_key; |
| 1264 | bool is_addr_ok; | ||
| 1098 | int ret; | 1265 | int ret; |
| 1099 | 1266 | ||
| 1100 | if (index < 0 || index >= 4) | 1267 | if (index < 0 || index >= 4) { |
| 1268 | devdbg(usbdev, "add_wpa_key: index out of range (%i)", index); | ||
| 1101 | return -EINVAL; | 1269 | return -EINVAL; |
| 1102 | if (key_len > sizeof(ndis_key.material) || key_len < 0) | 1270 | } |
| 1271 | if (key_len > sizeof(ndis_key.material) || key_len < 0) { | ||
| 1272 | devdbg(usbdev, "add_wpa_key: key length out of range (%i)", | ||
| 1273 | key_len); | ||
| 1103 | return -EINVAL; | 1274 | return -EINVAL; |
| 1104 | if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) | 1275 | } |
| 1276 | if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) { | ||
| 1277 | devdbg(usbdev, "add_wpa_key: recv seq flag without buffer"); | ||
| 1105 | return -EINVAL; | 1278 | return -EINVAL; |
| 1106 | if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !addr) | 1279 | } |
| 1280 | is_addr_ok = addr && memcmp(addr, zero_bssid, ETH_ALEN) != 0 && | ||
| 1281 | memcmp(addr, ffff_bssid, ETH_ALEN) != 0; | ||
| 1282 | if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) { | ||
| 1283 | devdbg(usbdev, "add_wpa_key: pairwise but bssid invalid (%pM)", | ||
| 1284 | addr); | ||
| 1107 | return -EINVAL; | 1285 | return -EINVAL; |
| 1286 | } | ||
| 1108 | 1287 | ||
| 1109 | devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index, | 1288 | devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index, |
| 1110 | !!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY), | 1289 | !!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY), |
| @@ -1118,7 +1297,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
| 1118 | ndis_key.length = cpu_to_le32(key_len); | 1297 | ndis_key.length = cpu_to_le32(key_len); |
| 1119 | ndis_key.index = cpu_to_le32(index) | flags; | 1298 | ndis_key.index = cpu_to_le32(index) | flags; |
| 1120 | 1299 | ||
| 1121 | if (alg == IW_ENCODE_ALG_TKIP && key_len == 32) { | 1300 | if (cipher == WLAN_CIPHER_SUITE_TKIP && key_len == 32) { |
| 1122 | /* wpa_supplicant gives us the Michael MIC RX/TX keys in | 1301 | /* wpa_supplicant gives us the Michael MIC RX/TX keys in |
| 1123 | * different order than NDIS spec, so swap the order here. */ | 1302 | * different order than NDIS spec, so swap the order here. */ |
| 1124 | memcpy(ndis_key.material, key, 16); | 1303 | memcpy(ndis_key.material, key, 16); |
| @@ -1132,7 +1311,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
| 1132 | 1311 | ||
| 1133 | if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) { | 1312 | if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) { |
| 1134 | /* pairwise key */ | 1313 | /* pairwise key */ |
| 1135 | memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN); | 1314 | memcpy(ndis_key.bssid, addr, ETH_ALEN); |
| 1136 | } else { | 1315 | } else { |
| 1137 | /* group key */ | 1316 | /* group key */ |
| 1138 | if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) | 1317 | if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) |
| @@ -1147,8 +1326,14 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
| 1147 | if (ret != 0) | 1326 | if (ret != 0) |
| 1148 | return ret; | 1327 | return ret; |
| 1149 | 1328 | ||
| 1150 | priv->encr_key_len[index] = key_len; | 1329 | memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index])); |
| 1151 | priv->encr_key_wpa[index] = 1; | 1330 | priv->encr_keys[index].len = key_len; |
| 1331 | priv->encr_keys[index].cipher = cipher; | ||
| 1332 | memcpy(&priv->encr_keys[index].material, key, key_len); | ||
| 1333 | if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) | ||
| 1334 | memcpy(&priv->encr_keys[index].bssid, ndis_key.bssid, ETH_ALEN); | ||
| 1335 | else | ||
| 1336 | memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN); | ||
| 1152 | 1337 | ||
| 1153 | if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY) | 1338 | if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY) |
| 1154 | priv->encr_tx_key_index = index; | 1339 | priv->encr_tx_key_index = index; |
| @@ -1157,25 +1342,74 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
| 1157 | } | 1342 | } |
| 1158 | 1343 | ||
| 1159 | 1344 | ||
| 1345 | static int restore_key(struct usbnet *usbdev, int key_idx) | ||
| 1346 | { | ||
| 1347 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
| 1348 | struct rndis_wlan_encr_key key; | ||
| 1349 | int flags; | ||
| 1350 | |||
| 1351 | key = priv->encr_keys[key_idx]; | ||
| 1352 | |||
| 1353 | devdbg(usbdev, "restore_key: %i:%s:%i", key_idx, | ||
| 1354 | is_wpa_key(priv, key_idx) ? "wpa" : "wep", | ||
| 1355 | key.len); | ||
| 1356 | |||
| 1357 | if (key.len == 0) | ||
| 1358 | return 0; | ||
| 1359 | |||
| 1360 | if (is_wpa_key(priv, key_idx)) { | ||
| 1361 | flags = 0; | ||
| 1362 | |||
| 1363 | /*if (priv->encr_tx_key_index == key_idx) | ||
| 1364 | flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;*/ | ||
| 1365 | |||
| 1366 | if (memcmp(key.bssid, zero_bssid, ETH_ALEN) != 0 && | ||
| 1367 | memcmp(key.bssid, ffff_bssid, ETH_ALEN) != 0) | ||
| 1368 | flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY; | ||
| 1369 | |||
| 1370 | return add_wpa_key(usbdev, key.material, key.len, key_idx, | ||
| 1371 | key.bssid, NULL, key.cipher, flags); | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | return add_wep_key(usbdev, key.material, key.len, key_idx); | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | |||
| 1378 | static void restore_keys(struct usbnet *usbdev) | ||
| 1379 | { | ||
| 1380 | int i; | ||
| 1381 | |||
| 1382 | for (i = 0; i < 4; i++) | ||
| 1383 | restore_key(usbdev, i); | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | |||
| 1387 | static void clear_key(struct rndis_wlan_private *priv, int idx) | ||
| 1388 | { | ||
| 1389 | memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx])); | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | |||
| 1160 | /* remove_key is for both wep and wpa */ | 1393 | /* remove_key is for both wep and wpa */ |
| 1161 | static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) | 1394 | static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) |
| 1162 | { | 1395 | { |
| 1163 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1396 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
| 1164 | struct ndis_80211_remove_key remove_key; | 1397 | struct ndis_80211_remove_key remove_key; |
| 1165 | __le32 keyindex; | 1398 | __le32 keyindex; |
| 1399 | bool is_wpa; | ||
| 1166 | int ret; | 1400 | int ret; |
| 1167 | 1401 | ||
| 1168 | if (priv->encr_key_len[index] == 0) | 1402 | if (priv->encr_keys[index].len == 0) |
| 1169 | return 0; | 1403 | return 0; |
| 1170 | 1404 | ||
| 1171 | priv->encr_key_len[index] = 0; | 1405 | is_wpa = is_wpa_key(priv, index); |
| 1172 | priv->encr_key_wpa[index] = 0; | 1406 | |
| 1173 | memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index])); | 1407 | devdbg(usbdev, "remove_key: %i:%s:%i", index, is_wpa ? "wpa" : "wep", |
| 1408 | priv->encr_keys[index].len); | ||
| 1409 | |||
| 1410 | clear_key(priv, index); | ||
| 1174 | 1411 | ||
| 1175 | if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP || | 1412 | if (is_wpa) { |
| 1176 | priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP || | ||
| 1177 | priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP || | ||
| 1178 | priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) { | ||
| 1179 | remove_key.size = cpu_to_le32(sizeof(remove_key)); | 1413 | remove_key.size = cpu_to_le32(sizeof(remove_key)); |
| 1180 | remove_key.index = cpu_to_le32(index); | 1414 | remove_key.index = cpu_to_le32(index); |
| 1181 | if (bssid) { | 1415 | if (bssid) { |
| @@ -1484,6 +1718,9 @@ static void rndis_get_scan_results(struct work_struct *work) | |||
| 1484 | 1718 | ||
| 1485 | devdbg(usbdev, "get_scan_results"); | 1719 | devdbg(usbdev, "get_scan_results"); |
| 1486 | 1720 | ||
| 1721 | if (!priv->scan_request) | ||
| 1722 | return; | ||
| 1723 | |||
| 1487 | ret = rndis_check_bssid_list(usbdev); | 1724 | ret = rndis_check_bssid_list(usbdev); |
| 1488 | 1725 | ||
| 1489 | cfg80211_scan_done(priv->scan_request, ret < 0); | 1726 | cfg80211_scan_done(priv->scan_request, ret < 0); |
| @@ -1716,8 +1953,9 @@ static int rndis_iw_set_encode(struct net_device *dev, | |||
| 1716 | { | 1953 | { |
| 1717 | struct usbnet *usbdev = netdev_priv(dev); | 1954 | struct usbnet *usbdev = netdev_priv(dev); |
| 1718 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1955 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
| 1956 | struct rndis_wlan_encr_key key; | ||
| 1719 | int ret, index, key_len; | 1957 | int ret, index, key_len; |
| 1720 | u8 *key; | 1958 | u8 *keybuf; |
| 1721 | 1959 | ||
| 1722 | index = (wrqu->encoding.flags & IW_ENCODE_INDEX); | 1960 | index = (wrqu->encoding.flags & IW_ENCODE_INDEX); |
| 1723 | 1961 | ||
| @@ -1752,17 +1990,18 @@ static int rndis_iw_set_encode(struct net_device *dev, | |||
| 1752 | 1990 | ||
| 1753 | if (wrqu->data.length > 0) { | 1991 | if (wrqu->data.length > 0) { |
| 1754 | key_len = wrqu->data.length; | 1992 | key_len = wrqu->data.length; |
| 1755 | key = extra; | 1993 | keybuf = extra; |
| 1756 | } else { | 1994 | } else { |
| 1757 | /* must be set as tx key */ | 1995 | /* must be set as tx key */ |
| 1758 | if (priv->encr_key_len[index] == 0) | 1996 | if (priv->encr_keys[index].len == 0) |
| 1759 | return -EINVAL; | 1997 | return -EINVAL; |
| 1760 | key_len = priv->encr_key_len[index]; | ||
| 1761 | key = priv->encr_keys[index]; | 1998 | key = priv->encr_keys[index]; |
| 1999 | key_len = key.len; | ||
| 2000 | keybuf = key.material; | ||
| 1762 | priv->encr_tx_key_index = index; | 2001 | priv->encr_tx_key_index = index; |
| 1763 | } | 2002 | } |
| 1764 | 2003 | ||
| 1765 | if (add_wep_key(usbdev, key, key_len, index) != 0) | 2004 | if (add_wep_key(usbdev, keybuf, key_len, index) != 0) |
| 1766 | return -EINVAL; | 2005 | return -EINVAL; |
| 1767 | 2006 | ||
| 1768 | if (index == priv->encr_tx_key_index) | 2007 | if (index == priv->encr_tx_key_index) |
| @@ -1779,7 +2018,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, | |||
| 1779 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 2018 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
| 1780 | struct usbnet *usbdev = netdev_priv(dev); | 2019 | struct usbnet *usbdev = netdev_priv(dev); |
| 1781 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2020 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
| 1782 | int keyidx, flags; | 2021 | int keyidx, flags, cipher; |
| 1783 | 2022 | ||
| 1784 | keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; | 2023 | keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; |
| 1785 | 2024 | ||
| @@ -1789,8 +2028,10 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, | |||
| 1789 | else | 2028 | else |
| 1790 | keyidx = priv->encr_tx_key_index; | 2029 | keyidx = priv->encr_tx_key_index; |
| 1791 | 2030 | ||
| 1792 | if (keyidx < 0 || keyidx >= 4) | 2031 | if (keyidx < 0 || keyidx >= 4) { |
| 2032 | devwarn(usbdev, "encryption index out of range (%u)", keyidx); | ||
| 1793 | return -EINVAL; | 2033 | return -EINVAL; |
| 2034 | } | ||
| 1794 | 2035 | ||
| 1795 | if (ext->alg == WPA_ALG_WEP) { | 2036 | if (ext->alg == WPA_ALG_WEP) { |
| 1796 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) | 2037 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) |
| @@ -1798,10 +2039,19 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, | |||
| 1798 | return add_wep_key(usbdev, ext->key, ext->key_len, keyidx); | 2039 | return add_wep_key(usbdev, ext->key, ext->key_len, keyidx); |
| 1799 | } | 2040 | } |
| 1800 | 2041 | ||
| 2042 | cipher = -1; | ||
| 2043 | if (ext->alg == IW_ENCODE_ALG_TKIP) | ||
| 2044 | cipher = WLAN_CIPHER_SUITE_TKIP; | ||
| 2045 | else if (ext->alg == IW_ENCODE_ALG_CCMP) | ||
| 2046 | cipher = WLAN_CIPHER_SUITE_CCMP; | ||
| 2047 | |||
| 1801 | if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) || | 2048 | if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) || |
| 1802 | ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) | 2049 | ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) |
| 1803 | return remove_key(usbdev, keyidx, NULL); | 2050 | return remove_key(usbdev, keyidx, NULL); |
| 1804 | 2051 | ||
| 2052 | if (cipher == -1) | ||
| 2053 | return -EOPNOTSUPP; | ||
| 2054 | |||
| 1805 | flags = 0; | 2055 | flags = 0; |
| 1806 | if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) | 2056 | if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) |
| 1807 | flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ; | 2057 | flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ; |
| @@ -1810,8 +2060,9 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, | |||
| 1810 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) | 2060 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) |
| 1811 | flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY; | 2061 | flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY; |
| 1812 | 2062 | ||
| 1813 | return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr, | 2063 | return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, |
| 1814 | ext->rx_seq, ext->alg, flags); | 2064 | (u8 *)&ext->addr.sa_data, ext->rx_seq, cipher, |
| 2065 | flags); | ||
| 1815 | } | 2066 | } |
| 1816 | 2067 | ||
| 1817 | 2068 | ||
| @@ -2104,13 +2355,216 @@ static void rndis_wlan_set_multicast_list(struct net_device *dev) | |||
| 2104 | queue_work(priv->workqueue, &priv->work); | 2355 | queue_work(priv->workqueue, &priv->work); |
| 2105 | } | 2356 | } |
| 2106 | 2357 | ||
| 2107 | static void rndis_wlan_link_change(struct usbnet *usbdev, int state) | 2358 | |
| 2359 | static void rndis_wlan_auth_indication(struct usbnet *usbdev, | ||
| 2360 | struct ndis_80211_status_indication *indication, | ||
| 2361 | int len) | ||
| 2362 | { | ||
| 2363 | u8 *buf; | ||
| 2364 | const char *type; | ||
| 2365 | int flags, buflen; | ||
| 2366 | bool pairwise_error, group_error; | ||
| 2367 | struct ndis_80211_auth_request *auth_req; | ||
| 2368 | |||
| 2369 | /* must have at least one array entry */ | ||
| 2370 | if (len < offsetof(struct ndis_80211_status_indication, u) + | ||
| 2371 | sizeof(struct ndis_80211_auth_request)) { | ||
| 2372 | devinfo(usbdev, "authentication indication: " | ||
| 2373 | "too short message (%i)", len); | ||
| 2374 | return; | ||
| 2375 | } | ||
| 2376 | |||
| 2377 | buf = (void *)&indication->u.auth_request[0]; | ||
| 2378 | buflen = len - offsetof(struct ndis_80211_status_indication, u); | ||
| 2379 | |||
| 2380 | while (buflen >= sizeof(*auth_req)) { | ||
| 2381 | auth_req = (void *)buf; | ||
| 2382 | type = "unknown"; | ||
| 2383 | flags = le32_to_cpu(auth_req->flags); | ||
| 2384 | pairwise_error = false; | ||
| 2385 | group_error = false; | ||
| 2386 | |||
| 2387 | if (flags & 0x1) | ||
| 2388 | type = "reauth request"; | ||
| 2389 | if (flags & 0x2) | ||
| 2390 | type = "key update request"; | ||
| 2391 | if (flags & 0x6) { | ||
| 2392 | pairwise_error = true; | ||
| 2393 | type = "pairwise_error"; | ||
| 2394 | } | ||
| 2395 | if (flags & 0xe) { | ||
| 2396 | group_error = true; | ||
| 2397 | type = "group_error"; | ||
| 2398 | } | ||
| 2399 | |||
| 2400 | devinfo(usbdev, "authentication indication: %s (0x%08x)", type, | ||
| 2401 | le32_to_cpu(auth_req->flags)); | ||
| 2402 | |||
| 2403 | if (pairwise_error || group_error) { | ||
| 2404 | union iwreq_data wrqu; | ||
| 2405 | struct iw_michaelmicfailure micfailure; | ||
| 2406 | |||
| 2407 | memset(&micfailure, 0, sizeof(micfailure)); | ||
| 2408 | if (pairwise_error) | ||
| 2409 | micfailure.flags |= IW_MICFAILURE_PAIRWISE; | ||
| 2410 | if (group_error) | ||
| 2411 | micfailure.flags |= IW_MICFAILURE_GROUP; | ||
| 2412 | |||
| 2413 | memcpy(micfailure.src_addr.sa_data, auth_req->bssid, | ||
| 2414 | ETH_ALEN); | ||
| 2415 | |||
| 2416 | memset(&wrqu, 0, sizeof(wrqu)); | ||
| 2417 | wrqu.data.length = sizeof(micfailure); | ||
| 2418 | wireless_send_event(usbdev->net, IWEVMICHAELMICFAILURE, | ||
| 2419 | &wrqu, (u8 *)&micfailure); | ||
| 2420 | } | ||
| 2421 | |||
| 2422 | buflen -= le32_to_cpu(auth_req->length); | ||
| 2423 | buf += le32_to_cpu(auth_req->length); | ||
| 2424 | } | ||
| 2425 | } | ||
| 2426 | |||
| 2427 | static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev, | ||
| 2428 | struct ndis_80211_status_indication *indication, | ||
| 2429 | int len) | ||
| 2430 | { | ||
| 2431 | struct ndis_80211_pmkid_cand_list *cand_list; | ||
| 2432 | int list_len, expected_len, i; | ||
| 2433 | |||
| 2434 | if (len < offsetof(struct ndis_80211_status_indication, u) + | ||
| 2435 | sizeof(struct ndis_80211_pmkid_cand_list)) { | ||
| 2436 | devinfo(usbdev, "pmkid candidate list indication: " | ||
| 2437 | "too short message (%i)", len); | ||
| 2438 | return; | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | list_len = le32_to_cpu(indication->u.cand_list.num_candidates) * | ||
| 2442 | sizeof(struct ndis_80211_pmkid_candidate); | ||
| 2443 | expected_len = sizeof(struct ndis_80211_pmkid_cand_list) + list_len + | ||
| 2444 | offsetof(struct ndis_80211_status_indication, u); | ||
| 2445 | |||
| 2446 | if (len < expected_len) { | ||
| 2447 | devinfo(usbdev, "pmkid candidate list indication: " | ||
| 2448 | "list larger than buffer (%i < %i)", | ||
| 2449 | len, expected_len); | ||
| 2450 | return; | ||
| 2451 | } | ||
| 2452 | |||
| 2453 | cand_list = &indication->u.cand_list; | ||
| 2454 | |||
| 2455 | devinfo(usbdev, "pmkid candidate list indication: " | ||
| 2456 | "version %i, candidates %i", | ||
| 2457 | le32_to_cpu(cand_list->version), | ||
| 2458 | le32_to_cpu(cand_list->num_candidates)); | ||
| 2459 | |||
| 2460 | if (le32_to_cpu(cand_list->version) != 1) | ||
| 2461 | return; | ||
| 2462 | |||
| 2463 | for (i = 0; i < le32_to_cpu(cand_list->num_candidates); i++) { | ||
| 2464 | struct iw_pmkid_cand pcand; | ||
| 2465 | union iwreq_data wrqu; | ||
| 2466 | struct ndis_80211_pmkid_candidate *cand = | ||
| 2467 | &cand_list->candidate_list[i]; | ||
| 2468 | |||
| 2469 | devdbg(usbdev, "cand[%i]: flags: 0x%08x, bssid: %pM", | ||
| 2470 | i, le32_to_cpu(cand->flags), cand->bssid); | ||
| 2471 | |||
| 2472 | memset(&pcand, 0, sizeof(pcand)); | ||
| 2473 | if (le32_to_cpu(cand->flags) & 0x01) | ||
| 2474 | pcand.flags |= IW_PMKID_CAND_PREAUTH; | ||
| 2475 | pcand.index = i; | ||
| 2476 | memcpy(pcand.bssid.sa_data, cand->bssid, ETH_ALEN); | ||
| 2477 | |||
| 2478 | memset(&wrqu, 0, sizeof(wrqu)); | ||
| 2479 | wrqu.data.length = sizeof(pcand); | ||
| 2480 | wireless_send_event(usbdev->net, IWEVPMKIDCAND, &wrqu, | ||
| 2481 | (u8 *)&pcand); | ||
| 2482 | } | ||
| 2483 | } | ||
| 2484 | |||
| 2485 | static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, | ||
| 2486 | struct rndis_indicate *msg, int buflen) | ||
| 2487 | { | ||
| 2488 | struct ndis_80211_status_indication *indication; | ||
| 2489 | int len, offset; | ||
| 2490 | |||
| 2491 | offset = offsetof(struct rndis_indicate, status) + | ||
| 2492 | le32_to_cpu(msg->offset); | ||
| 2493 | len = le32_to_cpu(msg->length); | ||
| 2494 | |||
| 2495 | if (len < 8) { | ||
| 2496 | devinfo(usbdev, "media specific indication, " | ||
| 2497 | "ignore too short message (%i < 8)", len); | ||
| 2498 | return; | ||
| 2499 | } | ||
| 2500 | |||
| 2501 | if (offset + len > buflen) { | ||
| 2502 | devinfo(usbdev, "media specific indication, " | ||
| 2503 | "too large to fit to buffer (%i > %i)", | ||
| 2504 | offset + len, buflen); | ||
| 2505 | return; | ||
| 2506 | } | ||
| 2507 | |||
| 2508 | indication = (void *)((u8 *)msg + offset); | ||
| 2509 | |||
| 2510 | switch (le32_to_cpu(indication->status_type)) { | ||
| 2511 | case NDIS_80211_STATUSTYPE_RADIOSTATE: | ||
| 2512 | devinfo(usbdev, "radio state indication: %i", | ||
| 2513 | le32_to_cpu(indication->u.radio_status)); | ||
| 2514 | return; | ||
| 2515 | |||
| 2516 | case NDIS_80211_STATUSTYPE_MEDIASTREAMMODE: | ||
| 2517 | devinfo(usbdev, "media stream mode indication: %i", | ||
| 2518 | le32_to_cpu(indication->u.media_stream_mode)); | ||
| 2519 | return; | ||
| 2520 | |||
| 2521 | case NDIS_80211_STATUSTYPE_AUTHENTICATION: | ||
| 2522 | rndis_wlan_auth_indication(usbdev, indication, len); | ||
| 2523 | return; | ||
| 2524 | |||
| 2525 | case NDIS_80211_STATUSTYPE_PMKID_CANDIDATELIST: | ||
| 2526 | rndis_wlan_pmkid_cand_list_indication(usbdev, indication, len); | ||
| 2527 | return; | ||
| 2528 | |||
| 2529 | default: | ||
| 2530 | devinfo(usbdev, "media specific indication: " | ||
| 2531 | "unknown status type 0x%08x", | ||
| 2532 | le32_to_cpu(indication->status_type)); | ||
| 2533 | } | ||
| 2534 | } | ||
| 2535 | |||
| 2536 | |||
| 2537 | static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen) | ||
| 2108 | { | 2538 | { |
| 2109 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2539 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
| 2540 | struct rndis_indicate *msg = ind; | ||
| 2110 | 2541 | ||
| 2111 | /* queue work to avoid recursive calls into rndis_command */ | 2542 | switch (msg->status) { |
| 2112 | set_bit(state ? WORK_LINK_UP : WORK_LINK_DOWN, &priv->work_pending); | 2543 | case RNDIS_STATUS_MEDIA_CONNECT: |
| 2113 | queue_work(priv->workqueue, &priv->work); | 2544 | devinfo(usbdev, "media connect"); |
| 2545 | |||
| 2546 | /* queue work to avoid recursive calls into rndis_command */ | ||
| 2547 | set_bit(WORK_LINK_UP, &priv->work_pending); | ||
| 2548 | queue_work(priv->workqueue, &priv->work); | ||
| 2549 | break; | ||
| 2550 | |||
| 2551 | case RNDIS_STATUS_MEDIA_DISCONNECT: | ||
| 2552 | devinfo(usbdev, "media disconnect"); | ||
| 2553 | |||
| 2554 | /* queue work to avoid recursive calls into rndis_command */ | ||
| 2555 | set_bit(WORK_LINK_DOWN, &priv->work_pending); | ||
| 2556 | queue_work(priv->workqueue, &priv->work); | ||
| 2557 | break; | ||
| 2558 | |||
| 2559 | case RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION: | ||
| 2560 | rndis_wlan_media_specific_indication(usbdev, msg, buflen); | ||
| 2561 | break; | ||
| 2562 | |||
| 2563 | default: | ||
| 2564 | devinfo(usbdev, "indication: 0x%08x", | ||
| 2565 | le32_to_cpu(msg->status)); | ||
| 2566 | break; | ||
| 2567 | } | ||
| 2114 | } | 2568 | } |
| 2115 | 2569 | ||
| 2116 | 2570 | ||
| @@ -2457,9 +2911,6 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) | |||
| 2457 | disassociate(usbdev, 1); | 2911 | disassociate(usbdev, 1); |
| 2458 | netif_carrier_off(usbdev->net); | 2912 | netif_carrier_off(usbdev->net); |
| 2459 | 2913 | ||
| 2460 | queue_delayed_work(priv->workqueue, &priv->stats_work, | ||
| 2461 | round_jiffies_relative(STATS_UPDATE_JIFFIES)); | ||
| 2462 | |||
| 2463 | return 0; | 2914 | return 0; |
| 2464 | 2915 | ||
| 2465 | fail: | 2916 | fail: |
| @@ -2499,21 +2950,61 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf) | |||
| 2499 | 2950 | ||
| 2500 | static int rndis_wlan_reset(struct usbnet *usbdev) | 2951 | static int rndis_wlan_reset(struct usbnet *usbdev) |
| 2501 | { | 2952 | { |
| 2953 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
| 2954 | int retval; | ||
| 2955 | |||
| 2502 | devdbg(usbdev, "rndis_wlan_reset"); | 2956 | devdbg(usbdev, "rndis_wlan_reset"); |
| 2957 | |||
| 2958 | retval = rndis_reset(usbdev); | ||
| 2959 | if (retval) | ||
| 2960 | devwarn(usbdev, "rndis_reset() failed: %d", retval); | ||
| 2961 | |||
| 2962 | /* rndis_reset cleared multicast list, so restore here. | ||
| 2963 | (set_multicast_list() also turns on current packet filter) */ | ||
| 2964 | set_multicast_list(usbdev); | ||
| 2965 | |||
| 2966 | queue_delayed_work(priv->workqueue, &priv->stats_work, | ||
| 2967 | round_jiffies_relative(STATS_UPDATE_JIFFIES)); | ||
| 2968 | |||
| 2503 | return deauthenticate(usbdev); | 2969 | return deauthenticate(usbdev); |
| 2504 | } | 2970 | } |
| 2505 | 2971 | ||
| 2506 | 2972 | ||
| 2507 | static int rndis_wlan_stop(struct usbnet *usbdev) | 2973 | static int rndis_wlan_stop(struct usbnet *usbdev) |
| 2508 | { | 2974 | { |
| 2975 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
| 2976 | int retval; | ||
| 2977 | __le32 filter; | ||
| 2978 | |||
| 2509 | devdbg(usbdev, "rndis_wlan_stop"); | 2979 | devdbg(usbdev, "rndis_wlan_stop"); |
| 2510 | return disassociate(usbdev, 0); | 2980 | |
| 2981 | retval = disassociate(usbdev, 0); | ||
| 2982 | |||
| 2983 | priv->work_pending = 0; | ||
| 2984 | cancel_delayed_work_sync(&priv->stats_work); | ||
| 2985 | cancel_delayed_work_sync(&priv->scan_work); | ||
| 2986 | cancel_work_sync(&priv->work); | ||
| 2987 | flush_workqueue(priv->workqueue); | ||
| 2988 | |||
| 2989 | if (priv->scan_request) { | ||
| 2990 | cfg80211_scan_done(priv->scan_request, true); | ||
| 2991 | priv->scan_request = NULL; | ||
| 2992 | } | ||
| 2993 | |||
| 2994 | /* Set current packet filter zero to block receiving data packets from | ||
| 2995 | device. */ | ||
| 2996 | filter = 0; | ||
| 2997 | rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter, | ||
| 2998 | sizeof(filter)); | ||
| 2999 | |||
| 3000 | return retval; | ||
| 2511 | } | 3001 | } |
| 2512 | 3002 | ||
| 2513 | 3003 | ||
| 2514 | static const struct driver_info bcm4320b_info = { | 3004 | static const struct driver_info bcm4320b_info = { |
| 2515 | .description = "Wireless RNDIS device, BCM4320b based", | 3005 | .description = "Wireless RNDIS device, BCM4320b based", |
| 2516 | .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, | 3006 | .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | |
| 3007 | FLAG_AVOID_UNLINK_URBS, | ||
| 2517 | .bind = rndis_wlan_bind, | 3008 | .bind = rndis_wlan_bind, |
| 2518 | .unbind = rndis_wlan_unbind, | 3009 | .unbind = rndis_wlan_unbind, |
| 2519 | .status = rndis_status, | 3010 | .status = rndis_status, |
| @@ -2522,12 +3013,13 @@ static const struct driver_info bcm4320b_info = { | |||
| 2522 | .reset = rndis_wlan_reset, | 3013 | .reset = rndis_wlan_reset, |
| 2523 | .stop = rndis_wlan_stop, | 3014 | .stop = rndis_wlan_stop, |
| 2524 | .early_init = bcm4320b_early_init, | 3015 | .early_init = bcm4320b_early_init, |
| 2525 | .link_change = rndis_wlan_link_change, | 3016 | .indication = rndis_wlan_indication, |
| 2526 | }; | 3017 | }; |
| 2527 | 3018 | ||
| 2528 | static const struct driver_info bcm4320a_info = { | 3019 | static const struct driver_info bcm4320a_info = { |
| 2529 | .description = "Wireless RNDIS device, BCM4320a based", | 3020 | .description = "Wireless RNDIS device, BCM4320a based", |
| 2530 | .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, | 3021 | .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | |
| 3022 | FLAG_AVOID_UNLINK_URBS, | ||
| 2531 | .bind = rndis_wlan_bind, | 3023 | .bind = rndis_wlan_bind, |
| 2532 | .unbind = rndis_wlan_unbind, | 3024 | .unbind = rndis_wlan_unbind, |
| 2533 | .status = rndis_status, | 3025 | .status = rndis_status, |
| @@ -2536,12 +3028,13 @@ static const struct driver_info bcm4320a_info = { | |||
| 2536 | .reset = rndis_wlan_reset, | 3028 | .reset = rndis_wlan_reset, |
| 2537 | .stop = rndis_wlan_stop, | 3029 | .stop = rndis_wlan_stop, |
| 2538 | .early_init = bcm4320a_early_init, | 3030 | .early_init = bcm4320a_early_init, |
| 2539 | .link_change = rndis_wlan_link_change, | 3031 | .indication = rndis_wlan_indication, |
| 2540 | }; | 3032 | }; |
| 2541 | 3033 | ||
| 2542 | static const struct driver_info rndis_wlan_info = { | 3034 | static const struct driver_info rndis_wlan_info = { |
| 2543 | .description = "Wireless RNDIS device", | 3035 | .description = "Wireless RNDIS device", |
| 2544 | .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, | 3036 | .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | |
| 3037 | FLAG_AVOID_UNLINK_URBS, | ||
| 2545 | .bind = rndis_wlan_bind, | 3038 | .bind = rndis_wlan_bind, |
| 2546 | .unbind = rndis_wlan_unbind, | 3039 | .unbind = rndis_wlan_unbind, |
| 2547 | .status = rndis_status, | 3040 | .status = rndis_status, |
| @@ -2550,7 +3043,7 @@ static const struct driver_info rndis_wlan_info = { | |||
| 2550 | .reset = rndis_wlan_reset, | 3043 | .reset = rndis_wlan_reset, |
| 2551 | .stop = rndis_wlan_stop, | 3044 | .stop = rndis_wlan_stop, |
| 2552 | .early_init = bcm4320a_early_init, | 3045 | .early_init = bcm4320a_early_init, |
| 2553 | .link_change = rndis_wlan_link_change, | 3046 | .indication = rndis_wlan_indication, |
| 2554 | }; | 3047 | }; |
| 2555 | 3048 | ||
| 2556 | /*-------------------------------------------------------------------------*/ | 3049 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index f970aa25326a..ed1f997e3521 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | menuconfig RT2X00 | 1 | menuconfig RT2X00 |
| 2 | tristate "Ralink driver support" | 2 | tristate "Ralink driver support" |
| 3 | depends on MAC80211 && WLAN_80211 && EXPERIMENTAL | 3 | depends on MAC80211 && WLAN_80211 |
| 4 | ---help--- | 4 | ---help--- |
| 5 | This will enable the experimental support for the Ralink drivers, | 5 | This will enable the support for the Ralink drivers, |
| 6 | developed in the rt2x00 project <http://rt2x00.serialmonkey.com>. | 6 | developed in the rt2x00 project <http://rt2x00.serialmonkey.com>. |
| 7 | 7 | ||
| 8 | These drivers make use of the mac80211 stack. | 8 | These drivers make use of the mac80211 stack. |
| @@ -79,14 +79,14 @@ config RT73USB | |||
| 79 | 79 | ||
| 80 | config RT2800USB | 80 | config RT2800USB |
| 81 | tristate "Ralink rt2800 (USB) support" | 81 | tristate "Ralink rt2800 (USB) support" |
| 82 | depends on USB | 82 | depends on USB && EXPERIMENTAL |
| 83 | select RT2X00_LIB_USB | 83 | select RT2X00_LIB_USB |
| 84 | select RT2X00_LIB_HT | 84 | select RT2X00_LIB_HT |
| 85 | select RT2X00_LIB_FIRMWARE | 85 | select RT2X00_LIB_FIRMWARE |
| 86 | select RT2X00_LIB_CRYPTO | 86 | select RT2X00_LIB_CRYPTO |
| 87 | select CRC_CCITT | 87 | select CRC_CCITT |
| 88 | ---help--- | 88 | ---help--- |
| 89 | This adds support for rt2800 wireless chipset family. | 89 | This adds experimental support for rt2800 wireless chipset family. |
| 90 | Supported chips: RT2770, RT2870 & RT3070. | 90 | Supported chips: RT2770, RT2870 & RT3070. |
| 91 | 91 | ||
| 92 | When compiled as a module, this driver will be called "rt2800usb.ko". | 92 | When compiled as a module, this driver will be called "rt2800usb.ko". |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 658a63bfb761..db54fcc94c8f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
| @@ -215,7 +215,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
| 215 | rt2x00lib_beacondone_iter, | 215 | rt2x00lib_beacondone_iter, |
| 216 | rt2x00dev); | 216 | rt2x00dev); |
| 217 | 217 | ||
| 218 | queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); | 218 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work); |
| 219 | } | 219 | } |
| 220 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); | 220 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); |
| 221 | 221 | ||
| @@ -893,6 +893,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
| 893 | rt2x00lib_disable_radio(rt2x00dev); | 893 | rt2x00lib_disable_radio(rt2x00dev); |
| 894 | 894 | ||
| 895 | /* | 895 | /* |
| 896 | * Stop all work. | ||
| 897 | */ | ||
| 898 | cancel_work_sync(&rt2x00dev->filter_work); | ||
| 899 | cancel_work_sync(&rt2x00dev->intf_work); | ||
| 900 | |||
| 901 | /* | ||
| 896 | * Uninitialize device. | 902 | * Uninitialize device. |
| 897 | */ | 903 | */ |
| 898 | rt2x00lib_uninitialize(rt2x00dev); | 904 | rt2x00lib_uninitialize(rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 79915687e744..917831689ccd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
| @@ -351,8 +351,8 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) | |||
| 351 | 351 | ||
| 352 | rt2x00link_reset_tuner(rt2x00dev, false); | 352 | rt2x00link_reset_tuner(rt2x00dev, false); |
| 353 | 353 | ||
| 354 | queue_delayed_work(rt2x00dev->hw->workqueue, | 354 | ieee80211_queue_delayed_work(rt2x00dev->hw, |
| 355 | &link->work, LINK_TUNE_INTERVAL); | 355 | &link->work, LINK_TUNE_INTERVAL); |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) | 358 | void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) |
| @@ -461,8 +461,8 @@ static void rt2x00link_tuner(struct work_struct *work) | |||
| 461 | * Increase tuner counter, and reschedule the next link tuner run. | 461 | * Increase tuner counter, and reschedule the next link tuner run. |
| 462 | */ | 462 | */ |
| 463 | link->count++; | 463 | link->count++; |
| 464 | queue_delayed_work(rt2x00dev->hw->workqueue, | 464 | ieee80211_queue_delayed_work(rt2x00dev->hw, |
| 465 | &link->work, LINK_TUNE_INTERVAL); | 465 | &link->work, LINK_TUNE_INTERVAL); |
| 466 | } | 466 | } |
| 467 | 467 | ||
| 468 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) | 468 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 7de1a2cdcf8c..81febdfd6639 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
| @@ -431,10 +431,20 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
| 431 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) | 431 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) |
| 432 | rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); | 432 | rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); |
| 433 | else | 433 | else |
| 434 | queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); | 434 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work); |
| 435 | } | 435 | } |
| 436 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); | 436 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); |
| 437 | 437 | ||
| 438 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
| 439 | bool set) | ||
| 440 | { | ||
| 441 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
| 442 | |||
| 443 | rt2x00lib_beacondone(rt2x00dev); | ||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); | ||
| 447 | |||
| 438 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | 448 | #ifdef CONFIG_RT2X00_LIB_CRYPTO |
| 439 | static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) | 449 | static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) |
| 440 | { | 450 | { |
| @@ -454,16 +464,6 @@ static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) | |||
| 454 | sizeof(crypto->rx_mic)); | 464 | sizeof(crypto->rx_mic)); |
| 455 | } | 465 | } |
| 456 | 466 | ||
| 457 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
| 458 | bool set) | ||
| 459 | { | ||
| 460 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
| 461 | |||
| 462 | rt2x00lib_beacondone(rt2x00dev); | ||
| 463 | return 0; | ||
| 464 | } | ||
| 465 | EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); | ||
| 466 | |||
| 467 | int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 467 | int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
| 468 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | 468 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
| 469 | struct ieee80211_key_conf *key) | 469 | struct ieee80211_key_conf *key) |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index fb95b8cc4fe9..e20dd7431f21 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
| @@ -2601,6 +2601,11 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
| 2601 | int retval; | 2601 | int retval; |
| 2602 | 2602 | ||
| 2603 | /* | 2603 | /* |
| 2604 | * Disable power saving. | ||
| 2605 | */ | ||
| 2606 | rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); | ||
| 2607 | |||
| 2608 | /* | ||
| 2604 | * Allocate eeprom data. | 2609 | * Allocate eeprom data. |
| 2605 | */ | 2610 | */ |
| 2606 | retval = rt61pci_validate_eeprom(rt2x00dev); | 2611 | retval = rt61pci_validate_eeprom(rt2x00dev); |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index c9b9dbe584c6..53f57dc52226 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
| @@ -220,7 +220,7 @@ static void rtl8187_tx_cb(struct urb *urb) | |||
| 220 | * reading a register in the device. We are in interrupt mode | 220 | * reading a register in the device. We are in interrupt mode |
| 221 | * here, thus queue the skb and finish on a work queue. */ | 221 | * here, thus queue the skb and finish on a work queue. */ |
| 222 | skb_queue_tail(&priv->b_tx_status.queue, skb); | 222 | skb_queue_tail(&priv->b_tx_status.queue, skb); |
| 223 | queue_delayed_work(hw->workqueue, &priv->work, 0); | 223 | ieee80211_queue_delayed_work(hw, &priv->work, 0); |
| 224 | } | 224 | } |
| 225 | } | 225 | } |
| 226 | 226 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index cf9f899fe0e6..a6cfb7e77994 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c | |||
| @@ -108,11 +108,11 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, | |||
| 108 | struct rtl8187_priv *priv = hw->priv; | 108 | struct rtl8187_priv *priv = hw->priv; |
| 109 | 109 | ||
| 110 | if (brightness == LED_OFF) { | 110 | if (brightness == LED_OFF) { |
| 111 | queue_delayed_work(hw->workqueue, &priv->led_off, 0); | 111 | ieee80211_queue_delayed_work(hw, &priv->led_off, 0); |
| 112 | /* The LED is off for 1/20 sec so that it just blinks. */ | 112 | /* The LED is off for 1/20 sec so that it just blinks. */ |
| 113 | queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20); | 113 | ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20); |
| 114 | } else | 114 | } else |
| 115 | queue_delayed_work(hw->workqueue, &priv->led_on, 0); | 115 | ieee80211_queue_delayed_work(hw, &priv->led_on, 0); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static int rtl8187_register_led(struct ieee80211_hw *dev, | 118 | static int rtl8187_register_led(struct ieee80211_hw *dev, |
| @@ -193,7 +193,7 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid) | |||
| 193 | err = rtl8187_register_led(dev, &priv->led_rx, name, | 193 | err = rtl8187_register_led(dev, &priv->led_rx, name, |
| 194 | ieee80211_get_rx_led_name(dev), ledpin); | 194 | ieee80211_get_rx_led_name(dev), ledpin); |
| 195 | if (!err) { | 195 | if (!err) { |
| 196 | queue_delayed_work(dev->workqueue, &priv->led_on, 0); | 196 | ieee80211_queue_delayed_work(dev, &priv->led_on, 0); |
| 197 | return; | 197 | return; |
| 198 | } | 198 | } |
| 199 | /* registration of RX LED failed - unregister TX */ | 199 | /* registration of RX LED failed - unregister TX */ |
| @@ -209,7 +209,7 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev) | |||
| 209 | struct rtl8187_priv *priv = dev->priv; | 209 | struct rtl8187_priv *priv = dev->priv; |
| 210 | 210 | ||
| 211 | /* turn the LED off before exiting */ | 211 | /* turn the LED off before exiting */ |
| 212 | queue_delayed_work(dev->workqueue, &priv->led_off, 0); | 212 | ieee80211_queue_delayed_work(dev, &priv->led_off, 0); |
| 213 | cancel_delayed_work_sync(&priv->led_off); | 213 | cancel_delayed_work_sync(&priv->led_off); |
| 214 | cancel_delayed_work_sync(&priv->led_on); | 214 | cancel_delayed_work_sync(&priv->led_on); |
| 215 | rtl8187_unregister_led(&priv->led_rx); | 215 | rtl8187_unregister_led(&priv->led_rx); |
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 73300c226f67..ef2cb20e96ad 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c | |||
| @@ -1550,9 +1550,12 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1550 | 1550 | ||
| 1551 | if (time_after(jiffies, strip_info->pps_timer + HZ)) { | 1551 | if (time_after(jiffies, strip_info->pps_timer + HZ)) { |
| 1552 | unsigned long t = jiffies - strip_info->pps_timer; | 1552 | unsigned long t = jiffies - strip_info->pps_timer; |
| 1553 | unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t; | 1553 | unsigned long rx_pps_count = |
| 1554 | unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t; | 1554 | DIV_ROUND_CLOSEST(strip_info->rx_pps_count*HZ*8, t); |
| 1555 | unsigned long sx_pps_count = (strip_info->sx_pps_count * HZ * 8 + t / 2) / t; | 1555 | unsigned long tx_pps_count = |
| 1556 | DIV_ROUND_CLOSEST(strip_info->tx_pps_count*HZ*8, t); | ||
| 1557 | unsigned long sx_pps_count = | ||
| 1558 | DIV_ROUND_CLOSEST(strip_info->sx_pps_count*HZ*8, t); | ||
| 1556 | 1559 | ||
| 1557 | strip_info->pps_timer = jiffies; | 1560 | strip_info->pps_timer = jiffies; |
| 1558 | strip_info->rx_pps_count = 0; | 1561 | strip_info->rx_pps_count = 0; |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 9600b72495da..54abdd0c0045 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
| @@ -698,7 +698,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
| 698 | && !mac->pass_ctrl) | 698 | && !mac->pass_ctrl) |
| 699 | return 0; | 699 | return 0; |
| 700 | 700 | ||
| 701 | fc = *(__le16 *)buffer; | 701 | fc = get_unaligned((__le16*)buffer); |
| 702 | need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc); | 702 | need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc); |
| 703 | 703 | ||
| 704 | skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); | 704 | skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); |
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 10202903141a..21ca51bf4dd2 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h | |||
| @@ -47,6 +47,7 @@ enum rfkill_type { | |||
| 47 | RFKILL_TYPE_UWB, | 47 | RFKILL_TYPE_UWB, |
| 48 | RFKILL_TYPE_WIMAX, | 48 | RFKILL_TYPE_WIMAX, |
| 49 | RFKILL_TYPE_WWAN, | 49 | RFKILL_TYPE_WWAN, |
| 50 | RFKILL_TYPE_GPS, | ||
| 50 | NUM_RFKILL_TYPES, | 51 | NUM_RFKILL_TYPES, |
| 51 | }; | 52 | }; |
| 52 | 53 | ||
diff --git a/include/linux/usb/rndis_host.h b/include/linux/usb/rndis_host.h index 37836b937d97..1ef1ebc2b04f 100644 --- a/include/linux/usb/rndis_host.h +++ b/include/linux/usb/rndis_host.h | |||
| @@ -70,12 +70,13 @@ struct rndis_msg_hdr { | |||
| 70 | #define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION) | 70 | #define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION) |
| 71 | 71 | ||
| 72 | /* codes for "status" field of completion messages */ | 72 | /* codes for "status" field of completion messages */ |
| 73 | #define RNDIS_STATUS_SUCCESS cpu_to_le32(0x00000000) | 73 | #define RNDIS_STATUS_SUCCESS cpu_to_le32(0x00000000) |
| 74 | #define RNDIS_STATUS_FAILURE cpu_to_le32(0xc0000001) | 74 | #define RNDIS_STATUS_FAILURE cpu_to_le32(0xc0000001) |
| 75 | #define RNDIS_STATUS_INVALID_DATA cpu_to_le32(0xc0010015) | 75 | #define RNDIS_STATUS_INVALID_DATA cpu_to_le32(0xc0010015) |
| 76 | #define RNDIS_STATUS_NOT_SUPPORTED cpu_to_le32(0xc00000bb) | 76 | #define RNDIS_STATUS_NOT_SUPPORTED cpu_to_le32(0xc00000bb) |
| 77 | #define RNDIS_STATUS_MEDIA_CONNECT cpu_to_le32(0x4001000b) | 77 | #define RNDIS_STATUS_MEDIA_CONNECT cpu_to_le32(0x4001000b) |
| 78 | #define RNDIS_STATUS_MEDIA_DISCONNECT cpu_to_le32(0x4001000c) | 78 | #define RNDIS_STATUS_MEDIA_DISCONNECT cpu_to_le32(0x4001000c) |
| 79 | #define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION cpu_to_le32(0x40010012) | ||
| 79 | 80 | ||
| 80 | /* codes for OID_GEN_PHYSICAL_MEDIUM */ | 81 | /* codes for OID_GEN_PHYSICAL_MEDIUM */ |
| 81 | #define RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED cpu_to_le32(0x00000000) | 82 | #define RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED cpu_to_le32(0x00000000) |
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 7c17b2efba86..de8b4b18961b 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h | |||
| @@ -86,6 +86,7 @@ struct driver_info { | |||
| 86 | 86 | ||
| 87 | #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ | 87 | #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ |
| 88 | #define FLAG_WLAN 0x0080 /* use "wlan%d" names */ | 88 | #define FLAG_WLAN 0x0080 /* use "wlan%d" names */ |
| 89 | #define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */ | ||
| 89 | 90 | ||
| 90 | 91 | ||
| 91 | /* init device ... can sleep, or cause probe() failure */ | 92 | /* init device ... can sleep, or cause probe() failure */ |
| @@ -121,9 +122,8 @@ struct driver_info { | |||
| 121 | * right after minidriver have initialized hardware. */ | 122 | * right after minidriver have initialized hardware. */ |
| 122 | int (*early_init)(struct usbnet *dev); | 123 | int (*early_init)(struct usbnet *dev); |
| 123 | 124 | ||
| 124 | /* called by minidriver when link state changes, state: 0=disconnect, | 125 | /* called by minidriver when receiving indication */ |
| 125 | * 1=connect */ | 126 | void (*indication)(struct usbnet *dev, void *ind, int indlen); |
| 126 | void (*link_change)(struct usbnet *dev, int state); | ||
| 127 | 127 | ||
| 128 | /* for new devices, use the descriptor-reading code instead */ | 128 | /* for new devices, use the descriptor-reading code instead */ |
| 129 | int in; /* rx endpoint */ | 129 | int in; /* rx endpoint */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e1b92358242b..fa729979de88 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
| @@ -1514,20 +1514,6 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb); | |||
| 1514 | extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2); | 1514 | extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2); |
| 1515 | 1515 | ||
| 1516 | /** | 1516 | /** |
| 1517 | * regulatory_hint_11d - hints a country IE as a regulatory domain | ||
| 1518 | * @wiphy: the wireless device giving the hint (used only for reporting | ||
| 1519 | * conflicts) | ||
| 1520 | * @country_ie: pointer to the country IE | ||
| 1521 | * @country_ie_len: length of the country IE | ||
| 1522 | * | ||
| 1523 | * We will intersect the rd with the what CRDA tells us should apply | ||
| 1524 | * for the alpha2 this country IE belongs to, this prevents APs from | ||
| 1525 | * sending us incorrect or outdated information against a country. | ||
| 1526 | */ | ||
| 1527 | extern void regulatory_hint_11d(struct wiphy *wiphy, | ||
| 1528 | u8 *country_ie, | ||
| 1529 | u8 country_ie_len); | ||
| 1530 | /** | ||
| 1531 | * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain | 1517 | * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain |
| 1532 | * @wiphy: the wireless device we want to process the regulatory domain on | 1518 | * @wiphy: the wireless device we want to process the regulatory domain on |
| 1533 | * @regd: the custom regulatory domain to use for this wiphy | 1519 | * @regd: the custom regulatory domain to use for this wiphy |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d4e09a06b4a2..e2fb5767e1fa 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
| @@ -73,6 +73,21 @@ | |||
| 73 | */ | 73 | */ |
| 74 | 74 | ||
| 75 | /** | 75 | /** |
| 76 | * DOC: mac80211 workqueue | ||
| 77 | * | ||
| 78 | * mac80211 provides its own workqueue for drivers and internal mac80211 use. | ||
| 79 | * The workqueue is a single threaded workqueue and can only be accessed by | ||
| 80 | * helpers for sanity checking. Drivers must ensure all work added onto the | ||
| 81 | * mac80211 workqueue should be cancelled on the driver stop() callback. | ||
| 82 | * | ||
| 83 | * mac80211 will flushed the workqueue upon interface removal and during | ||
| 84 | * suspend. | ||
| 85 | * | ||
| 86 | * All work performed on the mac80211 workqueue must not acquire the RTNL lock. | ||
| 87 | * | ||
| 88 | */ | ||
| 89 | |||
| 90 | /** | ||
| 76 | * enum ieee80211_max_queues - maximum number of queues | 91 | * enum ieee80211_max_queues - maximum number of queues |
| 77 | * | 92 | * |
| 78 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. | 93 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. |
| @@ -913,12 +928,6 @@ enum ieee80211_hw_flags { | |||
| 913 | * | 928 | * |
| 914 | * @conf: &struct ieee80211_conf, device configuration, don't use. | 929 | * @conf: &struct ieee80211_conf, device configuration, don't use. |
| 915 | * | 930 | * |
| 916 | * @workqueue: single threaded workqueue available for driver use, | ||
| 917 | * allocated by mac80211 on registration and flushed when an | ||
| 918 | * interface is removed. | ||
| 919 | * NOTICE: All work performed on this workqueue must not | ||
| 920 | * acquire the RTNL lock. | ||
| 921 | * | ||
| 922 | * @priv: pointer to private area that was allocated for driver use | 931 | * @priv: pointer to private area that was allocated for driver use |
| 923 | * along with this structure. | 932 | * along with this structure. |
| 924 | * | 933 | * |
| @@ -954,7 +963,6 @@ enum ieee80211_hw_flags { | |||
| 954 | struct ieee80211_hw { | 963 | struct ieee80211_hw { |
| 955 | struct ieee80211_conf conf; | 964 | struct ieee80211_conf conf; |
| 956 | struct wiphy *wiphy; | 965 | struct wiphy *wiphy; |
| 957 | struct workqueue_struct *workqueue; | ||
| 958 | const char *rate_control_algorithm; | 966 | const char *rate_control_algorithm; |
| 959 | void *priv; | 967 | void *priv; |
| 960 | u32 flags; | 968 | u32 flags; |
| @@ -1236,10 +1244,13 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, | |||
| 1236 | * mac80211 needs to do and the amount of CPU wakeups, so you should | 1244 | * mac80211 needs to do and the amount of CPU wakeups, so you should |
| 1237 | * honour this flag if possible. | 1245 | * honour this flag if possible. |
| 1238 | * | 1246 | * |
| 1239 | * @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then | 1247 | * @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS |
| 1240 | * only those addressed to this station | 1248 | * is not set then only those addressed to this station. |
| 1241 | * | 1249 | * |
| 1242 | * @FIF_OTHER_BSS: pass frames destined to other BSSes | 1250 | * @FIF_OTHER_BSS: pass frames destined to other BSSes |
| 1251 | * | ||
| 1252 | * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only | ||
| 1253 | * those addressed to this station. | ||
| 1243 | */ | 1254 | */ |
| 1244 | enum ieee80211_filter_flags { | 1255 | enum ieee80211_filter_flags { |
| 1245 | FIF_PROMISC_IN_BSS = 1<<0, | 1256 | FIF_PROMISC_IN_BSS = 1<<0, |
| @@ -1249,6 +1260,7 @@ enum ieee80211_filter_flags { | |||
| 1249 | FIF_BCN_PRBRESP_PROMISC = 1<<4, | 1260 | FIF_BCN_PRBRESP_PROMISC = 1<<4, |
| 1250 | FIF_CONTROL = 1<<5, | 1261 | FIF_CONTROL = 1<<5, |
| 1251 | FIF_OTHER_BSS = 1<<6, | 1262 | FIF_OTHER_BSS = 1<<6, |
| 1263 | FIF_PSPOLL = 1<<7, | ||
| 1252 | }; | 1264 | }; |
| 1253 | 1265 | ||
| 1254 | /** | 1266 | /** |
| @@ -1301,7 +1313,8 @@ enum ieee80211_ampdu_mlme_action { | |||
| 1301 | * is disabled. This should turn off the hardware (at least | 1313 | * is disabled. This should turn off the hardware (at least |
| 1302 | * it must turn off frame reception.) | 1314 | * it must turn off frame reception.) |
| 1303 | * May be called right after add_interface if that rejects | 1315 | * May be called right after add_interface if that rejects |
| 1304 | * an interface. | 1316 | * an interface. If you added any work onto the mac80211 workqueue |
| 1317 | * you should ensure to cancel it on this callback. | ||
| 1305 | * Must be implemented. | 1318 | * Must be implemented. |
| 1306 | * | 1319 | * |
| 1307 | * @add_interface: Called when a netdevice attached to the hardware is | 1320 | * @add_interface: Called when a netdevice attached to the hardware is |
| @@ -1928,6 +1941,31 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, | |||
| 1928 | void *data); | 1941 | void *data); |
| 1929 | 1942 | ||
| 1930 | /** | 1943 | /** |
| 1944 | * ieee80211_queue_work - add work onto the mac80211 workqueue | ||
| 1945 | * | ||
| 1946 | * Drivers and mac80211 use this to add work onto the mac80211 workqueue. | ||
| 1947 | * This helper ensures drivers are not queueing work when they should not be. | ||
| 1948 | * | ||
| 1949 | * @hw: the hardware struct for the interface we are adding work for | ||
| 1950 | * @work: the work we want to add onto the mac80211 workqueue | ||
| 1951 | */ | ||
| 1952 | void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work); | ||
| 1953 | |||
| 1954 | /** | ||
| 1955 | * ieee80211_queue_delayed_work - add work onto the mac80211 workqueue | ||
| 1956 | * | ||
| 1957 | * Drivers and mac80211 use this to queue delayed work onto the mac80211 | ||
| 1958 | * workqueue. | ||
| 1959 | * | ||
| 1960 | * @hw: the hardware struct for the interface we are adding work for | ||
| 1961 | * @dwork: delayable work to queue onto the mac80211 workqueue | ||
| 1962 | * @delay: number of jiffies to wait before queueing | ||
| 1963 | */ | ||
| 1964 | void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, | ||
| 1965 | struct delayed_work *dwork, | ||
| 1966 | unsigned long delay); | ||
| 1967 | |||
| 1968 | /** | ||
| 1931 | * ieee80211_start_tx_ba_session - Start a tx Block Ack session. | 1969 | * ieee80211_start_tx_ba_session - Start a tx Block Ack session. |
| 1932 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1970 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
| 1933 | * @ra: receiver address of the BA session recipient | 1971 | * @ra: receiver address of the BA session recipient |
diff --git a/net/mac80211/driver-trace.c b/net/mac80211/driver-trace.c index 6da6f79932fc..8ed8711b1a6d 100644 --- a/net/mac80211/driver-trace.c +++ b/net/mac80211/driver-trace.c | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | /* bug in tracepoint.h, it should include this */ | 1 | /* bug in tracepoint.h, it should include this */ |
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | 3 | ||
| 4 | /* sparse isn't too happy with all macros... */ | ||
| 5 | #ifndef __CHECKER__ | ||
| 4 | #include "driver-ops.h" | 6 | #include "driver-ops.h" |
| 5 | #define CREATE_TRACE_POINTS | 7 | #define CREATE_TRACE_POINTS |
| 6 | #include "driver-trace.h" | 8 | #include "driver-trace.h" |
| 9 | #endif | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 6e3cca65c460..920ec8792f4b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
| @@ -781,7 +781,7 @@ static void ieee80211_ibss_timer(unsigned long data) | |||
| 781 | } | 781 | } |
| 782 | 782 | ||
| 783 | set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); | 783 | set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); |
| 784 | queue_work(local->hw.workqueue, &ifibss->work); | 784 | ieee80211_queue_work(&local->hw, &ifibss->work); |
| 785 | } | 785 | } |
| 786 | 786 | ||
| 787 | #ifdef CONFIG_PM | 787 | #ifdef CONFIG_PM |
| @@ -853,7 +853,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
| 853 | case IEEE80211_STYPE_PROBE_REQ: | 853 | case IEEE80211_STYPE_PROBE_REQ: |
| 854 | case IEEE80211_STYPE_AUTH: | 854 | case IEEE80211_STYPE_AUTH: |
| 855 | skb_queue_tail(&sdata->u.ibss.skb_queue, skb); | 855 | skb_queue_tail(&sdata->u.ibss.skb_queue, skb); |
| 856 | queue_work(local->hw.workqueue, &sdata->u.ibss.work); | 856 | ieee80211_queue_work(&local->hw, &sdata->u.ibss.work); |
| 857 | return RX_QUEUED; | 857 | return RX_QUEUED; |
| 858 | } | 858 | } |
| 859 | 859 | ||
| @@ -912,7 +912,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
| 912 | ieee80211_recalc_idle(sdata->local); | 912 | ieee80211_recalc_idle(sdata->local); |
| 913 | 913 | ||
| 914 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 914 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); |
| 915 | queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); | 915 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work); |
| 916 | 916 | ||
| 917 | return 0; | 917 | return 0; |
| 918 | } | 918 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index aec6853cb435..630a438180fd 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -280,6 +280,7 @@ struct ieee80211_if_managed { | |||
| 280 | struct work_struct beacon_loss_work; | 280 | struct work_struct beacon_loss_work; |
| 281 | 281 | ||
| 282 | unsigned long probe_timeout; | 282 | unsigned long probe_timeout; |
| 283 | int probe_send_count; | ||
| 283 | 284 | ||
| 284 | struct mutex mtx; | 285 | struct mutex mtx; |
| 285 | struct ieee80211_bss *associated; | 286 | struct ieee80211_bss *associated; |
| @@ -614,6 +615,12 @@ struct ieee80211_local { | |||
| 614 | 615 | ||
| 615 | const struct ieee80211_ops *ops; | 616 | const struct ieee80211_ops *ops; |
| 616 | 617 | ||
| 618 | /* | ||
| 619 | * private workqueue to mac80211. mac80211 makes this accessible | ||
| 620 | * via ieee80211_queue_work() | ||
| 621 | */ | ||
| 622 | struct workqueue_struct *workqueue; | ||
| 623 | |||
| 617 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; | 624 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; |
| 618 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ | 625 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ |
| 619 | spinlock_t queue_stop_reason_lock; | 626 | spinlock_t queue_stop_reason_lock; |
| @@ -621,7 +628,7 @@ struct ieee80211_local { | |||
| 621 | int open_count; | 628 | int open_count; |
| 622 | int monitors, cooked_mntrs; | 629 | int monitors, cooked_mntrs; |
| 623 | /* number of interfaces with corresponding FIF_ flags */ | 630 | /* number of interfaces with corresponding FIF_ flags */ |
| 624 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; | 631 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; |
| 625 | unsigned int filter_flags; /* FIF_* */ | 632 | unsigned int filter_flags; /* FIF_* */ |
| 626 | struct iw_statistics wstats; | 633 | struct iw_statistics wstats; |
| 627 | 634 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6c655b6547fb..e8fb03b91a44 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -220,8 +220,10 @@ static int ieee80211_open(struct net_device *dev) | |||
| 220 | local->fif_fcsfail++; | 220 | local->fif_fcsfail++; |
| 221 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | 221 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) |
| 222 | local->fif_plcpfail++; | 222 | local->fif_plcpfail++; |
| 223 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | 223 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) { |
| 224 | local->fif_control++; | 224 | local->fif_control++; |
| 225 | local->fif_pspoll++; | ||
| 226 | } | ||
| 225 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | 227 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) |
| 226 | local->fif_other_bss++; | 228 | local->fif_other_bss++; |
| 227 | 229 | ||
| @@ -244,7 +246,14 @@ static int ieee80211_open(struct net_device *dev) | |||
| 244 | spin_unlock_bh(&local->filter_lock); | 246 | spin_unlock_bh(&local->filter_lock); |
| 245 | 247 | ||
| 246 | ieee80211_start_mesh(sdata); | 248 | ieee80211_start_mesh(sdata); |
| 249 | } else if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
| 250 | local->fif_pspoll++; | ||
| 251 | |||
| 252 | spin_lock_bh(&local->filter_lock); | ||
| 253 | ieee80211_configure_filter(local); | ||
| 254 | spin_unlock_bh(&local->filter_lock); | ||
| 247 | } | 255 | } |
| 256 | |||
| 248 | changed |= ieee80211_reset_erp_info(sdata); | 257 | changed |= ieee80211_reset_erp_info(sdata); |
| 249 | ieee80211_bss_info_change_notify(sdata, changed); | 258 | ieee80211_bss_info_change_notify(sdata, changed); |
| 250 | ieee80211_enable_keys(sdata); | 259 | ieee80211_enable_keys(sdata); |
| @@ -312,7 +321,7 @@ static int ieee80211_open(struct net_device *dev) | |||
| 312 | * to fix this. | 321 | * to fix this. |
| 313 | */ | 322 | */ |
| 314 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 323 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
| 315 | queue_work(local->hw.workqueue, &sdata->u.mgd.work); | 324 | ieee80211_queue_work(&local->hw, &sdata->u.mgd.work); |
| 316 | 325 | ||
| 317 | netif_tx_start_all_queues(dev); | 326 | netif_tx_start_all_queues(dev); |
| 318 | 327 | ||
| @@ -388,6 +397,9 @@ static int ieee80211_stop(struct net_device *dev) | |||
| 388 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 397 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
| 389 | atomic_dec(&local->iff_promiscs); | 398 | atomic_dec(&local->iff_promiscs); |
| 390 | 399 | ||
| 400 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
| 401 | local->fif_pspoll--; | ||
| 402 | |||
| 391 | netif_addr_lock_bh(dev); | 403 | netif_addr_lock_bh(dev); |
| 392 | spin_lock_bh(&local->filter_lock); | 404 | spin_lock_bh(&local->filter_lock); |
| 393 | __dev_addr_unsync(&local->mc_list, &local->mc_count, | 405 | __dev_addr_unsync(&local->mc_list, &local->mc_count, |
| @@ -401,7 +413,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
| 401 | 413 | ||
| 402 | /* APs need special treatment */ | 414 | /* APs need special treatment */ |
| 403 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 415 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
| 404 | struct ieee80211_sub_if_data *vlan, *tmp; | 416 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
| 405 | struct beacon_data *old_beacon = sdata->u.ap.beacon; | 417 | struct beacon_data *old_beacon = sdata->u.ap.beacon; |
| 406 | 418 | ||
| 407 | /* remove beacon */ | 419 | /* remove beacon */ |
| @@ -410,7 +422,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
| 410 | kfree(old_beacon); | 422 | kfree(old_beacon); |
| 411 | 423 | ||
| 412 | /* down all dependent devices, that is VLANs */ | 424 | /* down all dependent devices, that is VLANs */ |
| 413 | list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, | 425 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
| 414 | u.vlan.list) | 426 | u.vlan.list) |
| 415 | dev_close(vlan->dev); | 427 | dev_close(vlan->dev); |
| 416 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | 428 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); |
| @@ -439,8 +451,10 @@ static int ieee80211_stop(struct net_device *dev) | |||
| 439 | local->fif_fcsfail--; | 451 | local->fif_fcsfail--; |
| 440 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | 452 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) |
| 441 | local->fif_plcpfail--; | 453 | local->fif_plcpfail--; |
| 442 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | 454 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) { |
| 455 | local->fif_pspoll--; | ||
| 443 | local->fif_control--; | 456 | local->fif_control--; |
| 457 | } | ||
| 444 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | 458 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) |
| 445 | local->fif_other_bss--; | 459 | local->fif_other_bss--; |
| 446 | 460 | ||
| @@ -522,6 +536,16 @@ static int ieee80211_stop(struct net_device *dev) | |||
| 522 | ieee80211_scan_completed(&local->hw, true); | 536 | ieee80211_scan_completed(&local->hw, true); |
| 523 | } | 537 | } |
| 524 | 538 | ||
| 539 | /* | ||
| 540 | * Disable beaconing for AP and mesh, IBSS can't | ||
| 541 | * still be joined to a network at this point. | ||
| 542 | */ | ||
| 543 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
| 544 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) { | ||
| 545 | ieee80211_bss_info_change_notify(sdata, | ||
| 546 | BSS_CHANGED_BEACON_ENABLED); | ||
| 547 | } | ||
| 548 | |||
| 525 | conf.vif = &sdata->vif; | 549 | conf.vif = &sdata->vif; |
| 526 | conf.type = sdata->vif.type; | 550 | conf.type = sdata->vif.type; |
| 527 | conf.mac_addr = dev->dev_addr; | 551 | conf.mac_addr = dev->dev_addr; |
| @@ -541,7 +565,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
| 541 | 565 | ||
| 542 | ieee80211_led_radio(local, false); | 566 | ieee80211_led_radio(local, false); |
| 543 | 567 | ||
| 544 | flush_workqueue(local->hw.workqueue); | 568 | flush_workqueue(local->workqueue); |
| 545 | 569 | ||
| 546 | tasklet_disable(&local->tx_pending_tasklet); | 570 | tasklet_disable(&local->tx_pending_tasklet); |
| 547 | tasklet_disable(&local->tasklet); | 571 | tasklet_disable(&local->tasklet); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c1a799194fff..0c4f8e122ed6 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -77,6 +77,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
| 77 | if (local->fif_other_bss) | 77 | if (local->fif_other_bss) |
| 78 | new_flags |= FIF_OTHER_BSS; | 78 | new_flags |= FIF_OTHER_BSS; |
| 79 | 79 | ||
| 80 | if (local->fif_pspoll) | ||
| 81 | new_flags |= FIF_PSPOLL; | ||
| 82 | |||
| 80 | changed_flags = local->filter_flags ^ new_flags; | 83 | changed_flags = local->filter_flags ^ new_flags; |
| 81 | 84 | ||
| 82 | /* be a bit nasty */ | 85 | /* be a bit nasty */ |
| @@ -198,7 +201,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
| 198 | } | 201 | } |
| 199 | 202 | ||
| 200 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 203 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
| 201 | if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { | 204 | if (local->quiescing || !netif_running(sdata->dev) || |
| 205 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { | ||
| 202 | sdata->vif.bss_conf.enable_beacon = false; | 206 | sdata->vif.bss_conf.enable_beacon = false; |
| 203 | } else { | 207 | } else { |
| 204 | /* | 208 | /* |
| @@ -310,6 +314,31 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
| 310 | { | 314 | { |
| 311 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 315 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 312 | 316 | ||
| 317 | /* | ||
| 318 | * XXX: This is temporary! | ||
| 319 | * | ||
| 320 | * The problem here is that when we get here, the driver will | ||
| 321 | * quite likely have pretty much overwritten info->control by | ||
| 322 | * using info->driver_data or info->rate_driver_data. Thus, | ||
| 323 | * when passing out the frame to the driver again, we would be | ||
| 324 | * passing completely bogus data since the driver would then | ||
| 325 | * expect a properly filled info->control. In mac80211 itself | ||
| 326 | * the same problem occurs, since we need info->control.vif | ||
| 327 | * internally. | ||
| 328 | * | ||
| 329 | * To fix this, we should send the frame through TX processing | ||
| 330 | * again. However, it's not that simple, since the frame will | ||
| 331 | * have been software-encrypted (if applicable) already, and | ||
| 332 | * encrypting it again doesn't do much good. So to properly do | ||
| 333 | * that, we not only have to skip the actual 'raw' encryption | ||
| 334 | * (key selection etc. still has to be done!) but also the | ||
| 335 | * sequence number assignment since that impacts the crypto | ||
| 336 | * encapsulation, of course. | ||
| 337 | * | ||
| 338 | * Hence, for now, fix the bug by just dropping the frame. | ||
| 339 | */ | ||
| 340 | goto drop; | ||
| 341 | |||
| 313 | sta->tx_filtered_count++; | 342 | sta->tx_filtered_count++; |
| 314 | 343 | ||
| 315 | /* | 344 | /* |
| @@ -363,6 +392,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
| 363 | return; | 392 | return; |
| 364 | } | 393 | } |
| 365 | 394 | ||
| 395 | drop: | ||
| 366 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 396 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
| 367 | if (net_ratelimit()) | 397 | if (net_ratelimit()) |
| 368 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " | 398 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " |
| @@ -794,9 +824,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 794 | if (hw->queues > IEEE80211_MAX_QUEUES) | 824 | if (hw->queues > IEEE80211_MAX_QUEUES) |
| 795 | hw->queues = IEEE80211_MAX_QUEUES; | 825 | hw->queues = IEEE80211_MAX_QUEUES; |
| 796 | 826 | ||
| 797 | local->hw.workqueue = | 827 | local->workqueue = |
| 798 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); | 828 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); |
| 799 | if (!local->hw.workqueue) { | 829 | if (!local->workqueue) { |
| 800 | result = -ENOMEM; | 830 | result = -ENOMEM; |
| 801 | goto fail_workqueue; | 831 | goto fail_workqueue; |
| 802 | } | 832 | } |
| @@ -886,7 +916,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 886 | sta_info_stop(local); | 916 | sta_info_stop(local); |
| 887 | fail_sta_info: | 917 | fail_sta_info: |
| 888 | debugfs_hw_del(local); | 918 | debugfs_hw_del(local); |
| 889 | destroy_workqueue(local->hw.workqueue); | 919 | destroy_workqueue(local->workqueue); |
| 890 | fail_workqueue: | 920 | fail_workqueue: |
| 891 | wiphy_unregister(local->hw.wiphy); | 921 | wiphy_unregister(local->hw.wiphy); |
| 892 | fail_wiphy_register: | 922 | fail_wiphy_register: |
| @@ -928,7 +958,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
| 928 | skb_queue_purge(&local->skb_queue); | 958 | skb_queue_purge(&local->skb_queue); |
| 929 | skb_queue_purge(&local->skb_queue_unreliable); | 959 | skb_queue_purge(&local->skb_queue_unreliable); |
| 930 | 960 | ||
| 931 | destroy_workqueue(local->hw.workqueue); | 961 | destroy_workqueue(local->workqueue); |
| 932 | wiphy_unregister(local->hw.wiphy); | 962 | wiphy_unregister(local->hw.wiphy); |
| 933 | ieee80211_wep_free(local); | 963 | ieee80211_wep_free(local); |
| 934 | ieee80211_led_exit(local); | 964 | ieee80211_led_exit(local); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 9a3826978b1c..2f4f518ab45c 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
| @@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) | |||
| 54 | return; | 54 | return; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | queue_work(local->hw.workqueue, &ifmsh->work); | 57 | ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | /** | 60 | /** |
| @@ -357,7 +357,7 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
| 357 | return; | 357 | return; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | queue_work(local->hw.workqueue, &ifmsh->work); | 360 | ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | 363 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl) |
| @@ -471,7 +471,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
| 471 | struct ieee80211_local *local = sdata->local; | 471 | struct ieee80211_local *local = sdata->local; |
| 472 | 472 | ||
| 473 | ifmsh->housekeeping = true; | 473 | ifmsh->housekeeping = true; |
| 474 | queue_work(local->hw.workqueue, &ifmsh->work); | 474 | ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); |
| 475 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 475 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
| 476 | BSS_CHANGED_BEACON_ENABLED); | 476 | BSS_CHANGED_BEACON_ENABLED); |
| 477 | } | 477 | } |
| @@ -619,7 +619,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | |||
| 619 | rcu_read_lock(); | 619 | rcu_read_lock(); |
| 620 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 620 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
| 621 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 621 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
| 622 | queue_work(local->hw.workqueue, &sdata->u.mesh.work); | 622 | ieee80211_queue_work(local->hw.workqueue, &sdata->u.mesh.work); |
| 623 | rcu_read_unlock(); | 623 | rcu_read_unlock(); |
| 624 | } | 624 | } |
| 625 | 625 | ||
| @@ -692,7 +692,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
| 692 | case IEEE80211_STYPE_PROBE_RESP: | 692 | case IEEE80211_STYPE_PROBE_RESP: |
| 693 | case IEEE80211_STYPE_BEACON: | 693 | case IEEE80211_STYPE_BEACON: |
| 694 | skb_queue_tail(&ifmsh->skb_queue, skb); | 694 | skb_queue_tail(&ifmsh->skb_queue, skb); |
| 695 | queue_work(local->hw.workqueue, &ifmsh->work); | 695 | ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); |
| 696 | return RX_QUEUED; | 696 | return RX_QUEUED; |
| 697 | } | 697 | } |
| 698 | 698 | ||
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index e93c37ef6a48..11ab71a68ff9 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
| @@ -660,14 +660,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
| 660 | spin_unlock(&ifmsh->mesh_preq_queue_lock); | 660 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
| 661 | 661 | ||
| 662 | if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) | 662 | if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) |
| 663 | queue_work(sdata->local->hw.workqueue, &ifmsh->work); | 663 | ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work); |
| 664 | 664 | ||
| 665 | else if (time_before(jiffies, ifmsh->last_preq)) { | 665 | else if (time_before(jiffies, ifmsh->last_preq)) { |
| 666 | /* avoid long wait if did not send preqs for a long time | 666 | /* avoid long wait if did not send preqs for a long time |
| 667 | * and jiffies wrapped around | 667 | * and jiffies wrapped around |
| 668 | */ | 668 | */ |
| 669 | ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; | 669 | ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; |
| 670 | queue_work(sdata->local->hw.workqueue, &ifmsh->work); | 670 | ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work); |
| 671 | } else | 671 | } else |
| 672 | mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + | 672 | mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + |
| 673 | min_preq_int_jiff(sdata)); | 673 | min_preq_int_jiff(sdata)); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ee83125ed179..6d5a1ee0445f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #define IEEE80211_AUTH_MAX_TRIES 3 | 31 | #define IEEE80211_AUTH_MAX_TRIES 3 |
| 32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
| 33 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 33 | #define IEEE80211_ASSOC_MAX_TRIES 3 |
| 34 | #define IEEE80211_MAX_PROBE_TRIES 5 | ||
| 34 | 35 | ||
| 35 | /* | 36 | /* |
| 36 | * beacon loss detection timeout | 37 | * beacon loss detection timeout |
| @@ -41,13 +42,13 @@ | |||
| 41 | * Time the connection can be idle before we probe | 42 | * Time the connection can be idle before we probe |
| 42 | * it to see if we can still talk to the AP. | 43 | * it to see if we can still talk to the AP. |
| 43 | */ | 44 | */ |
| 44 | #define IEEE80211_CONNECTION_IDLE_TIME (2 * HZ) | 45 | #define IEEE80211_CONNECTION_IDLE_TIME (30 * HZ) |
| 45 | /* | 46 | /* |
| 46 | * Time we wait for a probe response after sending | 47 | * Time we wait for a probe response after sending |
| 47 | * a probe request because of beacon loss or for | 48 | * a probe request because of beacon loss or for |
| 48 | * checking the connection still works. | 49 | * checking the connection still works. |
| 49 | */ | 50 | */ |
| 50 | #define IEEE80211_PROBE_WAIT (HZ / 5) | 51 | #define IEEE80211_PROBE_WAIT (HZ / 2) |
| 51 | 52 | ||
| 52 | #define TMR_RUNNING_TIMER 0 | 53 | #define TMR_RUNNING_TIMER 0 |
| 53 | #define TMR_RUNNING_CHANSW 1 | 54 | #define TMR_RUNNING_CHANSW 1 |
| @@ -565,7 +566,7 @@ static void ieee80211_chswitch_timer(unsigned long data) | |||
| 565 | return; | 566 | return; |
| 566 | } | 567 | } |
| 567 | 568 | ||
| 568 | queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); | 569 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); |
| 569 | } | 570 | } |
| 570 | 571 | ||
| 571 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 572 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
| @@ -597,7 +598,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
| 597 | sdata->local->csa_channel = new_ch; | 598 | sdata->local->csa_channel = new_ch; |
| 598 | 599 | ||
| 599 | if (sw_elem->count <= 1) { | 600 | if (sw_elem->count <= 1) { |
| 600 | queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); | 601 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); |
| 601 | } else { | 602 | } else { |
| 602 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 603 | ieee80211_stop_queues_by_reason(&sdata->local->hw, |
| 603 | IEEE80211_QUEUE_STOP_REASON_CSA); | 604 | IEEE80211_QUEUE_STOP_REASON_CSA); |
| @@ -763,7 +764,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data) | |||
| 763 | if (local->quiescing || local->suspended) | 764 | if (local->quiescing || local->suspended) |
| 764 | return; | 765 | return; |
| 765 | 766 | ||
| 766 | queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); | 767 | ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work); |
| 767 | } | 768 | } |
| 768 | 769 | ||
| 769 | /* MLME */ | 770 | /* MLME */ |
| @@ -916,12 +917,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
| 916 | 917 | ||
| 917 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 918 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
| 918 | 919 | ||
| 919 | /* will be same as sdata */ | 920 | mutex_lock(&local->iflist_mtx); |
| 920 | if (local->ps_sdata) { | 921 | ieee80211_recalc_ps(local, -1); |
| 921 | mutex_lock(&local->iflist_mtx); | 922 | mutex_unlock(&local->iflist_mtx); |
| 922 | ieee80211_recalc_ps(local, -1); | ||
| 923 | mutex_unlock(&local->iflist_mtx); | ||
| 924 | } | ||
| 925 | 923 | ||
| 926 | netif_tx_start_all_queues(sdata->dev); | 924 | netif_tx_start_all_queues(sdata->dev); |
| 927 | netif_carrier_on(sdata->dev); | 925 | netif_carrier_on(sdata->dev); |
| @@ -950,7 +948,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
| 950 | * due to work needing to be done. Hence, queue the STAs work | 948 | * due to work needing to be done. Hence, queue the STAs work |
| 951 | * again for that. | 949 | * again for that. |
| 952 | */ | 950 | */ |
| 953 | queue_work(local->hw.workqueue, &ifmgd->work); | 951 | ieee80211_queue_work(&local->hw, &ifmgd->work); |
| 954 | return RX_MGMT_CFG80211_AUTH_TO; | 952 | return RX_MGMT_CFG80211_AUTH_TO; |
| 955 | } | 953 | } |
| 956 | 954 | ||
| @@ -995,7 +993,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
| 995 | * due to work needing to be done. Hence, queue the STAs work | 993 | * due to work needing to be done. Hence, queue the STAs work |
| 996 | * again for that. | 994 | * again for that. |
| 997 | */ | 995 | */ |
| 998 | queue_work(local->hw.workqueue, &ifmgd->work); | 996 | ieee80211_queue_work(&local->hw, &ifmgd->work); |
| 999 | return RX_MGMT_CFG80211_AUTH_TO; | 997 | return RX_MGMT_CFG80211_AUTH_TO; |
| 1000 | } | 998 | } |
| 1001 | 999 | ||
| @@ -1124,7 +1122,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
| 1124 | * due to work needing to be done. Hence, queue the STAs work | 1122 | * due to work needing to be done. Hence, queue the STAs work |
| 1125 | * again for that. | 1123 | * again for that. |
| 1126 | */ | 1124 | */ |
| 1127 | queue_work(local->hw.workqueue, &ifmgd->work); | 1125 | ieee80211_queue_work(&local->hw, &ifmgd->work); |
| 1128 | return RX_MGMT_CFG80211_ASSOC_TO; | 1126 | return RX_MGMT_CFG80211_ASSOC_TO; |
| 1129 | } | 1127 | } |
| 1130 | 1128 | ||
| @@ -1156,11 +1154,24 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
| 1156 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | 1154 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); |
| 1157 | } | 1155 | } |
| 1158 | 1156 | ||
| 1157 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | ||
| 1158 | { | ||
| 1159 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
| 1160 | const u8 *ssid; | ||
| 1161 | |||
| 1162 | ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID); | ||
| 1163 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, | ||
| 1164 | ssid + 2, ssid[1], NULL, 0); | ||
| 1165 | |||
| 1166 | ifmgd->probe_send_count++; | ||
| 1167 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | ||
| 1168 | run_again(ifmgd, ifmgd->probe_timeout); | ||
| 1169 | } | ||
| 1170 | |||
| 1159 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | 1171 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, |
| 1160 | bool beacon) | 1172 | bool beacon) |
| 1161 | { | 1173 | { |
| 1162 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1174 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 1163 | const u8 *ssid; | ||
| 1164 | bool already = false; | 1175 | bool already = false; |
| 1165 | 1176 | ||
| 1166 | if (!netif_running(sdata->dev)) | 1177 | if (!netif_running(sdata->dev)) |
| @@ -1203,18 +1214,12 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
| 1203 | if (already) | 1214 | if (already) |
| 1204 | goto out; | 1215 | goto out; |
| 1205 | 1216 | ||
| 1206 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | ||
| 1207 | |||
| 1208 | mutex_lock(&sdata->local->iflist_mtx); | 1217 | mutex_lock(&sdata->local->iflist_mtx); |
| 1209 | ieee80211_recalc_ps(sdata->local, -1); | 1218 | ieee80211_recalc_ps(sdata->local, -1); |
| 1210 | mutex_unlock(&sdata->local->iflist_mtx); | 1219 | mutex_unlock(&sdata->local->iflist_mtx); |
| 1211 | 1220 | ||
| 1212 | ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID); | 1221 | ifmgd->probe_send_count = 0; |
| 1213 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, | 1222 | ieee80211_mgd_probe_ap_send(sdata); |
| 1214 | ssid + 2, ssid[1], NULL, 0); | ||
| 1215 | |||
| 1216 | run_again(ifmgd, ifmgd->probe_timeout); | ||
| 1217 | |||
| 1218 | out: | 1223 | out: |
| 1219 | mutex_unlock(&ifmgd->mtx); | 1224 | mutex_unlock(&ifmgd->mtx); |
| 1220 | } | 1225 | } |
| @@ -1232,8 +1237,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif) | |||
| 1232 | { | 1237 | { |
| 1233 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1238 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
| 1234 | 1239 | ||
| 1235 | queue_work(sdata->local->hw.workqueue, | 1240 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); |
| 1236 | &sdata->u.mgd.beacon_loss_work); | ||
| 1237 | } | 1241 | } |
| 1238 | EXPORT_SYMBOL(ieee80211_beacon_loss); | 1242 | EXPORT_SYMBOL(ieee80211_beacon_loss); |
| 1239 | 1243 | ||
| @@ -1570,6 +1574,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
| 1570 | wk->bss->cbss.bssid, | 1574 | wk->bss->cbss.bssid, |
| 1571 | ap_ht_cap_flags); | 1575 | ap_ht_cap_flags); |
| 1572 | 1576 | ||
| 1577 | /* delete work item -- must be before set_associated for PS */ | ||
| 1578 | list_del(&wk->list); | ||
| 1579 | |||
| 1573 | /* set AID and assoc capability, | 1580 | /* set AID and assoc capability, |
| 1574 | * ieee80211_set_associated() will tell the driver */ | 1581 | * ieee80211_set_associated() will tell the driver */ |
| 1575 | bss_conf->aid = aid; | 1582 | bss_conf->aid = aid; |
| @@ -1583,7 +1590,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
| 1583 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 1590 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
| 1584 | mod_beacon_timer(sdata); | 1591 | mod_beacon_timer(sdata); |
| 1585 | 1592 | ||
| 1586 | list_del(&wk->list); | ||
| 1587 | kfree(wk); | 1593 | kfree(wk); |
| 1588 | return RX_MGMT_CFG80211_ASSOC; | 1594 | return RX_MGMT_CFG80211_ASSOC; |
| 1589 | } | 1595 | } |
| @@ -1847,12 +1853,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 1847 | bssid, ap_ht_cap_flags); | 1853 | bssid, ap_ht_cap_flags); |
| 1848 | } | 1854 | } |
| 1849 | 1855 | ||
| 1856 | /* Note: country IE parsing is done for us by cfg80211 */ | ||
| 1850 | if (elems.country_elem) { | 1857 | if (elems.country_elem) { |
| 1851 | /* Note we are only reviewing this on beacons | ||
| 1852 | * for the BSSID we are associated to */ | ||
| 1853 | regulatory_hint_11d(local->hw.wiphy, | ||
| 1854 | elems.country_elem, elems.country_elem_len); | ||
| 1855 | |||
| 1856 | /* TODO: IBSS also needs this */ | 1858 | /* TODO: IBSS also needs this */ |
| 1857 | if (elems.pwr_constr_elem) | 1859 | if (elems.pwr_constr_elem) |
| 1858 | ieee80211_handle_pwr_constr(sdata, | 1860 | ieee80211_handle_pwr_constr(sdata, |
| @@ -1888,7 +1890,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | |||
| 1888 | case IEEE80211_STYPE_DISASSOC: | 1890 | case IEEE80211_STYPE_DISASSOC: |
| 1889 | case IEEE80211_STYPE_ACTION: | 1891 | case IEEE80211_STYPE_ACTION: |
| 1890 | skb_queue_tail(&sdata->u.mgd.skb_queue, skb); | 1892 | skb_queue_tail(&sdata->u.mgd.skb_queue, skb); |
| 1891 | queue_work(local->hw.workqueue, &sdata->u.mgd.work); | 1893 | ieee80211_queue_work(&local->hw, &sdata->u.mgd.work); |
| 1892 | return RX_QUEUED; | 1894 | return RX_QUEUED; |
| 1893 | } | 1895 | } |
| 1894 | 1896 | ||
| @@ -2026,7 +2028,7 @@ static void ieee80211_sta_timer(unsigned long data) | |||
| 2026 | return; | 2028 | return; |
| 2027 | } | 2029 | } |
| 2028 | 2030 | ||
| 2029 | queue_work(local->hw.workqueue, &ifmgd->work); | 2031 | ieee80211_queue_work(&local->hw, &ifmgd->work); |
| 2030 | } | 2032 | } |
| 2031 | 2033 | ||
| 2032 | static void ieee80211_sta_work(struct work_struct *work) | 2034 | static void ieee80211_sta_work(struct work_struct *work) |
| @@ -2051,13 +2053,11 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
| 2051 | return; | 2053 | return; |
| 2052 | 2054 | ||
| 2053 | /* | 2055 | /* |
| 2054 | * Nothing should have been stuffed into the workqueue during | 2056 | * ieee80211_queue_work() should have picked up most cases, |
| 2055 | * the suspend->resume cycle. If this WARN is seen then there | 2057 | * here we'll pick the the rest. |
| 2056 | * is a bug with either the driver suspend or something in | ||
| 2057 | * mac80211 stuffing into the workqueue which we haven't yet | ||
| 2058 | * cleared during mac80211's suspend cycle. | ||
| 2059 | */ | 2058 | */ |
| 2060 | if (WARN_ON(local->suspended)) | 2059 | if (WARN(local->suspended, "STA MLME work scheduled while " |
| 2060 | "going to suspend\n")) | ||
| 2061 | return; | 2061 | return; |
| 2062 | 2062 | ||
| 2063 | ifmgd = &sdata->u.mgd; | 2063 | ifmgd = &sdata->u.mgd; |
| @@ -2072,17 +2072,27 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
| 2072 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 2072 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
| 2073 | IEEE80211_STA_CONNECTION_POLL) && | 2073 | IEEE80211_STA_CONNECTION_POLL) && |
| 2074 | ifmgd->associated) { | 2074 | ifmgd->associated) { |
| 2075 | u8 bssid[ETH_ALEN]; | ||
| 2076 | |||
| 2077 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | ||
| 2075 | if (time_is_after_jiffies(ifmgd->probe_timeout)) | 2078 | if (time_is_after_jiffies(ifmgd->probe_timeout)) |
| 2076 | run_again(ifmgd, ifmgd->probe_timeout); | 2079 | run_again(ifmgd, ifmgd->probe_timeout); |
| 2077 | else { | 2080 | |
| 2078 | u8 bssid[ETH_ALEN]; | 2081 | else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) { |
| 2082 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
| 2083 | printk(KERN_DEBUG "No probe response from AP %pM" | ||
| 2084 | " after %dms, try %d\n", bssid, | ||
| 2085 | (1000 * IEEE80211_PROBE_WAIT)/HZ, | ||
| 2086 | ifmgd->probe_send_count); | ||
| 2087 | #endif | ||
| 2088 | ieee80211_mgd_probe_ap_send(sdata); | ||
| 2089 | } else { | ||
| 2079 | /* | 2090 | /* |
| 2080 | * We actually lost the connection ... or did we? | 2091 | * We actually lost the connection ... or did we? |
| 2081 | * Let's make sure! | 2092 | * Let's make sure! |
| 2082 | */ | 2093 | */ |
| 2083 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 2094 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
| 2084 | IEEE80211_STA_BEACON_POLL); | 2095 | IEEE80211_STA_BEACON_POLL); |
| 2085 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | ||
| 2086 | printk(KERN_DEBUG "No probe response from AP %pM" | 2096 | printk(KERN_DEBUG "No probe response from AP %pM" |
| 2087 | " after %dms, disconnecting.\n", | 2097 | " after %dms, disconnecting.\n", |
| 2088 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2098 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
| @@ -2113,9 +2123,9 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
| 2113 | mutex_unlock(&ifmgd->mtx); | 2123 | mutex_unlock(&ifmgd->mtx); |
| 2114 | 2124 | ||
| 2115 | if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) | 2125 | if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) |
| 2116 | queue_delayed_work(local->hw.workqueue, | 2126 | ieee80211_queue_delayed_work(&local->hw, |
| 2117 | &local->scan_work, | 2127 | &local->scan_work, |
| 2118 | round_jiffies_relative(0)); | 2128 | round_jiffies_relative(0)); |
| 2119 | return; | 2129 | return; |
| 2120 | } | 2130 | } |
| 2121 | 2131 | ||
| @@ -2196,8 +2206,7 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data) | |||
| 2196 | if (local->quiescing) | 2206 | if (local->quiescing) |
| 2197 | return; | 2207 | return; |
| 2198 | 2208 | ||
| 2199 | queue_work(sdata->local->hw.workqueue, | 2209 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); |
| 2200 | &sdata->u.mgd.beacon_loss_work); | ||
| 2201 | } | 2210 | } |
| 2202 | 2211 | ||
| 2203 | static void ieee80211_sta_conn_mon_timer(unsigned long data) | 2212 | static void ieee80211_sta_conn_mon_timer(unsigned long data) |
| @@ -2210,7 +2219,7 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data) | |||
| 2210 | if (local->quiescing) | 2219 | if (local->quiescing) |
| 2211 | return; | 2220 | return; |
| 2212 | 2221 | ||
| 2213 | queue_work(local->hw.workqueue, &ifmgd->monitor_work); | 2222 | ieee80211_queue_work(&local->hw, &ifmgd->monitor_work); |
| 2214 | } | 2223 | } |
| 2215 | 2224 | ||
| 2216 | static void ieee80211_sta_monitor_work(struct work_struct *work) | 2225 | static void ieee80211_sta_monitor_work(struct work_struct *work) |
| @@ -2229,10 +2238,10 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
| 2229 | IEEE80211_STA_CONNECTION_POLL); | 2238 | IEEE80211_STA_CONNECTION_POLL); |
| 2230 | 2239 | ||
| 2231 | /* let's probe the connection once */ | 2240 | /* let's probe the connection once */ |
| 2232 | queue_work(sdata->local->hw.workqueue, | 2241 | ieee80211_queue_work(&sdata->local->hw, |
| 2233 | &sdata->u.mgd.monitor_work); | 2242 | &sdata->u.mgd.monitor_work); |
| 2234 | /* and do all the other regular work too */ | 2243 | /* and do all the other regular work too */ |
| 2235 | queue_work(sdata->local->hw.workqueue, | 2244 | ieee80211_queue_work(&sdata->local->hw, |
| 2236 | &sdata->u.mgd.work); | 2245 | &sdata->u.mgd.work); |
| 2237 | } | 2246 | } |
| 2238 | } | 2247 | } |
| @@ -2393,7 +2402,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
| 2393 | list_add(&wk->list, &sdata->u.mgd.work_list); | 2402 | list_add(&wk->list, &sdata->u.mgd.work_list); |
| 2394 | mutex_unlock(&ifmgd->mtx); | 2403 | mutex_unlock(&ifmgd->mtx); |
| 2395 | 2404 | ||
| 2396 | queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work); | 2405 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); |
| 2397 | return 0; | 2406 | return 0; |
| 2398 | } | 2407 | } |
| 2399 | 2408 | ||
| @@ -2467,7 +2476,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 2467 | else | 2476 | else |
| 2468 | ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; | 2477 | ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; |
| 2469 | 2478 | ||
| 2470 | queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work); | 2479 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); |
| 2471 | 2480 | ||
| 2472 | err = 0; | 2481 | err = 0; |
| 2473 | 2482 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 5e3d476972f9..a5d2f1fb4417 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
| @@ -26,7 +26,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
| 26 | /* make quiescing visible to timers everywhere */ | 26 | /* make quiescing visible to timers everywhere */ |
| 27 | mb(); | 27 | mb(); |
| 28 | 28 | ||
| 29 | flush_workqueue(local->hw.workqueue); | 29 | flush_workqueue(local->workqueue); |
| 30 | 30 | ||
| 31 | /* Don't try to run timers while suspended. */ | 31 | /* Don't try to run timers while suspended. */ |
| 32 | del_timer_sync(&local->sta_cleanup); | 32 | del_timer_sync(&local->sta_cleanup); |
| @@ -96,6 +96,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
| 96 | if (!netif_running(sdata->dev)) | 96 | if (!netif_running(sdata->dev)) |
| 97 | continue; | 97 | continue; |
| 98 | 98 | ||
| 99 | /* disable beaconing */ | ||
| 100 | ieee80211_bss_info_change_notify(sdata, | ||
| 101 | BSS_CHANGED_BEACON_ENABLED); | ||
| 102 | |||
| 99 | conf.vif = &sdata->vif; | 103 | conf.vif = &sdata->vif; |
| 100 | conf.type = sdata->vif.type; | 104 | conf.type = sdata->vif.type; |
| 101 | conf.mac_addr = sdata->dev->dev_addr; | 105 | conf.mac_addr = sdata->dev->dev_addr; |
| @@ -113,7 +117,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
| 113 | * shouldn't be doing (or cancel everything in the | 117 | * shouldn't be doing (or cancel everything in the |
| 114 | * stop callback) that but better safe than sorry. | 118 | * stop callback) that but better safe than sorry. |
| 115 | */ | 119 | */ |
| 116 | flush_workqueue(local->hw.workqueue); | 120 | flush_workqueue(local->workqueue); |
| 117 | 121 | ||
| 118 | local->suspended = true; | 122 | local->suspended = true; |
| 119 | /* need suspended to be visible before quiescing is false */ | 123 | /* need suspended to be visible before quiescing is false */ |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 45731000eb8d..244f53f3c8b4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
| @@ -385,8 +385,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
| 385 | spin_unlock_bh(&local->filter_lock); | 385 | spin_unlock_bh(&local->filter_lock); |
| 386 | 386 | ||
| 387 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | 387 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ |
| 388 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | 388 | ieee80211_queue_delayed_work(&local->hw, |
| 389 | IEEE80211_CHANNEL_TIME); | 389 | &local->scan_work, |
| 390 | IEEE80211_CHANNEL_TIME); | ||
| 390 | 391 | ||
| 391 | return 0; | 392 | return 0; |
| 392 | } | 393 | } |
| @@ -715,8 +716,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
| 715 | } | 716 | } |
| 716 | } while (next_delay == 0); | 717 | } while (next_delay == 0); |
| 717 | 718 | ||
| 718 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | 719 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); |
| 719 | next_delay); | ||
| 720 | } | 720 | } |
| 721 | 721 | ||
| 722 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 722 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4e1b2ba122cd..7cffaa046b33 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -1400,7 +1400,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
| 1400 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 1400 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
| 1401 | ieee80211_stop_queues_by_reason(&local->hw, | 1401 | ieee80211_stop_queues_by_reason(&local->hw, |
| 1402 | IEEE80211_QUEUE_STOP_REASON_PS); | 1402 | IEEE80211_QUEUE_STOP_REASON_PS); |
| 1403 | queue_work(local->hw.workqueue, | 1403 | ieee80211_queue_work(&local->hw, |
| 1404 | &local->dynamic_ps_disable_work); | 1404 | &local->dynamic_ps_disable_work); |
| 1405 | } | 1405 | } |
| 1406 | 1406 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 8502936e5314..e55d57f559ec 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -511,6 +511,46 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
| 511 | } | 511 | } |
| 512 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | 512 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); |
| 513 | 513 | ||
| 514 | /* | ||
| 515 | * Nothing should have been stuffed into the workqueue during | ||
| 516 | * the suspend->resume cycle. If this WARN is seen then there | ||
| 517 | * is a bug with either the driver suspend or something in | ||
| 518 | * mac80211 stuffing into the workqueue which we haven't yet | ||
| 519 | * cleared during mac80211's suspend cycle. | ||
| 520 | */ | ||
| 521 | static bool ieee80211_can_queue_work(struct ieee80211_local *local) | ||
| 522 | { | ||
| 523 | if (WARN(local->suspended, "queueing ieee80211 work while " | ||
| 524 | "going to suspend\n")) | ||
| 525 | return false; | ||
| 526 | |||
| 527 | return true; | ||
| 528 | } | ||
| 529 | |||
| 530 | void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work) | ||
| 531 | { | ||
| 532 | struct ieee80211_local *local = hw_to_local(hw); | ||
| 533 | |||
| 534 | if (!ieee80211_can_queue_work(local)) | ||
| 535 | return; | ||
| 536 | |||
| 537 | queue_work(local->workqueue, work); | ||
| 538 | } | ||
| 539 | EXPORT_SYMBOL(ieee80211_queue_work); | ||
| 540 | |||
| 541 | void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, | ||
| 542 | struct delayed_work *dwork, | ||
| 543 | unsigned long delay) | ||
| 544 | { | ||
| 545 | struct ieee80211_local *local = hw_to_local(hw); | ||
| 546 | |||
| 547 | if (!ieee80211_can_queue_work(local)) | ||
| 548 | return; | ||
| 549 | |||
| 550 | queue_delayed_work(local->workqueue, dwork, delay); | ||
| 551 | } | ||
| 552 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); | ||
| 553 | |||
| 514 | void ieee802_11_parse_elems(u8 *start, size_t len, | 554 | void ieee802_11_parse_elems(u8 *start, size_t len, |
| 515 | struct ieee802_11_elems *elems) | 555 | struct ieee802_11_elems *elems) |
| 516 | { | 556 | { |
| @@ -1114,3 +1154,4 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1114 | #endif | 1154 | #endif |
| 1115 | return 0; | 1155 | return 0; |
| 1116 | } | 1156 | } |
| 1157 | |||
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 044de1c6af3d..dbeaf2983822 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
| @@ -589,11 +589,13 @@ static const char *rfkill_get_type_str(enum rfkill_type type) | |||
| 589 | return "wimax"; | 589 | return "wimax"; |
| 590 | case RFKILL_TYPE_WWAN: | 590 | case RFKILL_TYPE_WWAN: |
| 591 | return "wwan"; | 591 | return "wwan"; |
| 592 | case RFKILL_TYPE_GPS: | ||
| 593 | return "gps"; | ||
| 592 | default: | 594 | default: |
| 593 | BUG(); | 595 | BUG(); |
| 594 | } | 596 | } |
| 595 | 597 | ||
| 596 | BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_WWAN + 1); | 598 | BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_GPS + 1); |
| 597 | } | 599 | } |
| 598 | 600 | ||
| 599 | static ssize_t rfkill_type_show(struct device *dev, | 601 | static ssize_t rfkill_type_show(struct device *dev, |
diff --git a/net/wireless/core.c b/net/wireless/core.c index f9fee65dc06a..1e189306560d 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -34,9 +34,7 @@ MODULE_DESCRIPTION("wireless configuration support"); | |||
| 34 | LIST_HEAD(cfg80211_rdev_list); | 34 | LIST_HEAD(cfg80211_rdev_list); |
| 35 | 35 | ||
| 36 | /* | 36 | /* |
| 37 | * This is used to protect the cfg80211_rdev_list, cfg80211_regdomain, | 37 | * This is used to protect the cfg80211_rdev_list |
| 38 | * country_ie_regdomain, the reg_beacon_list and the the last regulatory | ||
| 39 | * request receipt (last_request). | ||
| 40 | */ | 38 | */ |
| 41 | DEFINE_MUTEX(cfg80211_mutex); | 39 | DEFINE_MUTEX(cfg80211_mutex); |
| 42 | 40 | ||
| @@ -314,7 +312,8 @@ static void cfg80211_process_events(struct wireless_dev *wdev) | |||
| 314 | ev->cr.req_ie, ev->cr.req_ie_len, | 312 | ev->cr.req_ie, ev->cr.req_ie_len, |
| 315 | ev->cr.resp_ie, ev->cr.resp_ie_len, | 313 | ev->cr.resp_ie, ev->cr.resp_ie_len, |
| 316 | ev->cr.status, | 314 | ev->cr.status, |
| 317 | ev->cr.status == WLAN_STATUS_SUCCESS); | 315 | ev->cr.status == WLAN_STATUS_SUCCESS, |
| 316 | NULL); | ||
| 318 | break; | 317 | break; |
| 319 | case EVENT_ROAMED: | 318 | case EVENT_ROAMED: |
| 320 | __cfg80211_roamed(wdev, ev->rm.bssid, | 319 | __cfg80211_roamed(wdev, ev->rm.bssid, |
| @@ -672,7 +671,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
| 672 | wdev->wext.default_mgmt_key = -1; | 671 | wdev->wext.default_mgmt_key = -1; |
| 673 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 672 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
| 674 | wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE; | 673 | wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE; |
| 675 | wdev->wext.ps_timeout = 500; | 674 | wdev->wext.ps_timeout = 100; |
| 676 | if (rdev->ops->set_power_mgmt) | 675 | if (rdev->ops->set_power_mgmt) |
| 677 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, | 676 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, |
| 678 | wdev->wext.ps, | 677 | wdev->wext.ps, |
| @@ -724,15 +723,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
| 724 | break; | 723 | break; |
| 725 | case NETDEV_UNREGISTER: | 724 | case NETDEV_UNREGISTER: |
| 726 | mutex_lock(&rdev->devlist_mtx); | 725 | mutex_lock(&rdev->devlist_mtx); |
| 726 | /* | ||
| 727 | * It is possible to get NETDEV_UNREGISTER | ||
| 728 | * multiple times. To detect that, check | ||
| 729 | * that the interface is still on the list | ||
| 730 | * of registered interfaces, and only then | ||
| 731 | * remove and clean it up. | ||
| 732 | */ | ||
| 727 | if (!list_empty(&wdev->list)) { | 733 | if (!list_empty(&wdev->list)) { |
| 728 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); | 734 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); |
| 729 | list_del_init(&wdev->list); | 735 | list_del_init(&wdev->list); |
| 730 | } | 736 | mutex_destroy(&wdev->mtx); |
| 731 | mutex_unlock(&rdev->devlist_mtx); | ||
| 732 | mutex_destroy(&wdev->mtx); | ||
| 733 | #ifdef CONFIG_WIRELESS_EXT | 737 | #ifdef CONFIG_WIRELESS_EXT |
| 734 | kfree(wdev->wext.keys); | 738 | kfree(wdev->wext.keys); |
| 735 | #endif | 739 | #endif |
| 740 | } | ||
| 741 | mutex_unlock(&rdev->devlist_mtx); | ||
| 736 | break; | 742 | break; |
| 737 | case NETDEV_PRE_UP: | 743 | case NETDEV_PRE_UP: |
| 738 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) | 744 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 6d903c1d721d..325c17e6198c 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -127,6 +127,11 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu | |||
| 127 | return container_of(pub, struct cfg80211_internal_bss, pub); | 127 | return container_of(pub, struct cfg80211_internal_bss, pub); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | static inline void cfg80211_ref_bss(struct cfg80211_internal_bss *bss) | ||
| 131 | { | ||
| 132 | kref_get(&bss->ref); | ||
| 133 | } | ||
| 134 | |||
| 130 | static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) | 135 | static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) |
| 131 | { | 136 | { |
| 132 | atomic_inc(&bss->hold); | 137 | atomic_inc(&bss->hold); |
| @@ -323,7 +328,8 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
| 323 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 328 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
| 324 | const u8 *req_ie, size_t req_ie_len, | 329 | const u8 *req_ie, size_t req_ie_len, |
| 325 | const u8 *resp_ie, size_t resp_ie_len, | 330 | const u8 *resp_ie, size_t resp_ie_len, |
| 326 | u16 status, bool wextev); | 331 | u16 status, bool wextev, |
| 332 | struct cfg80211_bss *bss); | ||
| 327 | 333 | ||
| 328 | /* SME */ | 334 | /* SME */ |
| 329 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 335 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 097a87d7bae1..525e8e247b30 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
| @@ -61,7 +61,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
| 61 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 61 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
| 62 | u8 *ie = mgmt->u.assoc_resp.variable; | 62 | u8 *ie = mgmt->u.assoc_resp.variable; |
| 63 | int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); | 63 | int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); |
| 64 | bool done; | 64 | struct cfg80211_internal_bss *bss = NULL; |
| 65 | 65 | ||
| 66 | wdev_lock(wdev); | 66 | wdev_lock(wdev); |
| 67 | 67 | ||
| @@ -69,22 +69,32 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
| 69 | 69 | ||
| 70 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); | 70 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); |
| 71 | 71 | ||
| 72 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | ||
| 73 | status_code, | ||
| 74 | status_code == WLAN_STATUS_SUCCESS); | ||
| 75 | |||
| 76 | if (status_code == WLAN_STATUS_SUCCESS) { | 72 | if (status_code == WLAN_STATUS_SUCCESS) { |
| 77 | for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) { | 73 | for (i = 0; i < MAX_AUTH_BSSES; i++) { |
| 78 | if (wdev->auth_bsses[i] == wdev->current_bss) { | 74 | if (!wdev->auth_bsses[i]) |
| 79 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | 75 | continue; |
| 80 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | 76 | if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid, |
| 77 | ETH_ALEN) == 0) { | ||
| 78 | bss = wdev->auth_bsses[i]; | ||
| 81 | wdev->auth_bsses[i] = NULL; | 79 | wdev->auth_bsses[i] = NULL; |
| 82 | done = true; | 80 | /* additional reference to drop hold */ |
| 81 | cfg80211_ref_bss(bss); | ||
| 83 | break; | 82 | break; |
| 84 | } | 83 | } |
| 85 | } | 84 | } |
| 86 | 85 | ||
| 87 | WARN_ON(!done); | 86 | WARN_ON(!bss); |
| 87 | } | ||
| 88 | |||
| 89 | /* this consumes one bss reference (unless bss is NULL) */ | ||
| 90 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | ||
| 91 | status_code, | ||
| 92 | status_code == WLAN_STATUS_SUCCESS, | ||
| 93 | bss ? &bss->pub : NULL); | ||
| 94 | /* drop hold now, and also reference acquired above */ | ||
| 95 | if (bss) { | ||
| 96 | cfg80211_unhold_bss(bss); | ||
| 97 | cfg80211_put_bss(&bss->pub); | ||
| 88 | } | 98 | } |
| 89 | 99 | ||
| 90 | wdev_unlock(wdev); | 100 | wdev_unlock(wdev); |
| @@ -144,7 +154,7 @@ static void __cfg80211_send_deauth(struct net_device *dev, | |||
| 144 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { | 154 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { |
| 145 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, | 155 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, |
| 146 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 156 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
| 147 | false); | 157 | false, NULL); |
| 148 | } | 158 | } |
| 149 | } | 159 | } |
| 150 | 160 | ||
| @@ -241,7 +251,7 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
| 241 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | 251 | if (wdev->sme_state == CFG80211_SME_CONNECTING) |
| 242 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | 252 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, |
| 243 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 253 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
| 244 | false); | 254 | false, NULL); |
| 245 | 255 | ||
| 246 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | 256 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { |
| 247 | if (wdev->authtry_bsses[i] && | 257 | if (wdev->authtry_bsses[i] && |
| @@ -275,7 +285,7 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
| 275 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | 285 | if (wdev->sme_state == CFG80211_SME_CONNECTING) |
| 276 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | 286 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, |
| 277 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 287 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
| 278 | false); | 288 | false, NULL); |
| 279 | 289 | ||
| 280 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | 290 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { |
| 281 | if (wdev->auth_bsses[i] && | 291 | if (wdev->auth_bsses[i] && |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index fb40428a5946..b3ac0aace0e5 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -62,6 +62,16 @@ const struct ieee80211_regdomain *cfg80211_regdomain; | |||
| 62 | */ | 62 | */ |
| 63 | static const struct ieee80211_regdomain *country_ie_regdomain; | 63 | static const struct ieee80211_regdomain *country_ie_regdomain; |
| 64 | 64 | ||
| 65 | /* | ||
| 66 | * Protects static reg.c components: | ||
| 67 | * - cfg80211_world_regdom | ||
| 68 | * - cfg80211_regdom | ||
| 69 | * - country_ie_regdomain | ||
| 70 | * - last_request | ||
| 71 | */ | ||
| 72 | DEFINE_MUTEX(reg_mutex); | ||
| 73 | #define assert_reg_lock() WARN_ON(!mutex_is_locked(®_mutex)) | ||
| 74 | |||
| 65 | /* Used to queue up regulatory hints */ | 75 | /* Used to queue up regulatory hints */ |
| 66 | static LIST_HEAD(reg_requests_list); | 76 | static LIST_HEAD(reg_requests_list); |
| 67 | static spinlock_t reg_requests_lock; | 77 | static spinlock_t reg_requests_lock; |
| @@ -1293,7 +1303,7 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
| 1293 | struct ieee80211_supported_band *sband; | 1303 | struct ieee80211_supported_band *sband; |
| 1294 | struct ieee80211_channel *chan; | 1304 | struct ieee80211_channel *chan; |
| 1295 | 1305 | ||
| 1296 | assert_cfg80211_lock(); | 1306 | assert_reg_lock(); |
| 1297 | 1307 | ||
| 1298 | sband = wiphy->bands[band]; | 1308 | sband = wiphy->bands[band]; |
| 1299 | BUG_ON(chan_idx >= sband->n_channels); | 1309 | BUG_ON(chan_idx >= sband->n_channels); |
| @@ -1342,14 +1352,14 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | |||
| 1342 | enum ieee80211_band band; | 1352 | enum ieee80211_band band; |
| 1343 | unsigned int bands_set = 0; | 1353 | unsigned int bands_set = 0; |
| 1344 | 1354 | ||
| 1345 | mutex_lock(&cfg80211_mutex); | 1355 | mutex_lock(®_mutex); |
| 1346 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1356 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
| 1347 | if (!wiphy->bands[band]) | 1357 | if (!wiphy->bands[band]) |
| 1348 | continue; | 1358 | continue; |
| 1349 | handle_band_custom(wiphy, band, regd); | 1359 | handle_band_custom(wiphy, band, regd); |
| 1350 | bands_set++; | 1360 | bands_set++; |
| 1351 | } | 1361 | } |
| 1352 | mutex_unlock(&cfg80211_mutex); | 1362 | mutex_unlock(®_mutex); |
| 1353 | 1363 | ||
| 1354 | /* | 1364 | /* |
| 1355 | * no point in calling this if it won't have any effect | 1365 | * no point in calling this if it won't have any effect |
| @@ -1495,7 +1505,7 @@ static int ignore_request(struct wiphy *wiphy, | |||
| 1495 | * Returns zero if all went fine, %-EALREADY if a regulatory domain had | 1505 | * Returns zero if all went fine, %-EALREADY if a regulatory domain had |
| 1496 | * already been set or other standard error codes. | 1506 | * already been set or other standard error codes. |
| 1497 | * | 1507 | * |
| 1498 | * Caller must hold &cfg80211_mutex | 1508 | * Caller must hold &cfg80211_mutex and ®_mutex |
| 1499 | */ | 1509 | */ |
| 1500 | static int __regulatory_hint(struct wiphy *wiphy, | 1510 | static int __regulatory_hint(struct wiphy *wiphy, |
| 1501 | struct regulatory_request *pending_request) | 1511 | struct regulatory_request *pending_request) |
| @@ -1570,6 +1580,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
| 1570 | BUG_ON(!reg_request->alpha2); | 1580 | BUG_ON(!reg_request->alpha2); |
| 1571 | 1581 | ||
| 1572 | mutex_lock(&cfg80211_mutex); | 1582 | mutex_lock(&cfg80211_mutex); |
| 1583 | mutex_lock(®_mutex); | ||
| 1573 | 1584 | ||
| 1574 | if (wiphy_idx_valid(reg_request->wiphy_idx)) | 1585 | if (wiphy_idx_valid(reg_request->wiphy_idx)) |
| 1575 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); | 1586 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); |
| @@ -1585,6 +1596,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
| 1585 | if (r == -EALREADY && wiphy && wiphy->strict_regulatory) | 1596 | if (r == -EALREADY && wiphy && wiphy->strict_regulatory) |
| 1586 | wiphy_update_regulatory(wiphy, reg_request->initiator); | 1597 | wiphy_update_regulatory(wiphy, reg_request->initiator); |
| 1587 | out: | 1598 | out: |
| 1599 | mutex_unlock(®_mutex); | ||
| 1588 | mutex_unlock(&cfg80211_mutex); | 1600 | mutex_unlock(&cfg80211_mutex); |
| 1589 | } | 1601 | } |
| 1590 | 1602 | ||
| @@ -1613,6 +1625,10 @@ static void reg_process_pending_beacon_hints(void) | |||
| 1613 | struct cfg80211_registered_device *rdev; | 1625 | struct cfg80211_registered_device *rdev; |
| 1614 | struct reg_beacon *pending_beacon, *tmp; | 1626 | struct reg_beacon *pending_beacon, *tmp; |
| 1615 | 1627 | ||
| 1628 | /* | ||
| 1629 | * No need to hold the reg_mutex here as we just touch wiphys | ||
| 1630 | * and do not read or access regulatory variables. | ||
| 1631 | */ | ||
| 1616 | mutex_lock(&cfg80211_mutex); | 1632 | mutex_lock(&cfg80211_mutex); |
| 1617 | 1633 | ||
| 1618 | /* This goes through the _pending_ beacon list */ | 1634 | /* This goes through the _pending_ beacon list */ |
| @@ -1734,12 +1750,13 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
| 1734 | } | 1750 | } |
| 1735 | EXPORT_SYMBOL(regulatory_hint); | 1751 | EXPORT_SYMBOL(regulatory_hint); |
| 1736 | 1752 | ||
| 1753 | /* Caller must hold reg_mutex */ | ||
| 1737 | static bool reg_same_country_ie_hint(struct wiphy *wiphy, | 1754 | static bool reg_same_country_ie_hint(struct wiphy *wiphy, |
| 1738 | u32 country_ie_checksum) | 1755 | u32 country_ie_checksum) |
| 1739 | { | 1756 | { |
| 1740 | struct wiphy *request_wiphy; | 1757 | struct wiphy *request_wiphy; |
| 1741 | 1758 | ||
| 1742 | assert_cfg80211_lock(); | 1759 | assert_reg_lock(); |
| 1743 | 1760 | ||
| 1744 | if (unlikely(last_request->initiator != | 1761 | if (unlikely(last_request->initiator != |
| 1745 | NL80211_REGDOM_SET_BY_COUNTRY_IE)) | 1762 | NL80211_REGDOM_SET_BY_COUNTRY_IE)) |
| @@ -1762,6 +1779,10 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy, | |||
| 1762 | return false; | 1779 | return false; |
| 1763 | } | 1780 | } |
| 1764 | 1781 | ||
| 1782 | /* | ||
| 1783 | * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and | ||
| 1784 | * therefore cannot iterate over the rdev list here. | ||
| 1785 | */ | ||
| 1765 | void regulatory_hint_11d(struct wiphy *wiphy, | 1786 | void regulatory_hint_11d(struct wiphy *wiphy, |
| 1766 | u8 *country_ie, | 1787 | u8 *country_ie, |
| 1767 | u8 country_ie_len) | 1788 | u8 country_ie_len) |
| @@ -1772,12 +1793,10 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
| 1772 | enum environment_cap env = ENVIRON_ANY; | 1793 | enum environment_cap env = ENVIRON_ANY; |
| 1773 | struct regulatory_request *request; | 1794 | struct regulatory_request *request; |
| 1774 | 1795 | ||
| 1775 | mutex_lock(&cfg80211_mutex); | 1796 | mutex_lock(®_mutex); |
| 1776 | 1797 | ||
| 1777 | if (unlikely(!last_request)) { | 1798 | if (unlikely(!last_request)) |
| 1778 | mutex_unlock(&cfg80211_mutex); | 1799 | goto out; |
| 1779 | return; | ||
| 1780 | } | ||
| 1781 | 1800 | ||
| 1782 | /* IE len must be evenly divisible by 2 */ | 1801 | /* IE len must be evenly divisible by 2 */ |
| 1783 | if (country_ie_len & 0x01) | 1802 | if (country_ie_len & 0x01) |
| @@ -1803,54 +1822,14 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
| 1803 | env = ENVIRON_OUTDOOR; | 1822 | env = ENVIRON_OUTDOOR; |
| 1804 | 1823 | ||
| 1805 | /* | 1824 | /* |
| 1806 | * We will run this for *every* beacon processed for the BSSID, so | 1825 | * We will run this only upon a successful connection on cfg80211. |
| 1807 | * we optimize an early check to exit out early if we don't have to | 1826 | * We leave conflict resolution to the workqueue, where can hold |
| 1808 | * do anything | 1827 | * cfg80211_mutex. |
| 1809 | */ | 1828 | */ |
| 1810 | if (likely(last_request->initiator == | 1829 | if (likely(last_request->initiator == |
| 1811 | NL80211_REGDOM_SET_BY_COUNTRY_IE && | 1830 | NL80211_REGDOM_SET_BY_COUNTRY_IE && |
| 1812 | wiphy_idx_valid(last_request->wiphy_idx))) { | 1831 | wiphy_idx_valid(last_request->wiphy_idx))) |
| 1813 | struct cfg80211_registered_device *rdev_last_ie; | 1832 | goto out; |
| 1814 | |||
| 1815 | rdev_last_ie = | ||
| 1816 | cfg80211_rdev_by_wiphy_idx(last_request->wiphy_idx); | ||
| 1817 | |||
| 1818 | /* | ||
| 1819 | * Lets keep this simple -- we trust the first AP | ||
| 1820 | * after we intersect with CRDA | ||
| 1821 | */ | ||
| 1822 | if (likely(&rdev_last_ie->wiphy == wiphy)) { | ||
| 1823 | /* | ||
| 1824 | * Ignore IEs coming in on this wiphy with | ||
| 1825 | * the same alpha2 and environment cap | ||
| 1826 | */ | ||
| 1827 | if (likely(alpha2_equal(rdev_last_ie->country_ie_alpha2, | ||
| 1828 | alpha2) && | ||
| 1829 | env == rdev_last_ie->env)) { | ||
| 1830 | goto out; | ||
| 1831 | } | ||
| 1832 | /* | ||
| 1833 | * the wiphy moved on to another BSSID or the AP | ||
| 1834 | * was reconfigured. XXX: We need to deal with the | ||
| 1835 | * case where the user suspends and goes to goes | ||
| 1836 | * to another country, and then gets IEs from an | ||
| 1837 | * AP with different settings | ||
| 1838 | */ | ||
| 1839 | goto out; | ||
| 1840 | } else { | ||
| 1841 | /* | ||
| 1842 | * Ignore IEs coming in on two separate wiphys with | ||
| 1843 | * the same alpha2 and environment cap | ||
| 1844 | */ | ||
| 1845 | if (likely(alpha2_equal(rdev_last_ie->country_ie_alpha2, | ||
| 1846 | alpha2) && | ||
| 1847 | env == rdev_last_ie->env)) { | ||
| 1848 | goto out; | ||
| 1849 | } | ||
| 1850 | /* We could potentially intersect though */ | ||
| 1851 | goto out; | ||
| 1852 | } | ||
| 1853 | } | ||
| 1854 | 1833 | ||
| 1855 | rd = country_ie_2_rd(country_ie, country_ie_len, &checksum); | 1834 | rd = country_ie_2_rd(country_ie, country_ie_len, &checksum); |
| 1856 | if (!rd) | 1835 | if (!rd) |
| @@ -1885,7 +1864,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
| 1885 | request->country_ie_checksum = checksum; | 1864 | request->country_ie_checksum = checksum; |
| 1886 | request->country_ie_env = env; | 1865 | request->country_ie_env = env; |
| 1887 | 1866 | ||
| 1888 | mutex_unlock(&cfg80211_mutex); | 1867 | mutex_unlock(®_mutex); |
| 1889 | 1868 | ||
| 1890 | queue_regulatory_request(request); | 1869 | queue_regulatory_request(request); |
| 1891 | 1870 | ||
| @@ -1894,9 +1873,8 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
| 1894 | free_rd_out: | 1873 | free_rd_out: |
| 1895 | kfree(rd); | 1874 | kfree(rd); |
| 1896 | out: | 1875 | out: |
| 1897 | mutex_unlock(&cfg80211_mutex); | 1876 | mutex_unlock(®_mutex); |
| 1898 | } | 1877 | } |
| 1899 | EXPORT_SYMBOL(regulatory_hint_11d); | ||
| 1900 | 1878 | ||
| 1901 | static bool freq_is_chan_12_13_14(u16 freq) | 1879 | static bool freq_is_chan_12_13_14(u16 freq) |
| 1902 | { | 1880 | { |
| @@ -2227,10 +2205,13 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2227 | 2205 | ||
| 2228 | assert_cfg80211_lock(); | 2206 | assert_cfg80211_lock(); |
| 2229 | 2207 | ||
| 2208 | mutex_lock(®_mutex); | ||
| 2209 | |||
| 2230 | /* Note that this doesn't update the wiphys, this is done below */ | 2210 | /* Note that this doesn't update the wiphys, this is done below */ |
| 2231 | r = __set_regdom(rd); | 2211 | r = __set_regdom(rd); |
| 2232 | if (r) { | 2212 | if (r) { |
| 2233 | kfree(rd); | 2213 | kfree(rd); |
| 2214 | mutex_unlock(®_mutex); | ||
| 2234 | return r; | 2215 | return r; |
| 2235 | } | 2216 | } |
| 2236 | 2217 | ||
| @@ -2245,6 +2226,8 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2245 | 2226 | ||
| 2246 | nl80211_send_reg_change_event(last_request); | 2227 | nl80211_send_reg_change_event(last_request); |
| 2247 | 2228 | ||
| 2229 | mutex_unlock(®_mutex); | ||
| 2230 | |||
| 2248 | return r; | 2231 | return r; |
| 2249 | } | 2232 | } |
| 2250 | 2233 | ||
| @@ -2255,16 +2238,20 @@ void reg_device_remove(struct wiphy *wiphy) | |||
| 2255 | 2238 | ||
| 2256 | assert_cfg80211_lock(); | 2239 | assert_cfg80211_lock(); |
| 2257 | 2240 | ||
| 2241 | mutex_lock(®_mutex); | ||
| 2242 | |||
| 2258 | kfree(wiphy->regd); | 2243 | kfree(wiphy->regd); |
| 2259 | 2244 | ||
| 2260 | if (last_request) | 2245 | if (last_request) |
| 2261 | request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | 2246 | request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); |
| 2262 | 2247 | ||
| 2263 | if (!request_wiphy || request_wiphy != wiphy) | 2248 | if (!request_wiphy || request_wiphy != wiphy) |
| 2264 | return; | 2249 | goto out; |
| 2265 | 2250 | ||
| 2266 | last_request->wiphy_idx = WIPHY_IDX_STALE; | 2251 | last_request->wiphy_idx = WIPHY_IDX_STALE; |
| 2267 | last_request->country_ie_env = ENVIRON_ANY; | 2252 | last_request->country_ie_env = ENVIRON_ANY; |
| 2253 | out: | ||
| 2254 | mutex_unlock(®_mutex); | ||
| 2268 | } | 2255 | } |
| 2269 | 2256 | ||
| 2270 | int regulatory_init(void) | 2257 | int regulatory_init(void) |
| @@ -2325,6 +2312,7 @@ void regulatory_exit(void) | |||
| 2325 | cancel_work_sync(®_work); | 2312 | cancel_work_sync(®_work); |
| 2326 | 2313 | ||
| 2327 | mutex_lock(&cfg80211_mutex); | 2314 | mutex_lock(&cfg80211_mutex); |
| 2315 | mutex_lock(®_mutex); | ||
| 2328 | 2316 | ||
| 2329 | reset_regdomains(); | 2317 | reset_regdomains(); |
| 2330 | 2318 | ||
| @@ -2363,5 +2351,6 @@ void regulatory_exit(void) | |||
| 2363 | } | 2351 | } |
| 2364 | spin_unlock(®_requests_lock); | 2352 | spin_unlock(®_requests_lock); |
| 2365 | 2353 | ||
| 2354 | mutex_unlock(®_mutex); | ||
| 2366 | mutex_unlock(&cfg80211_mutex); | 2355 | mutex_unlock(&cfg80211_mutex); |
| 2367 | } | 2356 | } |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index e37829a49dc4..662a9dad76d5 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
| @@ -36,4 +36,19 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, | |||
| 36 | struct ieee80211_channel *beacon_chan, | 36 | struct ieee80211_channel *beacon_chan, |
| 37 | gfp_t gfp); | 37 | gfp_t gfp); |
| 38 | 38 | ||
| 39 | /** | ||
| 40 | * regulatory_hint_11d - hints a country IE as a regulatory domain | ||
| 41 | * @wiphy: the wireless device giving the hint (used only for reporting | ||
| 42 | * conflicts) | ||
| 43 | * @country_ie: pointer to the country IE | ||
| 44 | * @country_ie_len: length of the country IE | ||
| 45 | * | ||
| 46 | * We will intersect the rd with the what CRDA tells us should apply | ||
| 47 | * for the alpha2 this country IE belongs to, this prevents APs from | ||
| 48 | * sending us incorrect or outdated information against a country. | ||
| 49 | */ | ||
| 50 | void regulatory_hint_11d(struct wiphy *wiphy, | ||
| 51 | u8 *country_ie, | ||
| 52 | u8 country_ie_len); | ||
| 53 | |||
| 39 | #endif /* __NET_WIRELESS_REG_H */ | 54 | #endif /* __NET_WIRELESS_REG_H */ |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index d2b5d4ce0a00..8a7dcbf90602 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <net/cfg80211.h> | 13 | #include <net/cfg80211.h> |
| 14 | #include <net/rtnetlink.h> | 14 | #include <net/rtnetlink.h> |
| 15 | #include "nl80211.h" | 15 | #include "nl80211.h" |
| 16 | #include "reg.h" | ||
| 16 | 17 | ||
| 17 | struct cfg80211_conn { | 18 | struct cfg80211_conn { |
| 18 | struct cfg80211_connect_params params; | 19 | struct cfg80211_connect_params params; |
| @@ -182,7 +183,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
| 182 | wdev->conn->params.bssid, | 183 | wdev->conn->params.bssid, |
| 183 | NULL, 0, NULL, 0, | 184 | NULL, 0, NULL, 0, |
| 184 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 185 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
| 185 | false); | 186 | false, NULL); |
| 186 | wdev_unlock(wdev); | 187 | wdev_unlock(wdev); |
| 187 | } | 188 | } |
| 188 | 189 | ||
| @@ -247,7 +248,7 @@ static void __cfg80211_sme_scan_done(struct net_device *dev) | |||
| 247 | wdev->conn->params.bssid, | 248 | wdev->conn->params.bssid, |
| 248 | NULL, 0, NULL, 0, | 249 | NULL, 0, NULL, 0, |
| 249 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 250 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
| 250 | false); | 251 | false, NULL); |
| 251 | } | 252 | } |
| 252 | } | 253 | } |
| 253 | 254 | ||
| @@ -305,7 +306,7 @@ void cfg80211_sme_rx_auth(struct net_device *dev, | |||
| 305 | schedule_work(&rdev->conn_work); | 306 | schedule_work(&rdev->conn_work); |
| 306 | } else if (status_code != WLAN_STATUS_SUCCESS) { | 307 | } else if (status_code != WLAN_STATUS_SUCCESS) { |
| 307 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, | 308 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, |
| 308 | status_code, false); | 309 | status_code, false, NULL); |
| 309 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING && | 310 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING && |
| 310 | wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { | 311 | wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { |
| 311 | wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; | 312 | wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; |
| @@ -316,10 +317,11 @@ void cfg80211_sme_rx_auth(struct net_device *dev, | |||
| 316 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 317 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
| 317 | const u8 *req_ie, size_t req_ie_len, | 318 | const u8 *req_ie, size_t req_ie_len, |
| 318 | const u8 *resp_ie, size_t resp_ie_len, | 319 | const u8 *resp_ie, size_t resp_ie_len, |
| 319 | u16 status, bool wextev) | 320 | u16 status, bool wextev, |
| 321 | struct cfg80211_bss *bss) | ||
| 320 | { | 322 | { |
| 321 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 323 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 322 | struct cfg80211_bss *bss; | 324 | u8 *country_ie; |
| 323 | #ifdef CONFIG_WIRELESS_EXT | 325 | #ifdef CONFIG_WIRELESS_EXT |
| 324 | union iwreq_data wrqu; | 326 | union iwreq_data wrqu; |
| 325 | #endif | 327 | #endif |
| @@ -361,6 +363,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
| 361 | } | 363 | } |
| 362 | #endif | 364 | #endif |
| 363 | 365 | ||
| 366 | if (wdev->current_bss) { | ||
| 367 | cfg80211_unhold_bss(wdev->current_bss); | ||
| 368 | cfg80211_put_bss(&wdev->current_bss->pub); | ||
| 369 | wdev->current_bss = NULL; | ||
| 370 | } | ||
| 371 | |||
| 364 | if (status == WLAN_STATUS_SUCCESS && | 372 | if (status == WLAN_STATUS_SUCCESS && |
| 365 | wdev->sme_state == CFG80211_SME_IDLE) | 373 | wdev->sme_state == CFG80211_SME_IDLE) |
| 366 | goto success; | 374 | goto success; |
| @@ -368,12 +376,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
| 368 | if (wdev->sme_state != CFG80211_SME_CONNECTING) | 376 | if (wdev->sme_state != CFG80211_SME_CONNECTING) |
| 369 | return; | 377 | return; |
| 370 | 378 | ||
| 371 | if (wdev->current_bss) { | ||
| 372 | cfg80211_unhold_bss(wdev->current_bss); | ||
| 373 | cfg80211_put_bss(&wdev->current_bss->pub); | ||
| 374 | wdev->current_bss = NULL; | ||
| 375 | } | ||
| 376 | |||
| 377 | if (wdev->conn) | 379 | if (wdev->conn) |
| 378 | wdev->conn->state = CFG80211_CONN_IDLE; | 380 | wdev->conn->state = CFG80211_CONN_IDLE; |
| 379 | 381 | ||
| @@ -383,13 +385,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
| 383 | wdev->conn = NULL; | 385 | wdev->conn = NULL; |
| 384 | kfree(wdev->connect_keys); | 386 | kfree(wdev->connect_keys); |
| 385 | wdev->connect_keys = NULL; | 387 | wdev->connect_keys = NULL; |
| 388 | wdev->ssid_len = 0; | ||
| 386 | return; | 389 | return; |
| 387 | } | 390 | } |
| 388 | 391 | ||
| 389 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | 392 | success: |
| 390 | wdev->ssid, wdev->ssid_len, | 393 | if (!bss) |
| 391 | WLAN_CAPABILITY_ESS, | 394 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, |
| 392 | WLAN_CAPABILITY_ESS); | 395 | wdev->ssid, wdev->ssid_len, |
| 396 | WLAN_CAPABILITY_ESS, | ||
| 397 | WLAN_CAPABILITY_ESS); | ||
| 393 | 398 | ||
| 394 | if (WARN_ON(!bss)) | 399 | if (WARN_ON(!bss)) |
| 395 | return; | 400 | return; |
| @@ -397,9 +402,22 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
| 397 | cfg80211_hold_bss(bss_from_pub(bss)); | 402 | cfg80211_hold_bss(bss_from_pub(bss)); |
| 398 | wdev->current_bss = bss_from_pub(bss); | 403 | wdev->current_bss = bss_from_pub(bss); |
| 399 | 404 | ||
| 400 | success: | ||
| 401 | wdev->sme_state = CFG80211_SME_CONNECTED; | 405 | wdev->sme_state = CFG80211_SME_CONNECTED; |
| 402 | cfg80211_upload_connect_keys(wdev); | 406 | cfg80211_upload_connect_keys(wdev); |
| 407 | |||
| 408 | country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); | ||
| 409 | |||
| 410 | if (!country_ie) | ||
| 411 | return; | ||
| 412 | |||
| 413 | /* | ||
| 414 | * ieee80211_bss_get_ie() ensures we can access: | ||
| 415 | * - country_ie + 2, the start of the country ie data, and | ||
| 416 | * - and country_ie[1] which is the IE length | ||
| 417 | */ | ||
| 418 | regulatory_hint_11d(wdev->wiphy, | ||
| 419 | country_ie + 2, | ||
| 420 | country_ie[1]); | ||
| 403 | } | 421 | } |
| 404 | 422 | ||
| 405 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 423 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
| @@ -549,6 +567,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
| 549 | 567 | ||
| 550 | wdev->current_bss = NULL; | 568 | wdev->current_bss = NULL; |
| 551 | wdev->sme_state = CFG80211_SME_IDLE; | 569 | wdev->sme_state = CFG80211_SME_IDLE; |
| 570 | wdev->ssid_len = 0; | ||
| 552 | 571 | ||
| 553 | if (wdev->conn) { | 572 | if (wdev->conn) { |
| 554 | kfree(wdev->conn->ie); | 573 | kfree(wdev->conn->ie); |
| @@ -704,6 +723,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
| 704 | wdev->conn = NULL; | 723 | wdev->conn = NULL; |
| 705 | wdev->sme_state = CFG80211_SME_IDLE; | 724 | wdev->sme_state = CFG80211_SME_IDLE; |
| 706 | wdev->connect_keys = NULL; | 725 | wdev->connect_keys = NULL; |
| 726 | wdev->ssid_len = 0; | ||
| 707 | } | 727 | } |
| 708 | 728 | ||
| 709 | return err; | 729 | return err; |
| @@ -768,6 +788,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
| 768 | wdev->sme_state = CFG80211_SME_IDLE; | 788 | wdev->sme_state = CFG80211_SME_IDLE; |
| 769 | kfree(wdev->conn); | 789 | kfree(wdev->conn); |
| 770 | wdev->conn = NULL; | 790 | wdev->conn = NULL; |
| 791 | wdev->ssid_len = 0; | ||
| 771 | return 0; | 792 | return 0; |
| 772 | } | 793 | } |
| 773 | 794 | ||
| @@ -788,7 +809,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
| 788 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) | 809 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) |
| 789 | __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, | 810 | __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, |
| 790 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 811 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
| 791 | wextev); | 812 | wextev, NULL); |
| 792 | 813 | ||
| 793 | return 0; | 814 | return 0; |
| 794 | } | 815 | } |
diff --git a/net/wireless/wext.c b/net/wireless/wext.c index 3fe3c2c0ce11..5b4a0cee4418 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c | |||
| @@ -1291,7 +1291,6 @@ static struct pernet_operations wext_pernet_ops = { | |||
| 1291 | static int __init wireless_nlevent_init(void) | 1291 | static int __init wireless_nlevent_init(void) |
| 1292 | { | 1292 | { |
| 1293 | return register_pernet_subsys(&wext_pernet_ops); | 1293 | return register_pernet_subsys(&wext_pernet_ops); |
| 1294 | return 0; | ||
| 1295 | } | 1294 | } |
| 1296 | 1295 | ||
| 1297 | subsys_initcall(wireless_nlevent_init); | 1296 | subsys_initcall(wireless_nlevent_init); |
