odhcpd: fix regression in dhcpv6 t1 and t2 calculation
[openwrt/staging/rmilecki.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
index 5b9146f45395154aaff5a58b56c8174e3f4e4f0f..63229520982831f801125f4877197c6ef7bc5618 100644 (file)
-commit e138e0ef9560c46ce93dbb22a728a57888e94d1c
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date:   Mon Feb 3 13:31:37 2014 +0530
-
-    ath9k: Fix TX power calculation
-    
-    The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template"
-    fixed the incorrect values in the eeprom templates, but if
-    boards have already been calibrated with incorrect values,
-    they would still be using the wrong TX power. Fix this by assigning
-    a default value in such cases.
-    
-    Cc: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-
-commit b9f268b5b01331c3c82179abca551429450e9417
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date:   Wed Jan 29 14:22:27 2014 +0100
+commit 6fb7eefaa4d8377e6b124435059656dd6f643e91
+Author: Karl Beldan <karl.beldan@rivierawaves.com>
+Date:   Tue Oct 7 15:53:38 2014 +0200
 
-    cfg80211: consider existing DFS interfaces
-    
-    It was possible to break interface combinations in
-    the following way:
-    
-     combo 1: iftype = AP, num_ifaces = 2, num_chans = 2,
-     combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20
-    
-    With the above interface combinations it was
-    possible to:
-    
-     step 1. start AP on DFS channel by matching combo 2
-     step 2. start AP on non-DFS channel by matching combo 1
-    
-    This was possible beacuse (step 2) did not consider
-    if other interfaces require radar detection.
+    mac80211/trivial: fix typo in starting baserate for rts_cts_rate_idx
     
-    The patch changes how cfg80211 tracks channels -
-    instead of channel itself now a complete chandef
-    is stored.
-    
-    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Fixes: 5253ffb8 ("mac80211: always pick a basic rate to tx RTS/CTS for pre-HT rates")
+    Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
 
-commit bc9c62f5f511cc395c62dbf4cdd437f23db53b28
-Author: Antonio Quartulli <antonio@open-mesh.com>
-Date:   Wed Jan 29 17:53:43 2014 +0100
+commit b18111d911980af52bead74ee45250cc96ad5108
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Tue Oct 7 10:14:37 2014 +0530
 
-    cfg80211: fix channel configuration in IBSS join
+    ath9k: Fix crash in MCC mode
     
-    When receiving an IBSS_JOINED event select the BSS object
-    based on the {bssid, channel} couple rather than the bssid
-    only.
-    With the current approach if another cell having the same
-    BSSID (but using a different channel) exists then cfg80211
-    picks up the wrong BSS object.
-    The result is a mismatching channel configuration between
-    cfg80211 and the driver, that can lead to any sort of
-    problem.
+    When a channel context is removed, the hw_queue_base
+    is set to -1, this will result in a panic because
+    ath9k_chanctx_stop_queues() can be called on an interface
+    that is not assigned to any context yet - for example,
+    when trying to scan.
     
-    The issue can be triggered by having an IBSS sitting on
-    given channel and then asking the driver to create a new
-    cell using the same BSSID but with a different frequency.
-    By passing the channel to cfg80211_get_bss() we can solve
-    this ambiguity and retrieve/create the correct BSS object.
-    All the users of cfg80211_ibss_joined() have been changed
-    accordingly.
+    Fix this issue by setting the hw_queue_base to zero
+    when a channel context is removed.
     
-    Moreover WARN when cfg80211_ibss_joined() gets a NULL
-    channel as argument and remove a bogus call of the same
-    function in ath6kl (it does not make sense to call
-    cfg80211_ibss_joined() with a zero BSSID on ibss-leave).
-    
-    Cc: Kalle Valo <kvalo@qca.qualcomm.com>
-    Cc: Arend van Spriel <arend@broadcom.com>
-    Cc: Bing Zhao <bzhao@marvell.com>
-    Cc: Jussi Kivilinna <jussi.kivilinna@iki.fi>
-    Cc: libertas-dev@lists.infradead.org
-    Acked-by: Kalle Valo <kvalo@qca.qualcomm.com>
-    Signed-off-by: Antonio Quartulli <antonio@open-mesh.com>
-    [minor code cleanup in ath6kl]
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit 7e0c41cb41f215aba2c39b1c237bb4d42ec49a85
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Fri Jan 24 14:41:44 2014 +0100
+commit e2cba8d7590e76661e86f1f0987ef9f8c13c9a6d
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Thu Oct 2 06:33:20 2014 +0530
 
-    mac80211: fix bufferable MMPDU RX handling
+    ath9k: Fix flushing in MCC mode
     
-    Action, disassoc and deauth frames are bufferable, and as such don't
-    have the PM bit in the frame control field reserved which means we
-    need to react to the bit when receiving in such a frame.
+    When we are attempting to switch to a new
+    channel context, the TX queues are flushed, but
+    the mac80211 queues are not stopped and traffic
+    can still come down to the driver.
     
-    Fix this by introducing a new helper ieee80211_is_bufferable_mmpdu()
-    and using it for the RX path that currently ignores the PM bit in
-    any non-data frames for doze->wake transitions, but listens to it in
-    all frames for wake->doze transitions, both of which are wrong.
+    This patch fixes it by stopping the queues
+    assigned to the current context/vif before
+    trying to flush.
     
-    Also use the new helper in the TX path to clean up the code.
-    
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit fc0df6d2343636e3f48a069330d5b972e3d8659d
-Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-Date:   Fri Jan 24 14:29:21 2014 +0100
+commit 5ba8d9d2f018f2c4e23f9e68b90ca5b9d5470457
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Thu Oct 2 06:33:19 2014 +0530
 
-    cfg80211: set preset_chandef after channel switch
+    ath9k: Fix queue handling for channel contexts
     
-    Set preset_chandef in channel switch notification.
-    In other case we will have old preset_chandef.
+    When a full chip reset is done, all the queues
+    across all VIFs are stopped, but if MCC is enabled,
+    only the queues of the current context is awakened,
+    when we complete the reset.
     
-    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit cdec895e2344987ff171cece96e25d7407a3ebf6
-Author: Simon Wunderlich <simon@open-mesh.com>
-Date:   Fri Jan 24 23:48:29 2014 +0100
-
-    mac80211: send ibss probe responses with noack flag
+    This results in unfairness for the inactive context.
+    Since frames are queued internally in the driver if
+    there is a context mismatch, we can awaken all the
+    queues when coming out of a reset.
     
-    Responding to probe requests for scanning clients will often create
-    excessive retries, as it happens quite often that the scanning client
-    already left the channel. Therefore do it like hostapd and send probe
-    responses for wildcard SSID only once by using the noack flag.
+    The VIF-specific queues are still used in flow control,
+    to ensure fairness when traffic is high.
     
-    Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
-    [fix typo & 'wildcard SSID' in commit log]
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit 0b865d1e6b9c05052adae9315df7cb195dc60c3b
-Author: Luciano Coelho <luciano.coelho@intel.com>
-Date:   Tue Jan 28 17:09:08 2014 +0200
+commit a064eaa10ca4ec58d5a405c9a7f87efc6d2fa423
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Thu Oct 2 06:33:18 2014 +0530
 
-    mac80211: ibss: remove unnecessary call to release channel
+    ath9k: Add ath9k_chanctx_stop_queues()
     
-    The ieee80211_vif_use_channel() function calls
-    ieee80211_vif_release_channel(), so there's no need to call it
-    explicitly in __ieee80211_sta_join_ibss().
+    This can be used when the queues of a context
+    needs to be stopped.
     
-    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit e1b6c17e971f0a51ff86c2dac2584c63cd999cd7
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date:   Wed Jan 29 07:56:21 2014 +0100
+commit b39031536aab9cb1324328cf46fa4ef940bd975f
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Thu Oct 2 06:33:17 2014 +0530
 
-    mac80211: add missing CSA locking
+    ath9k: Pass context to ath9k_chanctx_wake_queues()
     
-    The patch adds a missing sdata lock and adds a few
-    lockdeps for easier maintenance.
+    Change the ath9k_chanctx_wake_queues() API so
+    that we can pass the channel context that needs its
+    queues to be stopped.
     
-    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit ad17ba7d14d225b109b73c177cd446afb8050598
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date:   Wed Jan 29 07:56:20 2014 +0100
+commit 4f82eecf73019c27537f65c160e90385e159afd8
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Thu Oct 2 06:33:16 2014 +0530
 
-    mac80211: fix sdata->radar_required locking
+    ath9k: Fix queue handling in flush()
     
-    radar_required setting wasn't protected by
-    local->mtx in some places. This should prevent
-    from scanning/radar detection/roc colliding.
+    When draining of the TX queues fails, a
+    full HW reset is done. ath_reset() makes sure
+    that the queues in mac80211 are restarted,
+    so there is no need to wake them up again.
     
-    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit 5fcd5f1808813a3d9e502fd756e01bee8a79c85d
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date:   Wed Jan 29 07:56:19 2014 +0100
+commit 60913f4d2951f6410eed969aae4717c7ced37044
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Thu Oct 2 06:33:15 2014 +0530
 
-    mac80211: move csa_active setting in STA CSA
+    ath9k: Remove duplicate code
     
-    The sdata->vif.csa_active could be left set after,
-    e.g. channel context constraints check fail in STA
-    mode leaving the interface in a strange state for
-    a brief period of time until it is disconnected.
-    This was harmless but ugly.
+    ath9k_has_tx_pending() can be used to
+    check if there are pending frames instead
+    of having duplicate code.
     
-    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-    Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit e486da4b7eed71821c6b4c1bb9ac62ffd3ab13e9
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date:   Wed Jan 29 07:56:18 2014 +0100
+commit fc1314c75e0558c03cb434e2af2c257caa201e76
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Thu Oct 2 06:33:14 2014 +0530
 
-    mac80211: fix possible memory leak on AP CSA failure
+    ath9k: Fix pending frame check
     
-    If CSA for AP interface failed and the interface
-    was not stopped afterwards another CSA request
-    would leak sdata->u.ap.next_beacon.
+    Checking for the queue depth outside of
+    the TX queue lock is incorrect and in this
+    case, is not required since it is done inside
+    ath9k_has_pending_frames().
     
-    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-    Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit 3a77ba08940682bf3d52cf14f980337324af9d4a
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Sat Feb 1 00:33:29 2014 +0100
+commit b736728575af03488388e84fceac7bf0eac5dbb6
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Thu Oct 2 06:33:13 2014 +0530
 
-    mac80211: fix fragmentation code, particularly for encryption
-    
-    The "new" fragmentation code (since my rewrite almost 5 years ago)
-    erroneously sets skb->len rather than using skb_trim() to adjust
-    the length of the first fragment after copying out all the others.
-    This leaves the skb tail pointer pointing to after where the data
-    originally ended, and thus causes the encryption MIC to be written
-    at that point, rather than where it belongs: immediately after the
-    data.
+    ath9k: Check pending frames properly
     
-    The impact of this is that if software encryption is done, then
-     a) encryption doesn't work for the first fragment, the connection
-        becomes unusable as the first fragment will never be properly
-        verified at the receiver, the MIC is practically guaranteed to
-        be wrong
-     b) we leak up to 8 bytes of plaintext (!) of the packet out into
-        the air
+    There is no need to check if the current
+    channel context has active ACs queued up
+    if the TX queue is not empty.
     
-    This is only mitigated by the fact that many devices are capable
-    of doing encryption in hardware, in which case this can't happen
-    as the tail pointer is irrelevant in that case. Additionally,
-    fragmentation is not used very frequently and would normally have
-    to be configured manually.
-    
-    Fix this by using skb_trim() properly.
-    
-    Cc: stable@vger.kernel.org
-    Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation")
-    Reported-by: Jouni Malinen <j@w1.fi>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit de5f242e0c10e841017e37eb8c38974a642dbca8
+commit 4b60af4ab4363bd79eeba94bb6bed396cf2aaf62
 Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date:   Tue Jan 28 06:21:59 2014 +0530
+Date:   Thu Oct 2 06:33:12 2014 +0530
 
-    ath9k: Fix build error on ARM
-    
-    Use mdelay instead of udelay to fix this error:
-    
-    ERROR: "__bad_udelay" [drivers/net/wireless/ath/ath9k/ath9k_hw.ko] undefined!
-    make[1]: *** [__modpost] Error 1
-    make: *** [modules] Error 2
+    ath9k: Print RoC expiration
     
-    Reported-by: Josh Boyer <jwboyer@fedoraproject.org>
     Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit 8e3ea7a51dfc61810fcefd947f6edcf61125252a
-Author: Geert Uytterhoeven <geert@linux-m68k.org>
-Date:   Sun Jan 26 11:53:21 2014 +0100
+commit 4d9f634b02e4240f86719f30e4c9e62f6a4c4d36
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Tue Sep 30 14:15:23 2014 +0530
 
-    ath9k: Fix uninitialized variable in ath9k_has_tx_pending()
-    
-    drivers/net/wireless/ath/ath9k/main.c: In function ‘ath9k_has_tx_pending’:
-    drivers/net/wireless/ath/ath9k/main.c:1869: warning: ‘npend’ may be used uninitialized in this function
+    ath9k: Check early for HW reset
     
-    Introduced by commit 10e2318103f5941aa70c318afe34bc41f1b98529 ("ath9k:
-    optimize ath9k_flush").
+    chan_lock is not required for checking if
+    we are in the middle of a HW reset, so do it
+    early. This also removes the small window
+    where the lock is dropped and reacquired.
     
-    Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6
-Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-Date:   Mon Jan 27 11:07:42 2014 +0200
+commit c393d179924685d5c8c72446c5b6401f25fdb2a0
+Author: Marek Puzyniak <marek.puzyniak@tieto.com>
+Date:   Tue Oct 7 17:04:30 2014 +0200
 
-    mac80211: release the channel in error path in start_ap
+    ath9k_htc: avoid kernel panic in ath9k_hw_reset
     
-    When the driver cannot start the AP or when the assignement
-    of the beacon goes wrong, we need to unassign the vif.
+    hw pointer of ath_hw is not assigned to proper value
+    in function ath9k_hw_reset what finally causes kernel panic.
+    This can be solved by proper initialization of ath_hw in
+    ath9k_init_priv.
     
-    Cc: stable@vger.kernel.org
-    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Marek Puzyniak <marek.puzyniak@tieto.com>
+    Acked-by: Oleksij Rempel <linux@rempel-privat.de>
+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
 
-commit dfb6889a75c601aedb7450b7e606668e77da6679
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Wed Jan 22 11:14:19 2014 +0200
+commit 065e0b64f71632f5ad7f00c102fde09c534cfbf0
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Tue Sep 30 11:00:33 2014 +0200
 
-    cfg80211: send scan results from work queue
-    
-    Due to the previous commit, when a scan finishes, it is in theory
-    possible to hit the following sequence:
-     1. interface starts being removed
-     2. scan is cancelled by driver and cfg80211 is notified
-     3. scan done work is scheduled
-     4. interface is removed completely, rdev->scan_req is freed,
-        event sent to userspace but scan done work remains pending
-     5. new scan is requested on another virtual interface
-     6. scan done work runs, freeing the still-running scan
+    ath9k: fix getting tx duration for dynack
     
-    To fix this situation, hang on to the scan done message and block
-    new scans while that is the case, and only send the message from
-    the work function, regardless of whether the scan_req is already
-    freed from interface removal. This makes step 5 above impossible
-    and changes step 6 to be
-     5. scan done work runs, sending the scan done message
+    On AR9003, tx control and tx status are in separate descriptor rings.
+    Tx duration is extracted from the tx control descriptor data, which
+    ar9003_hw_proc_txdesc cannot access.
     
-    As this can't work for wext, so we send the message immediately,
-    but this shouldn't be an issue since we still return -EBUSY.
+    Fix getting the duration by adding a separate callback for it.
     
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Acked-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit 45b7ab41fc08627d9a8428cb413d5d84662a9707
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Wed Jan 22 11:14:18 2014 +0200
+commit fdf9a4517b60d847b9bc0a30249efd96559fa450
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Tue Sep 9 09:48:30 2014 +0200
 
-    cfg80211: fix scan done race
+    ath9k_hw: fix PLL clock initialization for newer SoC
     
-    When an interface/wdev is removed, any ongoing scan should be
-    cancelled by the driver. This will make it call cfg80211, which
-    only queues a work struct. If interface/wdev removal is quick
-    enough, this can leave the scan request pending and processed
-    only after the interface is gone, causing a use-after-free.
+    On AR934x and newer SoC devices, the layout of the AR_RTC_PLL_CONTROL
+    register changed. This currently breaks at least 5/10 MHz operation.
+    AR933x uses the old layout.
     
-    Fix this by making sure the scan request is not pending after
-    the interface is destroyed. We can't flush or cancel the work
-    item due to locking concerns, but when it'll run it shouldn't
-    find anything to do. This leaves a potential issue, if a new
-    scan gets requested before the work runs, it prematurely stops
-    the running scan, potentially causing another crash. I'll fix
-    that in the next patch.
+    It might also have been causing other stability issues because of the
+    different location of the PLL_BYPASS bit which needs to be set during
+    PLL clock initialization.
     
-    This was particularly observed with P2P_DEVICE wdevs, likely
-    because freeing them is quicker than freeing netdevs.
+    This patch also removes more instances of hardcoded register values in
+    favor of properly computed ones with the PLL_BYPASS bit added.
     
-    Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
-    Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans")
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Reported-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit ae04fa489ab31b5a10d3cc8399f52761175d4321
-Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-Date:   Thu Jan 23 14:28:16 2014 +0200
+commit b6d1f51cd8bdc9d952147a960fbf1f261d8e4188
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon Sep 8 18:35:08 2014 +0200
 
-    mac80211: avoid deadlock revealed by lockdep
-    
-    sdata->u.ap.request_smps_work can’t be flushed synchronously
-    under wdev_lock(wdev) since ieee80211_request_smps_ap_work
-    itself locks the same lock.
-    While at it, reset the driver_smps_mode when the ap is
-    stopped to its default: OFF.
+    ath9k_hw: reduce ANI spur immunity setting on HT40 extension channel
     
-    This solves:
+    The cycpwr_thr1 value needs to be lower on the extension channel than on
+    the control channel, similar to how the register settings are programmed
+    in the initvals.
     
-    ======================================================
-    [ INFO: possible circular locking dependency detected ]
-    3.12.0-ipeer+ #2 Tainted: G           O
-    -------------------------------------------------------
-    rmmod/2867 is trying to acquire lock:
-      ((&sdata->u.ap.request_smps_work)){+.+...}, at: [<c105b8d0>] flush_work+0x0/0x90
+    Also drop the unnecessary check for HT40 - this register can always be
+    written. This patch has been reported to improve HT40 stability and
+    throughput in some environments.
     
-    but task is already holding lock:
-      (&wdev->mtx){+.+.+.}, at: [<f9b32626>] cfg80211_stop_ap+0x26/0x230 [cfg80211]
-    
-    which lock already depends on the new lock.
-    
-    the existing dependency chain (in reverse order) is:
-    
-    -> #1 (&wdev->mtx){+.+.+.}:
-            [<c10aefa9>] lock_acquire+0x79/0xe0
-            [<c1607a1a>] mutex_lock_nested+0x4a/0x360
-            [<fb06288b>] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211]
-            [<c105cdd8>] process_one_work+0x198/0x450
-            [<c105d469>] worker_thread+0xf9/0x320
-            [<c10669ff>] kthread+0x9f/0xb0
-            [<c1613397>] ret_from_kernel_thread+0x1b/0x28
-    
-    -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}:
-            [<c10ae9df>] __lock_acquire+0x183f/0x1910
-            [<c10aefa9>] lock_acquire+0x79/0xe0
-            [<c105b917>] flush_work+0x47/0x90
-            [<c105d867>] __cancel_work_timer+0x67/0xe0
-            [<c105d90f>] cancel_work_sync+0xf/0x20
-            [<fb0765cc>] ieee80211_stop_ap+0x8c/0x340 [mac80211]
-            [<f9b3268c>] cfg80211_stop_ap+0x8c/0x230 [cfg80211]
-            [<f9b0d8f9>] cfg80211_leave+0x79/0x100 [cfg80211]
-            [<f9b0da72>] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211]
-            [<c160f2c9>] notifier_call_chain+0x59/0x130
-            [<c106c6de>] __raw_notifier_call_chain+0x1e/0x30
-            [<c106c70f>] raw_notifier_call_chain+0x1f/0x30
-            [<c14f8213>] call_netdevice_notifiers_info+0x33/0x70
-            [<c14f8263>] call_netdevice_notifiers+0x13/0x20
-            [<c14f82a4>] __dev_close_many+0x34/0xb0
-            [<c14f83fe>] dev_close_many+0x6e/0xc0
-            [<c14f9c77>] rollback_registered_many+0xa7/0x1f0
-            [<c14f9dd4>] unregister_netdevice_many+0x14/0x60
-            [<fb06f4d9>] ieee80211_remove_interfaces+0xe9/0x170 [mac80211]
-            [<fb055116>] ieee80211_unregister_hw+0x56/0x110 [mac80211]
-            [<fa3e9396>] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm]
-            [<f9b9d8ca>] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi]
-            [<f9b9d96f>] iwl_opmode_deregister+0x6f/0x90 [iwlwifi]
-            [<fa405179>] __exit_compat+0xd/0x19 [iwlmvm]
-            [<c10b8bf9>] SyS_delete_module+0x179/0x2b0
-            [<c1613421>] sysenter_do_call+0x12/0x32
-    
-    Fixes: 687da132234f ("mac80211: implement SMPS for AP")
-    Cc: <stable@vger.kernel.org> [3.13]
-    Reported-by: Ilan Peer <ilan.peer@intel.com>
-    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit 178b205e96217164fd7c30113464250d0b6f5eca
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Thu Jan 23 16:32:29 2014 +0100
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-    cfg80211: re-enable 5/10 MHz support
-    
-    Unfortunately I forgot this during the merge window, but the
-    patch seems small enough to go in as a fix. The userspace API
-    bug that was the reason for disabling it has long been fixed.
-    
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61
-Author: Pontus Fuchs <pontus.fuchs@gmail.com>
-Date:   Thu Jan 16 15:00:40 2014 +0100
+commit 5ad2dfbaa19aa45d29184d30c8c5dae0e110074a
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon Sep 8 18:31:26 2014 +0200
 
-    nl80211: Reset split_start when netlink skb is exhausted
+    Revert "ath9k_hw: reduce ANI firstep range for older chips"
     
-    When the netlink skb is exhausted split_start is left set. In the
-    subsequent retry, with a larger buffer, the dump is continued from the
-    failing point instead of from the beginning.
+    This reverts commit 09efc56345be4146ab9fc87a55c837ed5d6ea1ab
     
-    This was causing my rt28xx based USB dongle to now show up when
-    running "iw list" with an old iw version without split dump support.
+    I've received reports that this change is decreasing throughput in some
+    rare conditions on an AR9280 based device
     
     Cc: stable@vger.kernel.org
-    Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps")
-    Signed-off-by: Pontus Fuchs <pontus.fuchs@gmail.com>
-    [avoid the entire workaround when state->split is set]
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4
-Author: Eliad Peller <eliad@wizery.com>
-Date:   Sun Jan 12 11:06:37 2014 +0200
+commit 4c82fc569cf2f29e6c66d98ef4a1b0f3b6a98e9d
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Sep 27 22:39:27 2014 +0200
 
-    mac80211: move roc cookie assignment earlier
+    ath9k_hw: disable hardware ad-hoc flag on ar934x rev 3
     
-    ieee80211_start_roc_work() might add a new roc
-    to existing roc, and tell cfg80211 it has already
-    started.
+    On AR934x rev 3, settin the ad-hoc flag completely messes up hardware
+    state - beacons get stuck, almost no packets make it out, hardware is
+    constantly reset.
     
-    However, this might happen before the roc cookie
-    was set, resulting in REMAIN_ON_CHANNEL (started)
-    event with null cookie. Consequently, it can make
-    wpa_supplicant go out of sync.
+    When leaving out that flag and setting up the hw like in AP mode, TSF
+    timers won't be automatically synced, but at least the rest works.
     
-    Fix it by setting the roc cookie earlier.
+    AR934x rev 2 and older are not affected by this bug
     
-    Cc: stable@vger.kernel.org
-    Signed-off-by: Eliad Peller <eliad@wizery.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Fri Jan 24 14:06:29 2014 +0100
+commit ecfb4b3fff006372ac5c40871f9bb182fd00444f
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Sep 27 22:15:43 2014 +0200
 
-    nl80211: send event when AP operation is stopped
-    
-    There are a few cases, e.g. suspend, where an AP interface is
-    stopped by the kernel rather than by userspace request, most
-    commonly when suspending. To let userspace know about this,
-    send the NL80211_CMD_STOP_AP command as an event every time
-    an AP interface is stopped. This also happens when userspace
-    did in fact request the AP stop, but that's not a problem.
+    ath9k: use ah->get_mac_revision for all SoC devices if available
     
-    For full-MAC drivers this may need to be extended to also
-    cover cases where the device stopped the AP operation for
-    some reason, this a bit more complicated because then all
-    cfg80211 state also needs to be reset; such API is not part
-    of this patch.
+    It is needed for AR934x as well
     
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit d5d567eda7704f190379ca852a8f9a4112e3eee3
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Thu Jan 23 16:20:29 2014 +0100
+commit c11113bc25df22898fb995d3205bdc4f27c98073
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Sep 27 18:04:58 2014 +0200
 
-    mac80211: add length check in ieee80211_is_robust_mgmt_frame()
+    ath5k: add missing include for debug code
     
-    A few places weren't checking that the frame passed to the
-    function actually has enough data even though the function
-    clearly documents it must have a payload byte. Make this
-    safer by changing the function to take an skb and checking
-    the length inside. The old version is preserved for now as
-    the rtl* drivers use it and don't have a correct skb.
+    Needed for calling vmalloc()/vfree()
     
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit f8f6d212a047fc65c7d3442dfc038f65517236fc
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Fri Jan 24 10:53:53 2014 +0100
+commit 83f76a9f9a42773c7eef90bb86b4b2c16b0b3755
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Sep 27 15:58:51 2014 +0200
 
-    nl80211: fix scheduled scan RSSI matchset attribute confusion
-    
-    The scheduled scan matchsets were intended to be a list of filters,
-    with the found BSS having to pass at least one of them to be passed
-    to the host. When the RSSI attribute was added, however, this was
-    broken and currently wpa_supplicant adds that attribute in its own
-    matchset; however, it doesn't intend that to mean that anything
-    that passes the RSSI filter should be passed to the host, instead
-    it wants it to mean that everything needs to also have higher RSSI.
+    ath5k: fix AHB kconfig dependency
     
-    This is semantically problematic because we have a list of filters
-    like [ SSID1, SSID2, SSID3, RSSI ] with no real indication which
-    one should be OR'ed and which one AND'ed.
-    
-    To fix this, move the RSSI filter attribute into each matchset. As
-    we need to stay backward compatible, treat a matchset with only the
-    RSSI attribute as a "default RSSI filter" for all other matchsets,
-    but only if there are other matchsets (an RSSI-only matchset by
-    itself is still desirable.)
-    
-    To make driver implementation easier, keep a global min_rssi_thold
-    for the entire request as well. The only affected driver is ath6kl.
-    
-    I found this when I looked into the code after Raja Mani submitted
-    a patch fixing the n_match_sets calculation to disregard the RSSI,
-    but that patch didn't address the semantic issue.
-    
-    Reported-by: Raja Mani <rmani@qti.qualcomm.com>
-    Acked-by: Luciano Coelho <luciano.coelho@intel.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit de553e8545e65a6dc4e45f43df7e1443d4291922
-Author: Johannes Berg <johannes.berg@intel.com>
-Date:   Fri Jan 24 10:17:47 2014 +0100
+commit ddd67f2a5cfd73fad4b78190025402d419b9f0a9
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Sep 27 15:57:09 2014 +0200
 
-    nl80211: check nla_parse() return values
-    
-    If there's a policy, then nla_parse() return values must be
-    checked, otherwise the policy is useless and there's nothing
-    that ensures the attributes are actually what we expect them
-    to be.
+    Revert "ath5k: Remove AHB bus support"
     
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit 652204a0733e9e1c54661d6f9d36e2e1e3b22bb1
-Author: Karl Beldan <karl.beldan@rivierawaves.com>
-Date:   Thu Jan 23 20:06:34 2014 +0100
+    This reverts commit 093ec3c5337434f40d77c1af06c139da3e5ba6dc.
 
-    mac80211: send {ADD,DEL}BA on AC_VO like other mgmt frames, as per spec
-    
-    ATM, {ADD,DEL}BA and BAR frames are sent on the AC matching the TID of
-    the BA parameters. In the discussion [1] about this patch, Johannes
-    recalled that it fixed some races with the DELBA and indeed this
-    behavior was introduced in [2].
-    While [2] is right for the BARs, the part queueing the {ADD,DEL}BAs on
-    their BA params TID AC violates the spec and is more a workaround for
-    some drivers. Helmut expressed some concerns wrt such drivers, in
-    particular DELBAs in rt2x00.
-    
-    ATM, DELBAs are sent after a driver has called (hence "purposely")
-    ieee80211_start_tx_ba_cb_irqsafe and Johannes and Emmanuel gave some
-    details wrt intentions behind the split of the IEEE80211_AMPDU_TX_STOP_*
-    given to the driver ampdu_action supposed to call this function, which
-    could prove handy to people trying to do the right thing in faulty
-    drivers (if their fw/hw don't get in their way).
-    
-    [1] http://mid.gmane.org/1390391564-18481-1-git-send-email-karl.beldan@gmail.com
-    [2] Commit: cf6bb79ad828 ("mac80211: Use appropriate TID for sending BAR, ADDBA and DELBA frames")
-    
-    Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
-    Cc: Helmut Schaa <helmut.schaa@googlemail.com>
-    Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
-+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
-@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struc
-       if (nw_type & ADHOC_NETWORK) {
-               ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
-                          nw_type & ADHOC_CREATOR ? "creator" : "joiner");
--              cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
-+              cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
-               cfg80211_put_bss(ar->wiphy, bss);
-               return;
-       }
-@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(st
-       }
-       if (vif->nw_type & ADHOC_NETWORK) {
--              if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
-+              if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
-                       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
-                                  "%s: ath6k not in ibss mode\n", __func__);
--                      return;
--              }
--              memset(bssid, 0, ETH_ALEN);
--              cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
-               return;
-       }
-@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(s
-       struct ath6kl_vif *vif = netdev_priv(dev);
-       u16 interval;
-       int ret, rssi_thold;
-+      int n_match_sets = request->n_match_sets;
-+
-+      /*
-+       * If there's a matchset w/o an SSID, then assume it's just for
-+       * the RSSI (nothing else is currently supported) and ignore it.
-+       * The device only supports a global RSSI filter that we set below.
-+       */
-+      if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
-+              n_match_sets = 0;
-       if (ar->state != ATH6KL_STATE_ON)
-               return -EIO;
-@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(s
-       ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
-                                     request->n_ssids,
-                                     request->match_sets,
--                                    request->n_match_sets);
-+                                    n_match_sets);
-       if (ret < 0)
-               return ret;
--      if (!request->n_match_sets) {
-+      if (!n_match_sets) {
-               ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
-                                              ALL_BSS_FILTER, 0);
-               if (ret < 0)
-@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(s
-       if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
-                    ar->fw_capabilities)) {
--              if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
-+              if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
-                       rssi_thold = 0;
--              else if (request->rssi_thold < -127)
-+              else if (request->min_rssi_thold < -127)
-                       rssi_thold = -127;
-               else
--                      rssi_thold = request->rssi_thold;
-+                      rssi_thold = request->min_rssi_thold;
-               ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
-                                                    rssi_thold);
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct at
-       if (AR_SREV_9300_20_OR_LATER(ah))
-               udelay(50);
-       else if (AR_SREV_9100(ah))
--              udelay(10000);
-+              mdelay(10);
-       else
-               udelay(100);
-@@ -2051,9 +2051,8 @@ static bool ath9k_hw_set_power_awake(str
-       REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
-                   AR_RTC_FORCE_WAKE_EN);
--
-       if (AR_SREV_9100(ah))
--              udelay(10000);
-+              mdelay(10);
-       else
-               udelay(50);
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str
- static bool ath9k_has_tx_pending(struct ath_softc *sc)
- {
--      int i, npend;
-+      int i, npend = 0;
-       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-               if (!ATH_TXQ_SETUP(sc, i))
---- a/drivers/net/wireless/iwlwifi/mvm/scan.c
-+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
-@@ -595,6 +595,9 @@ static void iwl_scan_offload_build_ssid(
-        * config match list.
-        */
-       for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) {
-+              /* skip empty SSID matchsets */
-+              if (!req->match_sets[i].ssid.ssid_len)
-+                      continue;
-               scan->direct_scan[i].id = WLAN_EID_SSID;
-               scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
-               memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
---- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
-+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
-@@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80
-                       /* During testing, hdr was NULL */
-                       return false;
-               }
--              if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
-+              if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
-                   (ieee80211_has_protected(hdr->frame_control)))
-                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
-               else
---- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
-+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
-@@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80
-                       /* In testing, hdr was NULL here */
-                       return false;
-               }
--              if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
-+              if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
-                   (ieee80211_has_protected(hdr->frame_control)))
-                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
-               else
---- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
-+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
-@@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80
-                       /* during testing, hdr was NULL here */
-                       return false;
-               }
--              if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
-+              if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
-                       (ieee80211_has_protected(hdr->frame_control)))
-                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
-               else
---- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
-+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
-@@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee
-                       /* during testing, hdr could be NULL here */
-                       return false;
-               }
--              if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
-+              if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
-                       (ieee80211_has_protected(hdr->frame_control)))
-                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
-               else
---- a/include/linux/ieee80211.h
-+++ b/include/linux/ieee80211.h
-@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullf
- }
- /**
-+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
-+ * @fc: frame control field in little-endian byteorder
+--- a/drivers/net/wireless/ath/ath5k/Kconfig
++++ b/drivers/net/wireless/ath/ath5k/Kconfig
+@@ -2,12 +2,14 @@ config ATH5K
+       tristate "Atheros 5xxx wireless cards support"
+       depends on m
+       depends on PCI && MAC80211
++      depends on (PCI || ATHEROS_AR231X) && MAC80211
+       select ATH_COMMON
+       select MAC80211_LEDS
+       select BACKPORT_LEDS_CLASS
+       select BACKPORT_NEW_LEDS
+       select BACKPORT_AVERAGE
+-      select ATH5K_PCI
++      select ATH5K_AHB if ATHEROS_AR231X
++      select ATH5K_PCI if !ATHEROS_AR231X
+       ---help---
+         This module adds support for wireless adapters based on
+         Atheros 5xxx chipset.
+@@ -52,9 +54,16 @@ config ATH5K_TRACER
+         If unsure, say N.
++config ATH5K_AHB
++      bool "Atheros 5xxx AHB bus support"
++      depends on ATHEROS_AR231X
++      ---help---
++        This adds support for WiSoC type chipsets of the 5xxx Atheros
++        family.
++
+ config ATH5K_PCI
+       bool "Atheros 5xxx PCI bus support"
+-      depends on PCI
++      depends on !ATHEROS_AR231X
+       ---help---
+         This adds support for PCI type chipsets of the 5xxx Atheros
+         family.
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath5k/ahb.c
+@@ -0,0 +1,234 @@
++/*
++ * Copyright (c) 2008-2009 Atheros Communications Inc.
++ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 + */
-+static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
++
++#include <linux/nl80211.h>
++#include <linux/platform_device.h>
++#include <linux/etherdevice.h>
++#include <linux/export.h>
++#include <ar231x_platform.h>
++#include "ath5k.h"
++#include "debug.h"
++#include "base.h"
++#include "reg.h"
++
++/* return bus cachesize in 4B word units */
++static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
 +{
-+      /* IEEE 802.11-2012, definition of "bufferable management frame";
-+       * note that this ignores the IBSS special case. */
-+      return ieee80211_is_mgmt(fc) &&
-+             (ieee80211_is_action(fc) ||
-+              ieee80211_is_disassoc(fc) ||
-+              ieee80211_is_deauth(fc));
++      *csz = L1_CACHE_BYTES >> 2;
 +}
 +
-+/**
-  * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
-  * @seq_ctrl: frame sequence control bytes in little-endian byteorder
-  */
-@@ -2192,10 +2206,10 @@ static inline u8 *ieee80211_get_DA(struc
- }
- /**
-- * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
-+ * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
-  * @hdr: the frame (buffer must include at least the first octet of payload)
-  */
--static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
-+static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
- {
-       if (ieee80211_is_disassoc(hdr->frame_control) ||
-           ieee80211_is_deauth(hdr->frame_control))
-@@ -2224,6 +2238,17 @@ static inline bool ieee80211_is_robust_m
- }
- /**
-+ * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
-+ * @skb: the skb containing the frame, length will be checked
-+ */
-+static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
++static bool
++ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 +{
-+      if (skb->len < 25)
++      struct ath5k_hw *ah = common->priv;
++      struct platform_device *pdev = to_platform_device(ah->dev);
++      struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
++      u16 *eeprom, *eeprom_end;
++
++      eeprom = (u16 *) bcfg->radio;
++      eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
++
++      eeprom += off;
++      if (eeprom > eeprom_end)
 +              return false;
-+      return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
++
++      *data = *eeprom;
++      return true;
 +}
 +
-+/**
-  * ieee80211_is_public_action - check if frame is a public action frame
-  * @hdr: the frame
-  * @len: length of the frame
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1395,9 +1395,11 @@ struct cfg80211_scan_request {
-  * struct cfg80211_match_set - sets of attributes to match
-  *
-  * @ssid: SSID to be matched
-+ * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
-  */
- struct cfg80211_match_set {
-       struct cfg80211_ssid ssid;
-+      s32 rssi_thold;
- };
- /**
-@@ -1420,7 +1422,8 @@ struct cfg80211_match_set {
-  * @dev: the interface
-  * @scan_start: start time of the scheduled scan
-  * @channels: channels to scan
-- * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
-+ * @min_rssi_thold: for drivers only supporting a single threshold, this
-+ *    contains the minimum over all matchsets
-  */
- struct cfg80211_sched_scan_request {
-       struct cfg80211_ssid *ssids;
-@@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request {
-       u32 flags;
-       struct cfg80211_match_set *match_sets;
-       int n_match_sets;
--      s32 rssi_thold;
-+      s32 min_rssi_thold;
-       /* internal */
-       struct wiphy *wiphy;
-@@ -3130,8 +3133,8 @@ struct cfg80211_cached_keys;
-  * @identifier: (private) Identifier used in nl80211 to identify this
-  *    wireless device if it has no netdev
-  * @current_bss: (private) Used by the internal configuration code
-- * @channel: (private) Used by the internal configuration code to track
-- *    the user-set AP, monitor and WDS channel
-+ * @chandef: (private) Used by the internal configuration code to track
-+ *    the user-set channel definition.
-  * @preset_chandef: (private) Used by the internal configuration code to
-  *    track the channel to be used for AP later
-  * @bssid: (private) Used by the internal configuration code
-@@ -3195,9 +3198,7 @@ struct wireless_dev {
-       struct cfg80211_internal_bss *current_bss; /* associated / joined */
-       struct cfg80211_chan_def preset_chandef;
--
--      /* for AP and mesh channel tracking */
--      struct ieee80211_channel *channel;
-+      struct cfg80211_chan_def chandef;
-       bool ibss_fixed;
-       bool ibss_dfs_possible;
-@@ -3879,6 +3880,7 @@ void cfg80211_michael_mic_failure(struct
-  *
-  * @dev: network device
-  * @bssid: the BSSID of the IBSS joined
-+ * @channel: the channel of the IBSS joined
-  * @gfp: allocation flags
-  *
-  * This function notifies cfg80211 that the device joined an IBSS or
-@@ -3888,7 +3890,8 @@ void cfg80211_michael_mic_failure(struct
-  * with the locally generated beacon -- this guarantees that there is
-  * always a scan result for this IBSS. cfg80211 will handle the rest.
-  */
--void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
-+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-+                        struct ieee80211_channel *channel, gfp_t gfp);
- /**
-  * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -2442,9 +2442,15 @@ enum nl80211_reg_rule_attr {
-  * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
-  * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
-  * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
-- * only report BSS with matching SSID.
-+ *    only report BSS with matching SSID.
-  * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
-- *    BSS in scan results. Filtering is turned off if not specified.
-+ *    BSS in scan results. Filtering is turned off if not specified. Note that
-+ *    if this attribute is in a match set of its own, then it is treated as
-+ *    the default value for all matchsets with an SSID, rather than being a
-+ *    matchset of its own without an RSSI filter. This is due to problems with
-+ *    how this API was implemented in the past. Also, due to the same problem,
-+ *    the only way to create a matchset with only an RSSI filter (with this
-+ *    attribute) is if there's only a single matchset with the RSSI attribute.
-  * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
-  *    attribute number currently defined
-  * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -107,7 +107,7 @@ static void ieee80211_send_addba_request
-       mgmt->u.action.u.addba_req.start_seq_num =
-                                       cpu_to_le16(start_seq_num << 4);
--      ieee80211_tx_skb_tid(sdata, skb, tid);
-+      ieee80211_tx_skb(sdata, skb);
- }
- void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wip
-       /* TODO: make hostapd tell us what it wants */
-       sdata->smps_mode = IEEE80211_SMPS_OFF;
-       sdata->needed_rx_chains = sdata->local->rx_chains;
--      sdata->radar_required = params->radar_required;
-       mutex_lock(&local->mtx);
-+      sdata->radar_required = params->radar_required;
-       err = ieee80211_vif_use_channel(sdata, &params->chandef,
-                                       IEEE80211_CHANCTX_SHARED);
-       mutex_unlock(&local->mtx);
-@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip
-                                       IEEE80211_P2P_OPPPS_ENABLE_BIT;
-       err = ieee80211_assign_beacon(sdata, &params->beacon);
--      if (err < 0)
-+      if (err < 0) {
-+              ieee80211_vif_release_channel(sdata);
-               return err;
++int ath5k_hw_read_srev(struct ath5k_hw *ah)
++{
++      struct platform_device *pdev = to_platform_device(ah->dev);
++      struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
++      ah->ah_mac_srev = bcfg->devid;
++      return 0;
++}
++
++static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
++{
++      struct platform_device *pdev = to_platform_device(ah->dev);
++      struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
++      u8 *cfg_mac;
++
++      if (to_platform_device(ah->dev)->id == 0)
++              cfg_mac = bcfg->config->wlan0_mac;
++      else
++              cfg_mac = bcfg->config->wlan1_mac;
++
++      memcpy(mac, cfg_mac, ETH_ALEN);
++      return 0;
++}
++
++static const struct ath_bus_ops ath_ahb_bus_ops = {
++      .ath_bus_type = ATH_AHB,
++      .read_cachesize = ath5k_ahb_read_cachesize,
++      .eeprom_read = ath5k_ahb_eeprom_read,
++      .eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
++};
++
++/*Initialization*/
++static int ath_ahb_probe(struct platform_device *pdev)
++{
++      struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
++      struct ath5k_hw *ah;
++      struct ieee80211_hw *hw;
++      struct resource *res;
++      void __iomem *mem;
++      int irq;
++      int ret = 0;
++      u32 reg;
++
++      if (!dev_get_platdata(&pdev->dev)) {
++              dev_err(&pdev->dev, "no platform data specified\n");
++              ret = -EINVAL;
++              goto err_out;
 +      }
-       changed |= err;
-       err = drv_start_ap(sdata->local, sdata);
-@@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wip
-               if (old)
-                       kfree_rcu(old, rcu_head);
-               RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
-+              ieee80211_vif_release_channel(sdata);
-               return err;
-       }
-@@ -1053,6 +1056,7 @@ static int ieee80211_change_beacon(struc
-       int err;
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+      sdata_assert_lock(sdata);
-       /* don't allow changing the beacon while CSA is in place - offset
-        * of channel switch counter may change
-@@ -1080,6 +1084,8 @@ static int ieee80211_stop_ap(struct wiph
-       struct probe_resp *old_probe_resp;
-       struct cfg80211_chan_def chandef;
-+      sdata_assert_lock(sdata);
 +
-       old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
-       if (!old_beacon)
-               return -ENOENT;
-@@ -1090,8 +1096,6 @@ static int ieee80211_stop_ap(struct wiph
-       kfree(sdata->u.ap.next_beacon);
-       sdata->u.ap.next_beacon = NULL;
--      cancel_work_sync(&sdata->u.ap.request_smps_work);
--
-       /* turn off carrier for this interface and dependent VLANs */
-       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
-               netif_carrier_off(vlan->dev);
-@@ -1103,6 +1107,7 @@ static int ieee80211_stop_ap(struct wiph
-       kfree_rcu(old_beacon, rcu_head);
-       if (old_probe_resp)
-               kfree_rcu(old_probe_resp, rcu_head);
-+      sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
-       __sta_info_flush(sdata, true);
-       ieee80211_free_keys(sdata, true);
-@@ -2638,6 +2643,24 @@ static int ieee80211_start_roc_work(stru
-       INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
-       INIT_LIST_HEAD(&roc->dependents);
-+      /*
-+       * cookie is either the roc cookie (for normal roc)
-+       * or the SKB (for mgmt TX)
-+       */
-+      if (!txskb) {
-+              /* local->mtx protects this */
-+              local->roc_cookie_counter++;
-+              roc->cookie = local->roc_cookie_counter;
-+              /* wow, you wrapped 64 bits ... more likely a bug */
-+              if (WARN_ON(roc->cookie == 0)) {
-+                      roc->cookie = 1;
-+                      local->roc_cookie_counter++;
-+              }
-+              *cookie = roc->cookie;
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (res == NULL) {
++              dev_err(&pdev->dev, "no memory resource found\n");
++              ret = -ENXIO;
++              goto err_out;
++      }
++
++      mem = ioremap_nocache(res->start, resource_size(res));
++      if (mem == NULL) {
++              dev_err(&pdev->dev, "ioremap failed\n");
++              ret = -ENOMEM;
++              goto err_out;
++      }
++
++      res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++      if (res == NULL) {
++              dev_err(&pdev->dev, "no IRQ resource found\n");
++              ret = -ENXIO;
++              goto err_iounmap;
++      }
++
++      irq = res->start;
++
++      hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
++      if (hw == NULL) {
++              dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
++              ret = -ENOMEM;
++              goto err_iounmap;
++      }
++
++      ah = hw->priv;
++      ah->hw = hw;
++      ah->dev = &pdev->dev;
++      ah->iobase = mem;
++      ah->irq = irq;
++      ah->devid = bcfg->devid;
++
++      if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
++              /* Enable WMAC AHB arbitration */
++              reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
++              reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
++              iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
++
++              /* Enable global WMAC swapping */
++              reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP);
++              reg |= AR5K_AR2315_BYTESWAP_WMAC;
++              iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
 +      } else {
-+              *cookie = (unsigned long)txskb;
++              /* Enable WMAC DMA access (assuming 5312 or 231x*/
++              /* TODO: check other platforms */
++              reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
++              if (to_platform_device(ah->dev)->id == 0)
++                      reg |= AR5K_AR5312_ENABLE_WLAN0;
++              else
++                      reg |= AR5K_AR5312_ENABLE_WLAN1;
++              iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
++
++              /*
++               * On a dual-band AR5312, the multiband radio is only
++               * used as pass-through. Disable 2 GHz support in the
++               * driver for it
++               */
++              if (to_platform_device(ah->dev)->id == 0 &&
++                  (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
++                   (BD_WLAN1 | BD_WLAN0))
++                      ah->ah_capabilities.cap_needs_2GHz_ovr = true;
++              else
++                      ah->ah_capabilities.cap_needs_2GHz_ovr = false;
 +      }
 +
-       /* if there's one pending or we're scanning, queue this one */
-       if (!list_empty(&local->roc_list) ||
-           local->scanning || local->radar_detect_enabled)
-@@ -2772,24 +2795,6 @@ static int ieee80211_start_roc_work(stru
-       if (!queued)
-               list_add_tail(&roc->list, &local->roc_list);
--      /*
--       * cookie is either the roc cookie (for normal roc)
--       * or the SKB (for mgmt TX)
--       */
--      if (!txskb) {
--              /* local->mtx protects this */
--              local->roc_cookie_counter++;
--              roc->cookie = local->roc_cookie_counter;
--              /* wow, you wrapped 64 bits ... more likely a bug */
--              if (WARN_ON(roc->cookie == 0)) {
--                      roc->cookie = 1;
--                      local->roc_cookie_counter++;
--              }
--              *cookie = roc->cookie;
--      } else {
--              *cookie = (unsigned long)txskb;
--      }
--
-       return 0;
- }
-@@ -3004,8 +3009,10 @@ void ieee80211_csa_finalize_work(struct 
-       if (!ieee80211_sdata_running(sdata))
-               goto unlock;
--      sdata->radar_required = sdata->csa_radar_required;
-+      sdata_assert_lock(sdata);
++      ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
++      if (ret != 0) {
++              dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
++              ret = -ENODEV;
++              goto err_free_hw;
++      }
 +
-       mutex_lock(&local->mtx);
-+      sdata->radar_required = sdata->csa_radar_required;
-       err = ieee80211_vif_change_channel(sdata, &changed);
-       mutex_unlock(&local->mtx);
-       if (WARN_ON(err < 0))
-@@ -3022,13 +3029,13 @@ void ieee80211_csa_finalize_work(struct 
-       switch (sdata->vif.type) {
-       case NL80211_IFTYPE_AP:
-               err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
-+              kfree(sdata->u.ap.next_beacon);
-+              sdata->u.ap.next_beacon = NULL;
++      platform_set_drvdata(pdev, hw);
 +
-               if (err < 0)
-                       goto unlock;
-               changed |= err;
--              kfree(sdata->u.ap.next_beacon);
--              sdata->u.ap.next_beacon = NULL;
--
-               ieee80211_bss_info_change_notify(sdata, err);
-               break;
-       case NL80211_IFTYPE_ADHOC:
-@@ -3066,7 +3073,7 @@ int ieee80211_channel_switch(struct wiph
-       struct ieee80211_if_mesh __maybe_unused *ifmsh;
-       int err, num_chanctx;
--      lockdep_assert_held(&sdata->wdev.mtx);
-+      sdata_assert_lock(sdata);
-       if (!list_empty(&local->roc_list) || local->scanning)
-               return -EBUSY;
---- a/net/mac80211/ht.c
-+++ b/net/mac80211/ht.c
-@@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee802
-       mgmt->u.action.u.delba.params = cpu_to_le16(params);
-       mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
--      ieee80211_tx_skb_tid(sdata, skb, tid);
-+      ieee80211_tx_skb(sdata, skb);
- }
- void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
-@@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(stru
-                            u.ap.request_smps_work);
-       sdata_lock(sdata);
--      __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
-+      if (sdata_dereference(sdata->u.ap.beacon, sdata))
-+              __ieee80211_request_smps_ap(sdata,
-+                                          sdata->u.ap.driver_smps_mode);
-       sdata_unlock(sdata);
- }
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee
-       ieee80211_roc_purge(local, sdata);
--      if (sdata->vif.type == NL80211_IFTYPE_STATION)
-+      switch (sdata->vif.type) {
-+      case NL80211_IFTYPE_STATION:
-               ieee80211_mgd_stop(sdata);
--
--      if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-+              break;
-+      case NL80211_IFTYPE_ADHOC:
-               ieee80211_ibss_stop(sdata);
--
-+              break;
-+      case NL80211_IFTYPE_AP:
-+              cancel_work_sync(&sdata->u.ap.request_smps_work);
-+              break;
-+      default:
-+              break;
++      return 0;
++
++ err_free_hw:
++      ieee80211_free_hw(hw);
++ err_iounmap:
++        iounmap(mem);
++ err_out:
++      return ret;
++}
++
++static int ath_ahb_remove(struct platform_device *pdev)
++{
++      struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
++      struct ieee80211_hw *hw = platform_get_drvdata(pdev);
++      struct ath5k_hw *ah;
++      u32 reg;
++
++      if (!hw)
++              return 0;
++
++      ah = hw->priv;
++
++      if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
++              /* Disable WMAC AHB arbitration */
++              reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
++              reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
++              iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
++      } else {
++              /*Stop DMA access */
++              reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
++              if (to_platform_device(ah->dev)->id == 0)
++                      reg &= ~AR5K_AR5312_ENABLE_WLAN0;
++              else
++                      reg &= ~AR5K_AR5312_ENABLE_WLAN1;
++              iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
 +      }
-       /*
-        * Remove all stations associated with this interface.
-@@ -827,7 +834,9 @@ static void ieee80211_do_stop(struct iee
-       cancel_work_sync(&local->dynamic_ps_enable_work);
-       cancel_work_sync(&sdata->recalc_smps);
-+      sdata_lock(sdata);
-       sdata->vif.csa_active = false;
-+      sdata_unlock(sdata);
-       cancel_work_sync(&sdata->csa_finalize_work);
-       cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m
- {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
--      if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1))
-+      if (is_multicast_ether_addr(hdr->addr1))
-               return 0;
--      return ieee80211_is_robust_mgmt_frame(hdr);
-+      return ieee80211_is_robust_mgmt_frame(skb);
++
++      ath5k_deinit_ah(ah);
++      iounmap(ah->iobase);
++      ieee80211_free_hw(hw);
++
++      return 0;
++}
++
++static struct platform_driver ath_ahb_driver = {
++      .probe      = ath_ahb_probe,
++      .remove     = ath_ahb_remove,
++      .driver         = {
++              .name   = "ar231x-wmac",
++              .owner  = THIS_MODULE,
++      },
++};
++
++module_platform_driver(ath_ahb_driver);
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1647,6 +1647,32 @@ static inline struct ath_regulatory *ath
+       return &(ath5k_hw_common(ah)->regulatory);
  }
  
-@@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust
++#ifdef CONFIG_ATHEROS_AR231X
++#define AR5K_AR2315_PCI_BASE  ((void __iomem *)0xb0100000)
++
++static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
++{
++      /* On AR2315 and AR2317 the PCI clock domain registers
++       * are outside of the WMAC register space */
++      if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
++          (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
++              return AR5K_AR2315_PCI_BASE + reg;
++
++      return ah->iobase + reg;
++}
++
++static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
++{
++      return ioread32(ath5k_ahb_reg(ah, reg));
++}
++
++static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
++{
++      iowrite32(val, ath5k_ahb_reg(ah, reg));
++}
++
++#else
++
+ static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
  {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
--      if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1))
-+      if (!is_multicast_ether_addr(hdr->addr1))
-               return 0;
--      return ieee80211_is_robust_mgmt_frame(hdr);
-+      return ieee80211_is_robust_mgmt_frame(skb);
+       return ioread32(ah->iobase + reg);
+@@ -1657,6 +1683,8 @@ static inline void ath5k_hw_reg_write(st
+       iowrite32(val, ah->iobase + reg);
  }
  
++#endif
++
+ static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah)
+ {
+       return ath5k_hw_common(ah)->bus_ops->ath_bus_type;
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -99,6 +99,15 @@ static int ath5k_reset(struct ath5k_hw *
+ /* Known SREVs */
+ static const struct ath5k_srev_name srev_names[] = {
++#ifdef CONFIG_ATHEROS_AR231X
++      { "5312",       AR5K_VERSION_MAC,       AR5K_SREV_AR5312_R2 },
++      { "5312",       AR5K_VERSION_MAC,       AR5K_SREV_AR5312_R7 },
++      { "2313",       AR5K_VERSION_MAC,       AR5K_SREV_AR2313_R8 },
++      { "2315",       AR5K_VERSION_MAC,       AR5K_SREV_AR2315_R6 },
++      { "2315",       AR5K_VERSION_MAC,       AR5K_SREV_AR2315_R7 },
++      { "2317",       AR5K_VERSION_MAC,       AR5K_SREV_AR2317_R1 },
++      { "2317",       AR5K_VERSION_MAC,       AR5K_SREV_AR2317_R2 },
++#else
+       { "5210",       AR5K_VERSION_MAC,       AR5K_SREV_AR5210 },
+       { "5311",       AR5K_VERSION_MAC,       AR5K_SREV_AR5311 },
+       { "5311A",      AR5K_VERSION_MAC,       AR5K_SREV_AR5311A },
+@@ -117,6 +126,7 @@ static const struct ath5k_srev_name srev
+       { "5418",       AR5K_VERSION_MAC,       AR5K_SREV_AR5418 },
+       { "2425",       AR5K_VERSION_MAC,       AR5K_SREV_AR2425 },
+       { "2417",       AR5K_VERSION_MAC,       AR5K_SREV_AR2417 },
++#endif
+       { "xxxxx",      AR5K_VERSION_MAC,       AR5K_SREV_UNKNOWN },
+       { "5110",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5110 },
+       { "5111",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5111 },
+@@ -132,6 +142,10 @@ static const struct ath5k_srev_name srev
+       { "5413",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5413 },
+       { "5424",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5424 },
+       { "5133",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5133 },
++#ifdef CONFIG_ATHEROS_AR231X
++      { "2316",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2316 },
++      { "2317",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2317 },
++#endif
+       { "xxxxx",      AR5K_VERSION_RAD,       AR5K_SREV_UNKNOWN },
+ };
  
-@@ -626,7 +626,7 @@ static int ieee80211_get_mmie_keyidx(str
-       if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
-               return -1;
--      if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr))
-+      if (!ieee80211_is_robust_mgmt_frame(skb))
-               return -1; /* not a robust management frame */
-       mmie = (struct ieee80211_mmie *)
-@@ -1311,18 +1311,15 @@ ieee80211_rx_h_sta_process(struct ieee80
-           !ieee80211_has_morefrags(hdr->frame_control) &&
-           !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
-           (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
--           rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
-+           rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
-+          /* PM bit is only checked in frames where it isn't reserved,
-+           * in AP mode it's reserved in non-bufferable management frames
-+           * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
-+           */
-+          (!ieee80211_is_mgmt(hdr->frame_control) ||
-+           ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
-               if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
--                      /*
--                       * Ignore doze->wake transitions that are
--                       * indicated by non-data frames, the standard
--                       * is unclear here, but for example going to
--                       * PS mode and then scanning would cause a
--                       * doze->wake transition for the probe request,
--                       * and that is clearly undesirable.
--                       */
--                      if (ieee80211_is_data(hdr->frame_control) &&
--                          !ieee80211_has_pm(hdr->frame_control))
-+                      if (!ieee80211_has_pm(hdr->frame_control))
-                               sta_ps_end(sta);
-               } else {
-                       if (ieee80211_has_pm(hdr->frame_control))
-@@ -1845,8 +1842,7 @@ static int ieee80211_drop_unencrypted_mg
-                * having configured keys.
-                */
-               if (unlikely(ieee80211_is_action(fc) && !rx->key &&
--                           ieee80211_is_robust_mgmt_frame(
--                                   (struct ieee80211_hdr *) rx->skb->data)))
-+                           ieee80211_is_robust_mgmt_frame(rx->skb)))
-                       return -EACCES;
-       }
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, 
-       if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
+--- a/drivers/net/wireless/ath/ath5k/led.c
++++ b/drivers/net/wireless/ath/ath5k/led.c
+@@ -163,14 +163,20 @@ int ath5k_init_leds(struct ath5k_hw *ah)
+ {
+       int ret = 0;
+       struct ieee80211_hw *hw = ah->hw;
++#ifndef CONFIG_ATHEROS_AR231X
+       struct pci_dev *pdev = ah->pdev;
++#endif
+       char name[ATH5K_LED_MAX_NAME_LEN + 1];
+       const struct pci_device_id *match;
+       if (!ah->pdev)
                return 0;
  
--      if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
--                                          skb->data))
-+      if (!ieee80211_is_robust_mgmt_frame(skb))
-               return 0;
++#ifdef CONFIG_ATHEROS_AR231X
++      match = NULL;
++#else
+       match = pci_match_id(&ath5k_led_devices[0], pdev);
++#endif
+       if (match) {
+               __set_bit(ATH_STAT_LEDSOFT, ah->status);
+               ah->led_pin = ATH_PIN(match->driver_data);
+--- a/drivers/net/wireless/ath/ath5k/debug.c
++++ b/drivers/net/wireless/ath/ath5k/debug.c
+@@ -65,6 +65,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/list.h>
++#include <linux/vmalloc.h>
+ #include "debug.h"
+ #include "ath5k.h"
+ #include "reg.h"
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -222,31 +222,28 @@ static void ath9k_hw_read_revisions(stru
+ {
+       u32 val;
  
-       return 1;
-@@ -525,9 +524,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_t
-       /* only deauth, disassoc and action are bufferable MMPDUs */
-       if (ieee80211_is_mgmt(hdr->frame_control) &&
--          !ieee80211_is_deauth(hdr->frame_control) &&
--          !ieee80211_is_disassoc(hdr->frame_control) &&
--          !ieee80211_is_action(hdr->frame_control)) {
-+          !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
-               if (tx->flags & IEEE80211_TX_UNICAST)
-                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
-               return TX_CONTINUE;
-@@ -567,7 +564,7 @@ ieee80211_tx_h_select_key(struct ieee802
-               tx->key = key;
-       else if (ieee80211_is_mgmt(hdr->frame_control) &&
-                is_multicast_ether_addr(hdr->addr1) &&
--               ieee80211_is_robust_mgmt_frame(hdr) &&
-+               ieee80211_is_robust_mgmt_frame(tx->skb) &&
-                (key = rcu_dereference(tx->sdata->default_mgmt_key)))
-               tx->key = key;
-       else if (is_multicast_ether_addr(hdr->addr1) &&
-@@ -582,12 +579,12 @@ ieee80211_tx_h_select_key(struct ieee802
-               tx->key = NULL;
-       else if (tx->skb->protocol == tx->sdata->control_port_protocol)
-               tx->key = NULL;
--      else if (ieee80211_is_robust_mgmt_frame(hdr) &&
-+      else if (ieee80211_is_robust_mgmt_frame(tx->skb) &&
-                !(ieee80211_is_action(hdr->frame_control) &&
-                  tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
-               tx->key = NULL;
-       else if (ieee80211_is_mgmt(hdr->frame_control) &&
--               !ieee80211_is_robust_mgmt_frame(hdr))
-+               !ieee80211_is_robust_mgmt_frame(tx->skb))
-               tx->key = NULL;
-       else {
-               I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
-@@ -878,7 +875,7 @@ static int ieee80211_fragment(struct iee
++      if (ah->get_mac_revision)
++              ah->hw_version.macRev = ah->get_mac_revision();
++
+       switch (ah->hw_version.devid) {
+       case AR5416_AR9100_DEVID:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9100;
+               break;
+       case AR9300_DEVID_AR9330:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9330;
+-              if (ah->get_mac_revision) {
+-                      ah->hw_version.macRev = ah->get_mac_revision();
+-              } else {
++              if (!ah->get_mac_revision) {
+                       val = REG_READ(ah, AR_SREV);
+                       ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+               }
+               return;
+       case AR9300_DEVID_AR9340:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9340;
+-              val = REG_READ(ah, AR_SREV);
+-              ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+               return;
+       case AR9300_DEVID_QCA955X:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9550;
+               return;
+       case AR9300_DEVID_AR953X:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9531;
+-              if (ah->get_mac_revision)
+-                      ah->hw_version.macRev = ah->get_mac_revision();
+               return;
        }
  
-       /* adjust first fragment's length */
--      skb->len = hdrlen + per_fragm;
-+      skb_trim(skb, hdrlen + per_fragm);
-       return 0;
- }
+@@ -704,6 +701,8 @@ static void ath9k_hw_init_pll(struct ath
+ {
+       u32 pll;
  
---- a/net/mac80211/wpa.c
-+++ b/net/mac80211/wpa.c
-@@ -499,7 +499,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
-       hdrlen = ieee80211_hdrlen(hdr->frame_control);
-       if (!ieee80211_is_data(hdr->frame_control) &&
--          !ieee80211_is_robust_mgmt_frame(hdr))
-+          !ieee80211_is_robust_mgmt_frame(skb))
-               return RX_CONTINUE;
-       data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
---- a/net/wireless/ap.c
-+++ b/net/wireless/ap.c
-@@ -27,9 +27,10 @@ static int __cfg80211_stop_ap(struct cfg
-       err = rdev_stop_ap(rdev, dev);
-       if (!err) {
-               wdev->beacon_interval = 0;
--              wdev->channel = NULL;
-+              memset(&wdev->chandef, 0, sizeof(wdev->chandef));
-               wdev->ssid_len = 0;
-               rdev_set_qos_map(rdev, dev, NULL);
-+              nl80211_send_ap_stopped(wdev);
++      pll = ath9k_hw_compute_pll_control(ah, chan);
++
+       if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
+               /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+@@ -754,7 +753,8 @@ static void ath9k_hw_init_pll(struct ath
+               REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+                             AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
+-              REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
++              REG_WRITE(ah, AR_RTC_PLL_CONTROL,
++                        pll | AR_RTC_9300_PLL_BYPASS);
+               udelay(1000);
+               /* program refdiv, nint, frac to RTC register */
+@@ -770,7 +770,8 @@ static void ath9k_hw_init_pll(struct ath
+       } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
+               u32 regval, pll2_divint, pll2_divfrac, refdiv;
+-              REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
++              REG_WRITE(ah, AR_RTC_PLL_CONTROL,
++                        pll | AR_RTC_9300_SOC_PLL_BYPASS);
+               udelay(1000);
+               REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16);
+@@ -843,7 +844,6 @@ static void ath9k_hw_init_pll(struct ath
+               udelay(1000);
        }
  
-       return err;
---- a/net/wireless/core.c
-+++ b/net/wireless/core.c
-@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg
-       rdev->opencount--;
--      WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
--              !rdev->scan_req->notified);
-+      if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-+              if (WARN_ON(!rdev->scan_req->notified))
-+                      rdev->scan_req->aborted = true;
-+              ___cfg80211_scan_done(rdev, false);
-+      }
- }
- static int cfg80211_rfkill_set_block(void *data, bool blocked)
-@@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy)
-       int i;
-       u16 ifmodes = wiphy->interface_modes;
+-      pll = ath9k_hw_compute_pll_control(ah, chan);
+       if (AR_SREV_9565(ah))
+               pll |= 0x40000;
+       REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
+@@ -1192,9 +1192,12 @@ static void ath9k_hw_set_operating_mode(
  
--      /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
--      wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
--
-       /*
-        * There are major locking problems in nl80211/mac80211 for CSA,
-        * disable for all drivers until this has been reworked.
-@@ -875,8 +875,11 @@ static int cfg80211_netdev_notifier_call
-               break;
-       case NETDEV_DOWN:
-               cfg80211_update_iface_num(rdev, wdev->iftype, -1);
--              WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
--                      !rdev->scan_req->notified);
-+              if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-+                      if (WARN_ON(!rdev->scan_req->notified))
-+                              rdev->scan_req->aborted = true;
-+                      ___cfg80211_scan_done(rdev, false);
+       switch (opmode) {
+       case NL80211_IFTYPE_ADHOC:
+-              set |= AR_STA_ID1_ADHOC;
+-              REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+-              break;
++              if (!AR_SREV_9340_13(ah)) {
++                      set |= AR_STA_ID1_ADHOC;
++                      REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
++                      break;
 +              }
++              /* fall through */
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_AP:
+               set |= AR_STA_ID1_STA_AP;
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -903,6 +903,10 @@
+ #define AR_SREV_9340(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340))
++#define AR_SREV_9340_13(_ah) \
++      (AR_SREV_9340((_ah)) && \
++       ((_ah)->hw_version.macRev == AR_SREV_REVISION_9340_13))
++
+ #define AR_SREV_9340_13_OR_LATER(_ah) \
+       (AR_SREV_9340((_ah)) && \
+        ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9340_13))
+@@ -1240,12 +1244,23 @@ enum {
+ #define AR_CH0_DPLL3_PHASE_SHIFT_S   23
+ #define AR_PHY_CCA_NOM_VAL_2GHZ      -118
++#define AR_RTC_9300_SOC_PLL_DIV_INT          0x0000003f
++#define AR_RTC_9300_SOC_PLL_DIV_INT_S        0
++#define AR_RTC_9300_SOC_PLL_DIV_FRAC         0x000fffc0
++#define AR_RTC_9300_SOC_PLL_DIV_FRAC_S       6
++#define AR_RTC_9300_SOC_PLL_REFDIV           0x01f00000
++#define AR_RTC_9300_SOC_PLL_REFDIV_S         20
++#define AR_RTC_9300_SOC_PLL_CLKSEL           0x06000000
++#define AR_RTC_9300_SOC_PLL_CLKSEL_S         25
++#define AR_RTC_9300_SOC_PLL_BYPASS           0x08000000
++
+ #define AR_RTC_9300_PLL_DIV          0x000003ff
+ #define AR_RTC_9300_PLL_DIV_S        0
+ #define AR_RTC_9300_PLL_REFDIV       0x00003C00
+ #define AR_RTC_9300_PLL_REFDIV_S     10
+ #define AR_RTC_9300_PLL_CLKSEL       0x0000C000
+ #define AR_RTC_9300_PLL_CLKSEL_S     14
++#define AR_RTC_9300_PLL_BYPASS       0x00010000
+ #define AR_RTC_9160_PLL_DIV   0x000003ff
+ #define AR_RTC_9160_PLL_DIV_S   0
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -1004,9 +1004,11 @@ static bool ar5008_hw_ani_control_new(st
+       case ATH9K_ANI_FIRSTEP_LEVEL:{
+               u32 level = param;
+-              value = level;
++              value = level * 2;
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                             AR_PHY_FIND_SIG_FIRSTEP, value);
++              REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
++                            AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
+               if (level != aniState->firstepLevel) {
+                       ath_dbg(common, ANI,
+@@ -1040,9 +1042,8 @@ static bool ar5008_hw_ani_control_new(st
+               REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+                             AR_PHY_TIMING5_CYCPWR_THR1, value);
+-              if (IS_CHAN_HT40(ah->curchan))
+-                      REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+-                                    AR_PHY_EXT_TIMING5_CYCPWR_THR1, value);
++              REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
++                                AR_PHY_EXT_TIMING5_CYCPWR_THR1, value - 1);
+               if (level != aniState->spurImmunityLevel) {
+                       ath_dbg(common, ANI,
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -517,6 +517,23 @@ static void ar9003_hw_spur_mitigate(stru
+       ar9003_hw_spur_mitigate_ofdm(ah, chan);
+ }
  
-               if (WARN_ON(rdev->sched_scan_req &&
-                           rdev->sched_scan_req->dev == wdev->netdev)) {
---- a/net/wireless/core.h
-+++ b/net/wireless/core.h
-@@ -62,6 +62,7 @@ struct cfg80211_registered_device {
-       struct rb_root bss_tree;
-       u32 bss_generation;
-       struct cfg80211_scan_request *scan_req; /* protected by RTNL */
-+      struct sk_buff *scan_msg;
-       struct cfg80211_sched_scan_request *sched_scan_req;
-       unsigned long suspend_at;
-       struct work_struct scan_done_wk;
-@@ -210,6 +211,7 @@ struct cfg80211_event {
-               } dc;
-               struct {
-                       u8 bssid[ETH_ALEN];
-+                      struct ieee80211_channel *channel;
-               } ij;
-       };
- };
-@@ -257,7 +259,8 @@ int __cfg80211_leave_ibss(struct cfg8021
-                         struct net_device *dev, bool nowext);
- int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
-                       struct net_device *dev, bool nowext);
--void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
-+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-+                          struct ieee80211_channel *channel);
- int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
-                           struct wireless_dev *wdev);
-@@ -361,7 +364,8 @@ int cfg80211_validate_key_settings(struc
-                                  struct key_params *params, int key_idx,
-                                  bool pairwise, const u8 *mac_addr);
- void __cfg80211_scan_done(struct work_struct *wk);
--void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
-+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
-+                         bool send_message);
- void __cfg80211_sched_scan_results(struct work_struct *wk);
- int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
-                              bool driver_initiated);
-@@ -441,7 +445,8 @@ static inline unsigned int elapsed_jiffi
- void
- cfg80211_get_chan_state(struct wireless_dev *wdev,
-                       struct ieee80211_channel **chan,
--                      enum cfg80211_chan_mode *chanmode);
-+                      enum cfg80211_chan_mode *chanmode,
-+                      u8 *radar_detect);
- int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
-                                struct cfg80211_chan_def *chandef);
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -1723,9 +1723,10 @@ static int nl80211_dump_wiphy(struct sk_
-                                * We can then retry with the larger buffer.
-                                */
-                               if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
--                                  !skb->len &&
-+                                  !skb->len && !state->split &&
-                                   cb->min_dump_alloc < 4096) {
-                                       cb->min_dump_alloc = 4096;
-+                                      state->split_start = 0;
-                                       rtnl_unlock();
-                                       return 1;
-                               }
-@@ -2047,10 +2048,12 @@ static int nl80211_set_wiphy(struct sk_b
-               nla_for_each_nested(nl_txq_params,
-                                   info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
-                                   rem_txq_params) {
--                      nla_parse(tb, NL80211_TXQ_ATTR_MAX,
--                                nla_data(nl_txq_params),
--                                nla_len(nl_txq_params),
--                                txq_params_policy);
-+                      result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
-+                                         nla_data(nl_txq_params),
-+                                         nla_len(nl_txq_params),
-+                                         txq_params_policy);
-+                      if (result)
-+                              goto bad_res;
-                       result = parse_txq_params(tb, &txq_params);
-                       if (result)
-                               goto bad_res;
-@@ -3289,7 +3292,7 @@ static int nl80211_start_ap(struct sk_bu
-       if (!err) {
-               wdev->preset_chandef = params.chandef;
-               wdev->beacon_interval = params.beacon_interval;
--              wdev->channel = params.chandef.chan;
-+              wdev->chandef = params.chandef;
-               wdev->ssid_len = params.ssid_len;
-               memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
-       }
-@@ -5210,9 +5213,11 @@ static int nl80211_set_reg(struct sk_buf
-       nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
-                           rem_reg_rules) {
--              nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
--                        nla_data(nl_reg_rule), nla_len(nl_reg_rule),
--                        reg_rule_policy);
-+              r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
-+                            nla_data(nl_reg_rule), nla_len(nl_reg_rule),
-+                            reg_rule_policy);
-+              if (r)
-+                      goto bad_reg;
-               r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
-               if (r)
-                       goto bad_reg;
-@@ -5277,7 +5282,7 @@ static int nl80211_trigger_scan(struct s
-       if (!rdev->ops->scan)
-               return -EOPNOTSUPP;
--      if (rdev->scan_req) {
-+      if (rdev->scan_req || rdev->scan_msg) {
-               err = -EBUSY;
-               goto unlock;
-       }
-@@ -5475,6 +5480,7 @@ static int nl80211_start_sched_scan(stru
-       enum ieee80211_band band;
-       size_t ie_len;
-       struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
-+      s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
-       if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
-           !rdev->ops->sched_scan_start)
-@@ -5509,11 +5515,40 @@ static int nl80211_start_sched_scan(stru
-       if (n_ssids > wiphy->max_sched_scan_ssids)
-               return -EINVAL;
--      if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
-+      /*
-+       * First, count the number of 'real' matchsets. Due to an issue with
-+       * the old implementation, matchsets containing only the RSSI attribute
-+       * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
-+       * RSSI for all matchsets, rather than their own matchset for reporting
-+       * all APs with a strong RSSI. This is needed to be compatible with
-+       * older userspace that treated a matchset with only the RSSI as the
-+       * global RSSI for all other matchsets - if there are other matchsets.
-+       */
-+      if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
-               nla_for_each_nested(attr,
-                                   info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
--                                  tmp)
--                      n_match_sets++;
-+                                  tmp) {
-+                      struct nlattr *rssi;
-+
-+                      err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
-+                                      nla_data(attr), nla_len(attr),
-+                                      nl80211_match_policy);
-+                      if (err)
-+                              return err;
-+                      /* add other standalone attributes here */
-+                      if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
-+                              n_match_sets++;
-+                              continue;
-+                      }
-+                      rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
-+                      if (rssi)
-+                              default_match_rssi = nla_get_s32(rssi);
-+              }
-+      }
++static u32 ar9003_hw_compute_pll_control_soc(struct ath_hw *ah,
++                                           struct ath9k_channel *chan)
++{
++      u32 pll;
 +
-+      /* However, if there's no other matchset, add the RSSI one */
-+      if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
-+              n_match_sets = 1;
-       if (n_match_sets > wiphy->max_match_sets)
-               return -EINVAL;
-@@ -5634,11 +5669,22 @@ static int nl80211_start_sched_scan(stru
-                                   tmp) {
-                       struct nlattr *ssid, *rssi;
--                      nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
--                                nla_data(attr), nla_len(attr),
--                                nl80211_match_policy);
-+                      err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
-+                                      nla_data(attr), nla_len(attr),
-+                                      nl80211_match_policy);
-+                      if (err)
-+                              goto out_free;
-                       ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
-                       if (ssid) {
-+                              if (WARN_ON(i >= n_match_sets)) {
-+                                      /* this indicates a programming error,
-+                                       * the loop above should have verified
-+                                       * things properly
-+                                       */
-+                                      err = -EINVAL;
-+                                      goto out_free;
-+                              }
-+
-                               if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
-                                       err = -EINVAL;
-                                       goto out_free;
-@@ -5647,15 +5693,28 @@ static int nl80211_start_sched_scan(stru
-                                      nla_data(ssid), nla_len(ssid));
-                               request->match_sets[i].ssid.ssid_len =
-                                       nla_len(ssid);
-+                              /* special attribute - old implemenation w/a */
-+                              request->match_sets[i].rssi_thold =
-+                                      default_match_rssi;
-+                              rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
-+                              if (rssi)
-+                                      request->match_sets[i].rssi_thold =
-+                                              nla_get_s32(rssi);
-                       }
--                      rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
--                      if (rssi)
--                              request->rssi_thold = nla_get_u32(rssi);
--                      else
--                              request->rssi_thold =
--                                                 NL80211_SCAN_RSSI_THOLD_OFF;
-                       i++;
-               }
++      pll = SM(0x5, AR_RTC_9300_SOC_PLL_REFDIV);
 +
-+              /* there was no other matchset, so the RSSI one is alone */
-+              if (i == 0)
-+                      request->match_sets[0].rssi_thold = default_match_rssi;
++      if (chan && IS_CHAN_HALF_RATE(chan))
++              pll |= SM(0x1, AR_RTC_9300_SOC_PLL_CLKSEL);
++      else if (chan && IS_CHAN_QUARTER_RATE(chan))
++              pll |= SM(0x2, AR_RTC_9300_SOC_PLL_CLKSEL);
 +
-+              request->min_rssi_thold = INT_MAX;
-+              for (i = 0; i < n_match_sets; i++)
-+                      request->min_rssi_thold =
-+                              min(request->match_sets[i].rssi_thold,
-+                                  request->min_rssi_thold);
-+      } else {
-+              request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
-       }
-       if (info->attrs[NL80211_ATTR_IE]) {
-@@ -5751,7 +5810,7 @@ static int nl80211_start_radar_detection
++      pll |= SM(0x2c, AR_RTC_9300_SOC_PLL_DIV_INT);
++
++      return pll;
++}
++
+ static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah,
+                                        struct ath9k_channel *chan)
+ {
+@@ -1781,7 +1798,12 @@ void ar9003_hw_attach_phy_ops(struct ath
  
-       err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
-       if (!err) {
--              wdev->channel = chandef.chan;
-+              wdev->chandef = chandef;
-               wdev->cac_started = true;
-               wdev->cac_start_time = jiffies;
-       }
-@@ -7502,16 +7561,19 @@ static int nl80211_set_tx_bitrate_mask(s
-        * directly to the enum ieee80211_band values used in cfg80211.
-        */
-       BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
--      nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
--      {
-+      nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
-               enum ieee80211_band band = nla_type(tx_rates);
-+              int err;
-+
-               if (band < 0 || band >= IEEE80211_NUM_BANDS)
-                       return -EINVAL;
-               sband = rdev->wiphy.bands[band];
-               if (sband == NULL)
-                       return -EINVAL;
--              nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
--                        nla_len(tx_rates), nl80211_txattr_policy);
-+              err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
-+                              nla_len(tx_rates), nl80211_txattr_policy);
-+              if (err)
-+                      return err;
-               if (tb[NL80211_TXRATE_LEGACY]) {
-                       mask.control[band].legacy = rateset_to_mask(
-                               sband,
-@@ -10054,40 +10116,31 @@ void nl80211_send_scan_start(struct cfg8
-                               NL80211_MCGRP_SCAN, GFP_KERNEL);
+       priv_ops->rf_set_freq = ar9003_hw_set_channel;
+       priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
+-      priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
++
++      if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah))
++              priv_ops->compute_pll_control = ar9003_hw_compute_pll_control_soc;
++      else
++              priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
++
+       priv_ops->set_channel_regs = ar9003_hw_set_channel_regs;
+       priv_ops->init_bb = ar9003_hw_init_bb;
+       priv_ops->process_ini = ar9003_hw_process_ini;
+--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+@@ -381,16 +381,27 @@ static int ar9002_hw_proc_txdesc(struct 
+       ts->evm1 = ads->AR_TxEVM1;
+       ts->evm2 = ads->AR_TxEVM2;
+-      status = ACCESS_ONCE(ads->ds_ctl4);
+-      ts->duration[0] = MS(status, AR_PacketDur0);
+-      ts->duration[1] = MS(status, AR_PacketDur1);
+-      status = ACCESS_ONCE(ads->ds_ctl5);
+-      ts->duration[2] = MS(status, AR_PacketDur2);
+-      ts->duration[3] = MS(status, AR_PacketDur3);
+-
+       return 0;
  }
  
--void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
--                          struct wireless_dev *wdev)
-+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
-+                                     struct wireless_dev *wdev, bool aborted)
++static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
++{
++      struct ar5416_desc *ads = AR5416DESC(ds);
++
++      switch (index) {
++      case 0:
++              return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur0);
++      case 1:
++              return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur1);
++      case 2:
++              return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur2);
++      case 3:
++              return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur3);
++      default:
++              return -1;
++      }
++}
++
+ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+                         u32 size, u32 flags)
  {
-       struct sk_buff *msg;
-       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (!msg)
--              return;
-+              return NULL;
-       if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
--                                NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
-+                                aborted ? NL80211_CMD_SCAN_ABORTED :
-+                                          NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
-               nlmsg_free(msg);
--              return;
-+              return NULL;
-       }
--      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
--                              NL80211_MCGRP_SCAN, GFP_KERNEL);
-+      return msg;
+@@ -413,4 +424,5 @@ void ar9002_hw_attach_mac_ops(struct ath
+       ops->get_isr = ar9002_hw_get_isr;
+       ops->set_txdesc = ar9002_set_txdesc;
+       ops->proc_txdesc = ar9002_hw_proc_txdesc;
++      ops->get_duration = ar9002_hw_get_duration;
  }
--void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
--                             struct wireless_dev *wdev)
-+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
-+                            struct sk_buff *msg)
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -355,11 +355,9 @@ static int ar9003_hw_proc_txdesc(struct 
+                                struct ath_tx_status *ts)
  {
--      struct sk_buff *msg;
--
--      msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (!msg)
-               return;
--      if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
--                                NL80211_CMD_SCAN_ABORTED) < 0) {
--              nlmsg_free(msg);
--              return;
--      }
+       struct ar9003_txs *ads;
+-      struct ar9003_txc *adc;
+       u32 status;
+       ads = &ah->ts_ring[ah->ts_tail];
+-      adc = (struct ar9003_txc *)ads;
+       status = ACCESS_ONCE(ads->status8);
+       if ((status & AR_TxDone) == 0)
+@@ -428,18 +426,29 @@ static int ar9003_hw_proc_txdesc(struct 
+       ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+       ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
+-      status = ACCESS_ONCE(adc->ctl15);
+-      ts->duration[0] = MS(status, AR_PacketDur0);
+-      ts->duration[1] = MS(status, AR_PacketDur1);
+-      status = ACCESS_ONCE(adc->ctl16);
+-      ts->duration[2] = MS(status, AR_PacketDur2);
+-      ts->duration[3] = MS(status, AR_PacketDur3);
 -
-       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
-                               NL80211_MCGRP_SCAN, GFP_KERNEL);
- }
-@@ -11158,7 +11211,8 @@ void cfg80211_ch_switch_notify(struct ne
-                   wdev->iftype != NL80211_IFTYPE_MESH_POINT))
-               return;
+       memset(ads, 0, sizeof(*ads));
  
--      wdev->channel = chandef->chan;
-+      wdev->chandef = *chandef;
-+      wdev->preset_chandef = *chandef;
-       nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
- }
- EXPORT_SYMBOL(cfg80211_ch_switch_notify);
-@@ -11673,6 +11727,35 @@ void cfg80211_crit_proto_stopped(struct 
+       return 0;
  }
- EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
  
-+void nl80211_send_ap_stopped(struct wireless_dev *wdev)
++static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
 +{
-+      struct wiphy *wiphy = wdev->wiphy;
-+      struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-+      struct sk_buff *msg;
-+      void *hdr;
-+
-+      msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-+      if (!msg)
-+              return;
-+
-+      hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
-+      if (!hdr)
-+              goto out;
-+
-+      if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-+          nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
-+          nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
-+              goto out;
++      const struct ar9003_txc *adc = ds;
 +
-+      genlmsg_end(msg, hdr);
-+
-+      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
-+                              NL80211_MCGRP_MLME, GFP_KERNEL);
-+      return;
-+ out:
-+      nlmsg_free(msg);
++      switch (index) {
++      case 0:
++              return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur0);
++      case 1:
++              return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur1);
++      case 2:
++              return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur2);
++      case 3:
++              return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur3);
++      default:
++              return 0;
++      }
 +}
 +
- /* initialisation/exit functions */
- int nl80211_init(void)
---- a/net/wireless/nl80211.h
-+++ b/net/wireless/nl80211.h
-@@ -8,10 +8,10 @@ void nl80211_exit(void);
- void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
- void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
-                            struct wireless_dev *wdev);
--void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
--                          struct wireless_dev *wdev);
--void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
--                             struct wireless_dev *wdev);
-+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
-+                                     struct wireless_dev *wdev, bool aborted);
-+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
-+                            struct sk_buff *msg);
- void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
-                            struct net_device *netdev, u32 cmd);
- void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
-@@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_reg
-                    enum nl80211_radar_event event,
-                    struct net_device *netdev, gfp_t gfp);
-+void nl80211_send_ap_stopped(struct wireless_dev *wdev);
-+
- void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
- #endif /* __NET_WIRELESS_NL80211_H */
---- a/net/wireless/scan.c
-+++ b/net/wireless/scan.c
-@@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct
-               dev->bss_generation++;
- }
--void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
-+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
-+                         bool send_message)
+ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
  {
-       struct cfg80211_scan_request *request;
-       struct wireless_dev *wdev;
-+      struct sk_buff *msg;
- #ifdef CPTCFG_CFG80211_WEXT
-       union iwreq_data wrqu;
- #endif
-       ASSERT_RTNL();
--      request = rdev->scan_req;
-+      if (rdev->scan_msg) {
-+              nl80211_send_scan_result(rdev, rdev->scan_msg);
-+              rdev->scan_msg = NULL;
-+              return;
-+      }
-+      request = rdev->scan_req;
-       if (!request)
-               return;
+       struct ath_hw_ops *ops = ath9k_hw_ops(hw);
+@@ -449,6 +458,7 @@ void ar9003_hw_attach_mac_ops(struct ath
+       ops->get_isr = ar9003_hw_get_isr;
+       ops->set_txdesc = ar9003_set_txdesc;
+       ops->proc_txdesc = ar9003_hw_proc_txdesc;
++      ops->get_duration = ar9003_hw_get_duration;
+ }
  
-@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802
-       if (wdev->netdev)
-               cfg80211_sme_scan_done(wdev->netdev);
--      if (request->aborted) {
--              nl80211_send_scan_aborted(rdev, wdev);
--      } else {
--              if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
--                      /* flush entries from previous scans */
--                      spin_lock_bh(&rdev->bss_lock);
--                      __cfg80211_bss_expire(rdev, request->scan_start);
--                      spin_unlock_bh(&rdev->bss_lock);
--              }
--              nl80211_send_scan_done(rdev, wdev);
-+      if (!request->aborted &&
-+          request->flags & NL80211_SCAN_FLAG_FLUSH) {
-+              /* flush entries from previous scans */
-+              spin_lock_bh(&rdev->bss_lock);
-+              __cfg80211_bss_expire(rdev, request->scan_start);
-+              spin_unlock_bh(&rdev->bss_lock);
-       }
+ void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
+--- a/drivers/net/wireless/ath/ath9k/dynack.c
++++ b/drivers/net/wireless/ath/ath9k/dynack.c
+@@ -202,7 +202,7 @@ void ath_dynack_sample_tx_ts(struct ath_
+       ridx = ts->ts_rateindex;
+       da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp;
+-      da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration[ts->ts_rateindex];
++      da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration;
+       ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1);
+       ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2);
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -67,6 +67,12 @@ static inline int ath9k_hw_txprocdesc(st
+       return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
+ }
  
-+      msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
++static inline int ath9k_hw_get_duration(struct ath_hw *ah, const void *ds,
++                                      int index)
++{
++      return ath9k_hw_ops(ah)->get_duration(ah, ds, index);
++}
 +
- #ifdef CPTCFG_CFG80211_WEXT
-       if (wdev->netdev && !request->aborted) {
-               memset(&wrqu, 0, sizeof(wrqu));
-@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802
+ static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+               struct ath_hw_antcomb_conf *antconf)
+ {
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -691,6 +691,7 @@ struct ath_hw_ops {
+                          struct ath_tx_info *i);
+       int (*proc_txdesc)(struct ath_hw *ah, void *ds,
+                          struct ath_tx_status *ts);
++      int (*get_duration)(struct ath_hw *ah, const void *ds, int index);
+       void (*antdiv_comb_conf_get)(struct ath_hw *ah,
+                       struct ath_hw_antcomb_conf *antconf);
+       void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -121,7 +121,7 @@ struct ath_tx_status {
+       u32 evm0;
+       u32 evm1;
+       u32 evm2;
+-      u32 duration[4];
++      u32 duration;
+ };
  
-       rdev->scan_req = NULL;
-       kfree(request);
-+
-+      if (!send_message)
-+              rdev->scan_msg = msg;
-+      else
-+              nl80211_send_scan_result(rdev, msg);
+ struct ath_rx_status {
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -683,6 +683,8 @@ static void ath_tx_process_buffer(struct
+       if (bf_is_ampdu_not_probing(bf))
+               txq->axq_ampdu_depth--;
++      ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
++                                           ts->ts_rateindex);
+       if (!bf_isampdu(bf)) {
+               if (!flush) {
+                       info = IEEE80211_SKB_CB(bf->bf_mpdu);
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -455,7 +455,8 @@ void ath9k_p2p_bss_info_changed(struct a
+ void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
+                         struct sk_buff *skb);
+ void ath9k_p2p_ps_timer(void *priv);
+-void ath9k_chanctx_wake_queues(struct ath_softc *sc);
++void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx);
++void ath9k_chanctx_stop_queues(struct ath_softc *sc, struct ath_chanctx *ctx);
+ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx);
+ void ath_chanctx_beacon_recv_ev(struct ath_softc *sc,
+@@ -525,7 +526,12 @@ static inline void ath9k_beacon_add_noa(
+ static inline void ath9k_p2p_ps_timer(struct ath_softc *sc)
+ {
  }
- void __cfg80211_scan_done(struct work_struct *wk)
-@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st
-                           scan_done_wk);
-       rtnl_lock();
--      ___cfg80211_scan_done(rdev);
-+      ___cfg80211_scan_done(rdev, true);
-       rtnl_unlock();
+-static inline void ath9k_chanctx_wake_queues(struct ath_softc *sc)
++static inline void ath9k_chanctx_wake_queues(struct ath_softc *sc,
++                                           struct ath_chanctx *ctx)
++{
++}
++static inline void ath9k_chanctx_stop_queues(struct ath_softc *sc,
++                                           struct ath_chanctx *ctx)
+ {
  }
+ static inline void ath_chanctx_check_active(struct ath_softc *sc,
+--- a/drivers/net/wireless/ath/ath9k/channel.c
++++ b/drivers/net/wireless/ath/ath9k/channel.c
+@@ -761,6 +761,13 @@ void ath_offchannel_next(struct ath_soft
  
-@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev
-       if (IS_ERR(rdev))
-               return PTR_ERR(rdev);
+ void ath_roc_complete(struct ath_softc *sc, bool abort)
+ {
++      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++
++      if (abort)
++              ath_dbg(common, CHAN_CTX, "RoC aborted\n");
++      else
++              ath_dbg(common, CHAN_CTX, "RoC expired\n");
++
+       sc->offchannel.roc_vif = NULL;
+       sc->offchannel.roc_chan = NULL;
+       if (!abort)
+@@ -1037,9 +1044,11 @@ static void ath_offchannel_channel_chang
+ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
+ {
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      struct ath_chanctx *old_ctx;
+       struct timespec ts;
+       bool measure_time = false;
+       bool send_ps = false;
++      bool queues_stopped = false;
+       spin_lock_bh(&sc->chan_lock);
+       if (!sc->next_chan) {
+@@ -1069,6 +1078,10 @@ void ath_chanctx_set_next(struct ath_sof
+                       getrawmonotonic(&ts);
+                       measure_time = true;
+               }
++
++              ath9k_chanctx_stop_queues(sc, sc->cur_chan);
++              queues_stopped = true;
++
+               __ath9k_flush(sc->hw, ~0, true);
  
--      if (rdev->scan_req) {
-+      if (rdev->scan_req || rdev->scan_msg) {
-               err = -EBUSY;
-               goto out;
+               if (ath_chanctx_send_ps_frame(sc, true))
+@@ -1082,6 +1095,7 @@ void ath_chanctx_set_next(struct ath_sof
+                       sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
+               }
        }
-@@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_dev
-       if (IS_ERR(rdev))
-               return PTR_ERR(rdev);
--      if (rdev->scan_req)
-+      if (rdev->scan_req || rdev->scan_msg)
-               return -EAGAIN;
-       res = ieee80211_scan_results(rdev, info, extra, data->length);
---- a/net/wireless/sme.c
-+++ b/net/wireless/sme.c
-@@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wir
-       ASSERT_RDEV_LOCK(rdev);
-       ASSERT_WDEV_LOCK(wdev);
--      if (rdev->scan_req)
-+      if (rdev->scan_req || rdev->scan_msg)
-               return -EBUSY;
-       if (wdev->conn->params.channel)
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -1001,7 +1001,6 @@ ieee80211_sta_process_chanswitch(struct 
++      old_ctx = sc->cur_chan;
+       sc->cur_chan = sc->next_chan;
+       sc->cur_chan->stopped = false;
+       sc->next_chan = NULL;
+@@ -1104,7 +1118,16 @@ void ath_chanctx_set_next(struct ath_sof
+               if (measure_time)
+                       sc->sched.channel_switch_time =
+                               ath9k_hw_get_tsf_offset(&ts, NULL);
++              /*
++               * A reset will ensure that all queues are woken up,
++               * so there is no need to awaken them again.
++               */
++              goto out;
        }
-       ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
--      sdata->vif.csa_active = true;
-       mutex_lock(&local->chanctx_mtx);
-       if (local->use_chanctx) {
-@@ -1039,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct 
-       mutex_unlock(&local->chanctx_mtx);
-       sdata->csa_chandef = csa_ie.chandef;
-+      sdata->vif.csa_active = true;
-       if (csa_ie.mode)
-               ieee80211_stop_queues_by_reason(&local->hw,
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required(
++
++      if (queues_stopped)
++              ath9k_chanctx_wake_queues(sc, old_ctx);
++out:
+       if (send_ps)
+               ath_chanctx_send_ps_frame(sc, false);
+@@ -1170,18 +1193,37 @@ bool ath9k_is_chanctx_enabled(void)
+ /* Queue management */
+ /********************/
+-void ath9k_chanctx_wake_queues(struct ath_softc *sc)
++void ath9k_chanctx_stop_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      int i;
++
++      if (ctx == &sc->offchannel.chan) {
++              ieee80211_stop_queue(sc->hw,
++                                   sc->hw->offchannel_tx_hw_queue);
++      } else {
++              for (i = 0; i < IEEE80211_NUM_ACS; i++)
++                      ieee80211_stop_queue(sc->hw,
++                                           ctx->hw_queue_base + i);
++      }
++
++      if (ah->opmode == NL80211_IFTYPE_AP)
++              ieee80211_stop_queue(sc->hw, sc->hw->queues - 2);
++}
++
++
++void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
  {
-       struct ieee80211_sub_if_data *sdata;
+       struct ath_hw *ah = sc->sc_ah;
+       int i;
  
-+      lockdep_assert_held(&local->mtx);
-+
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               if (sdata->radar_required) {
---- a/net/mac80211/ibss.c
-+++ b/net/mac80211/ibss.c
-@@ -294,7 +294,6 @@ static void __ieee80211_sta_join_ibss(st
+-      if (sc->cur_chan == &sc->offchannel.chan) {
++      if (ctx == &sc->offchannel.chan) {
+               ieee80211_wake_queue(sc->hw,
+                                    sc->hw->offchannel_tx_hw_queue);
+       } else {
+               for (i = 0; i < IEEE80211_NUM_ACS; i++)
+                       ieee80211_wake_queue(sc->hw,
+-                                           sc->cur_chan->hw_queue_base + i);
++                                           ctx->hw_queue_base + i);
        }
  
-       mutex_lock(&local->mtx);
--      ieee80211_vif_release_channel(sdata);
-       if (ieee80211_vif_use_channel(sdata, &chandef,
-                                     ifibss->fixed_channel ?
-                                       IEEE80211_CHANCTX_SHARED :
-@@ -303,6 +302,7 @@ static void __ieee80211_sta_join_ibss(st
-               mutex_unlock(&local->mtx);
-               return;
-       }
-+      sdata->radar_required = radar_required;
-       mutex_unlock(&local->mtx);
-       memcpy(ifibss->bssid, bssid, ETH_ALEN);
-@@ -318,7 +318,6 @@ static void __ieee80211_sta_join_ibss(st
-       rcu_assign_pointer(ifibss->presp, presp);
-       mgmt = (void *)presp->head;
--      sdata->radar_required = radar_required;
-       sdata->vif.bss_conf.enable_beacon = true;
-       sdata->vif.bss_conf.beacon_int = beacon_int;
-       sdata->vif.bss_conf.basic_rates = basic_rates;
-@@ -386,7 +385,7 @@ static void __ieee80211_sta_join_ibss(st
-                                             presp->head_len, 0, GFP_KERNEL);
-       cfg80211_put_bss(local->hw.wiphy, bss);
-       netif_carrier_on(sdata->dev);
--      cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
-+      cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL);
- }
+       if (ah->opmode == NL80211_IFTYPE_AP)
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -464,6 +464,7 @@ static int ath9k_init_priv(struct ath9k_
+               return -ENOMEM;
+       ah->dev = priv->dev;
++      ah->hw = priv->hw;
+       ah->hw_version.devid = devid;
+       ah->hw_version.usbdev = drv_info;
+       ah->ah_flags |= AH_USE_EEPROM;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -60,8 +60,10 @@ static bool ath9k_has_pending_frames(str
  
- static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
-@@ -802,6 +801,8 @@ ieee80211_ibss_process_chanswitch(struct
-       int err;
-       u32 sta_flags;
+       spin_lock_bh(&txq->axq_lock);
  
-+      sdata_assert_lock(sdata);
-+
-       sta_flags = IEEE80211_STA_DISABLE_VHT;
-       switch (ifibss->chandef.width) {
-       case NL80211_CHAN_WIDTH_5:
-@@ -1471,6 +1472,11 @@ static void ieee80211_rx_mgmt_probe_req(
-       memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
-       ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
-       IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
-+
-+      /* avoid excessive retries for probe request to wildcard SSIDs */
-+      if (pos[1] == 0)
-+              IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK;
-+
-       ieee80211_tx_skb(sdata, skb);
+-      if (txq->axq_depth)
++      if (txq->axq_depth) {
+               pending = true;
++              goto out;
++      }
+       if (txq->mac80211_qnum >= 0) {
+               struct list_head *list;
+@@ -70,6 +72,7 @@ static bool ath9k_has_pending_frames(str
+               if (!list_empty(list))
+                       pending = true;
+       }
++out:
+       spin_unlock_bh(&txq->axq_lock);
+       return pending;
  }
+@@ -261,12 +264,7 @@ static bool ath_complete_reset(struct at
  
---- a/net/mac80211/mesh.c
-+++ b/net/mac80211/mesh.c
-@@ -872,6 +872,8 @@ ieee80211_mesh_process_chnswitch(struct 
-       if (!ifmsh->mesh_id)
-               return false;
-+      sdata_assert_lock(sdata);
-+
-       sta_flags = IEEE80211_STA_DISABLE_VHT;
-       switch (sdata->vif.bss_conf.chandef.width) {
-       case NL80211_CHAN_WIDTH_20_NOHT:
---- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
-+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
-@@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf
-       struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
-       struct net_device *ndev = ifp->ndev;
-       struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
-+      struct ieee80211_channel *chan;
-       s32 err = 0;
-       if (ifp->vif->mode == WL_MODE_AP) {
-@@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf
-       } else if (brcmf_is_linkup(e)) {
-               brcmf_dbg(CONN, "Linkup\n");
-               if (brcmf_is_ibssmode(ifp->vif)) {
-+                      chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
-                       memcpy(profile->bssid, e->addr, ETH_ALEN);
-                       wl_inform_ibss(cfg, ndev, e->addr);
--                      cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
-+                      cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
-                       clear_bit(BRCMF_VIF_STATUS_CONNECTING,
-                                 &ifp->vif->sme_state);
-                       set_bit(BRCMF_VIF_STATUS_CONNECTED,
---- a/drivers/net/wireless/libertas/cfg.c
-+++ b/drivers/net/wireless/libertas/cfg.c
-@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_pri
-       memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
-       priv->wdev->ssid_len = params->ssid_len;
--      cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
-+      cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
-+                           GFP_KERNEL);
-       /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
-       priv->connect_status = LBS_CONNECTED;
---- a/drivers/net/wireless/mwifiex/cfg80211.c
-+++ b/drivers/net/wireless/mwifiex/cfg80211.c
-@@ -1881,7 +1881,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy 
-                                    params->privacy);
- done:
-       if (!ret) {
--              cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
-+              cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
-+                                   params->chandef.chan, GFP_KERNEL);
-               dev_dbg(priv->adapter->dev,
-                       "info: joined/created adhoc network with bssid"
-                       " %pM successfully\n", priv->cfg_bssid);
---- a/drivers/net/wireless/rndis_wlan.c
-+++ b/drivers/net/wireless/rndis_wlan.c
-@@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(s
-                                       bssid, req_ie, req_ie_len,
-                                       resp_ie, resp_ie_len, GFP_KERNEL);
-       } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
--              cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
-+              cfg80211_ibss_joined(usbdev->net, bssid,
-+                                   get_current_channel(usbdev, NULL),
-+                                   GFP_KERNEL);
-       kfree(info);
---- a/net/wireless/ibss.c
-+++ b/net/wireless/ibss.c
-@@ -14,7 +14,8 @@
- #include "rdev-ops.h"
--void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
-+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-+                          struct ieee80211_channel *channel)
- {
-       struct wireless_dev *wdev = dev->ieee80211_ptr;
-       struct cfg80211_bss *bss;
-@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_d
-       if (!wdev->ssid_len)
-               return;
+       ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+-
+-      if (!ath9k_is_chanctx_enabled())
+-              ieee80211_wake_queues(sc->hw);
+-      else
+-              ath9k_chanctx_wake_queues(sc);
+-
++      ieee80211_wake_queues(sc->hw);
+       ath9k_p2p_ps_timer(sc);
  
--      bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
--                             wdev->ssid, wdev->ssid_len,
-+      bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
-                              WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
+       return true;
+@@ -1971,9 +1969,6 @@ static bool ath9k_has_tx_pending(struct 
+               if (!ATH_TXQ_SETUP(sc, i))
+                       continue;
  
-       if (WARN_ON(!bss))
-@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_d
- #endif
- }
+-              if (!sc->tx.txq[i].axq_depth)
+-                      continue;
+-
+               npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
+               if (npend)
+                       break;
+@@ -1999,7 +1994,6 @@ void __ath9k_flush(struct ieee80211_hw *
+       struct ath_common *common = ath9k_hw_common(ah);
+       int timeout = HZ / 5; /* 200 ms */
+       bool drain_txq;
+-      int i;
  
--void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
-+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-+                        struct ieee80211_channel *channel, gfp_t gfp)
- {
-       struct wireless_dev *wdev = dev->ieee80211_ptr;
-       struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
-       struct cfg80211_event *ev;
-       unsigned long flags;
+       cancel_delayed_work_sync(&sc->tx_complete_work);
  
--      trace_cfg80211_ibss_joined(dev, bssid);
-+      trace_cfg80211_ibss_joined(dev, bssid, channel);
-+
-+      if (WARN_ON(!channel))
-+              return;
+@@ -2027,10 +2021,6 @@ void __ath9k_flush(struct ieee80211_hw *
+                       ath_reset(sc);
  
-       ev = kzalloc(sizeof(*ev), gfp);
-       if (!ev)
-               return;
+               ath9k_ps_restore(sc);
+-              for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+-                      ieee80211_wake_queue(sc->hw,
+-                                           sc->cur_chan->hw_queue_base + i);
+-              }
+       }
  
-       ev->type = EVENT_IBSS_JOINED;
--      memcpy(ev->cr.bssid, bssid, ETH_ALEN);
-+      memcpy(ev->ij.bssid, bssid, ETH_ALEN);
-+      ev->ij.channel = channel;
-       spin_lock_irqsave(&wdev->event_lock, flags);
-       list_add_tail(&ev->list, &wdev->event_list);
-@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211
-       wdev->ibss_fixed = params->channel_fixed;
-       wdev->ibss_dfs_possible = params->userspace_handles_dfs;
-+      wdev->chandef = params->chandef;
- #ifdef CPTCFG_CFG80211_WEXT
-       wdev->wext.ibss.chandef = params->chandef;
- #endif
-@@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct
-       wdev->current_bss = NULL;
-       wdev->ssid_len = 0;
-+      memset(&wdev->chandef, 0, sizeof(wdev->chandef));
- #ifdef CPTCFG_CFG80211_WEXT
-       if (!nowext)
-               wdev->wext.ibss.ssid_len = 0;
---- a/net/wireless/trace.h
-+++ b/net/wireless/trace.h
-@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
-       TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
- );
--DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
--      TP_PROTO(struct net_device *netdev, const u8 *addr),
--      TP_ARGS(netdev, addr)
--);
--
- DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
-       TP_PROTO(struct net_device *netdev, const u8 *addr),
-       TP_ARGS(netdev, addr)
-@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_r
-       TP_ARGS(netdev, addr)
- );
-+TRACE_EVENT(cfg80211_ibss_joined,
-+      TP_PROTO(struct net_device *netdev, const u8 *bssid,
-+               struct ieee80211_channel *channel),
-+      TP_ARGS(netdev, bssid, channel),
-+      TP_STRUCT__entry(
-+              NETDEV_ENTRY
-+              MAC_ENTRY(bssid)
-+              CHAN_ENTRY
-+      ),
-+      TP_fast_assign(
-+              NETDEV_ASSIGN;
-+              MAC_ASSIGN(bssid, bssid);
-+              CHAN_ASSIGN(channel);
-+      ),
-+      TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
-+                NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
-+);
-+
- TRACE_EVENT(cfg80211_probe_status,
-       TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
-                bool acked),
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct
-                                               ev->dc.reason, true);
-                       break;
-               case EVENT_IBSS_JOINED:
--                      __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
-+                      __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
-+                                             ev->ij.channel);
-                       break;
-               }
-               wdev_unlock(wdev);
-@@ -1356,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct 
-                */
-               mutex_lock_nested(&wdev_iter->mtx, 1);
-               __acquire(wdev_iter->mtx);
--              cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
-+              cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect);
-               wdev_unlock(wdev_iter);
-               switch (chmode) {
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct 
- void
- cfg80211_get_chan_state(struct wireless_dev *wdev,
-                       struct ieee80211_channel **chan,
--                      enum cfg80211_chan_mode *chanmode)
-+                      enum cfg80211_chan_mode *chanmode,
-+                      u8 *radar_detect)
+       ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
+@@ -2039,16 +2029,8 @@ void __ath9k_flush(struct ieee80211_hw *
+ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
  {
-       *chan = NULL;
-       *chanmode = CHAN_MODE_UNDEFINED;
-@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_
-                                    !wdev->ibss_dfs_possible)
-                                 ? CHAN_MODE_SHARED
-                                 : CHAN_MODE_EXCLUSIVE;
-+
-+                      /* consider worst-case - IBSS can try to return to the
-+                       * original user-specified channel as creator */
-+                      if (wdev->ibss_dfs_possible)
-+                              *radar_detect |= BIT(wdev->chandef.width);
-                       return;
-               }
-               break;
-@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_
-       case NL80211_IFTYPE_AP:
-       case NL80211_IFTYPE_P2P_GO:
-               if (wdev->cac_started) {
--                      *chan = wdev->channel;
-+                      *chan = wdev->chandef.chan;
-                       *chanmode = CHAN_MODE_SHARED;
-+                      *radar_detect |= BIT(wdev->chandef.width);
-               } else if (wdev->beacon_interval) {
--                      *chan = wdev->channel;
-+                      *chan = wdev->chandef.chan;
-                       *chanmode = CHAN_MODE_SHARED;
-+
-+                      if (cfg80211_chandef_dfs_required(wdev->wiphy,
-+                                                        &wdev->chandef))
-+                              *radar_detect |= BIT(wdev->chandef.width);
-               }
-               return;
-       case NL80211_IFTYPE_MESH_POINT:
-               if (wdev->mesh_id_len) {
--                      *chan = wdev->channel;
-+                      *chan = wdev->chandef.chan;
-                       *chanmode = CHAN_MODE_SHARED;
-+
-+                      if (cfg80211_chandef_dfs_required(wdev->wiphy,
-+                                                        &wdev->chandef))
-+                              *radar_detect |= BIT(wdev->chandef.width);
-               }
-               return;
-       case NL80211_IFTYPE_MONITOR:
---- a/net/wireless/mesh.c
-+++ b/net/wireless/mesh.c
-@@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211
-       if (!err) {
-               memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
-               wdev->mesh_id_len = setup->mesh_id_len;
--              wdev->channel = setup->chandef.chan;
-+              wdev->chandef = setup->chandef;
-       }
+       struct ath_softc *sc = hw->priv;
+-      int i;
+-
+-      for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+-              if (!ATH_TXQ_SETUP(sc, i))
+-                      continue;
  
-       return err;
-@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg
-               err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
-                                                    chandef->chan);
-               if (!err)
--                      wdev->channel = chandef->chan;
-+                      wdev->chandef = *chandef;
+-              if (ath9k_has_pending_frames(sc, &sc->tx.txq[i]))
+-                      return true;
+-      }
+-      return false;
++      return ath9k_has_tx_pending(sc);
+ }
  
-               return err;
-       }
-@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct 
-       err = rdev_leave_mesh(rdev, dev);
-       if (!err) {
-               wdev->mesh_id_len = 0;
--              wdev->channel = NULL;
-+              memset(&wdev->chandef, 0, sizeof(wdev->chandef));
-               rdev_set_qos_map(rdev, dev, NULL);
-       }
+ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
+@@ -2350,7 +2332,7 @@ static void ath9k_remove_chanctx(struct 
+               conf->def.chan->center_freq);
  
---- a/net/wireless/mlme.c
-+++ b/net/wireless/mlme.c
-@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_devic
-       if (WARN_ON(!wdev->cac_started))
-               return;
+       ctx->assigned = false;
+-      ctx->hw_queue_base = -1;
++      ctx->hw_queue_base = 0;
+       ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN);
  
--      if (WARN_ON(!wdev->channel))
-+      if (WARN_ON(!wdev->chandef.chan))
-               return;
+       mutex_unlock(&sc->mutex);
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -448,7 +448,7 @@ static void rate_fixup_ratelist(struct i
+        */
+       if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) {
+               u32 basic_rates = vif->bss_conf.basic_rates;
+-              s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0;
++              s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0;
  
-       switch (event) {
---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-@@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power(
-                       break;
-               }
-       }
-+
-+      if (is2GHz && !twiceMaxEdgePower)
-+              twiceMaxEdgePower = 60;
-+
-       return twiceMaxEdgePower;
- }
+               rate = &sband->bitrates[rates[0].idx];