diff --git a/config/kernel/linux-sunxi-current.config b/config/kernel/linux-sunxi-current.config
index 5b09a74fc..2253024ec 100644
--- a/config/kernel/linux-sunxi-current.config
+++ b/config/kernel/linux-sunxi-current.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm 5.3.9 Kernel Configuration
+# Linux/arm 5.3.13 Kernel Configuration
#
#
@@ -2554,13 +2554,13 @@ CONFIG_WLAN_VENDOR_TI=y
# CONFIG_WL18XX is not set
# CONFIG_WLCORE is not set
CONFIG_RTL8822BU=m
-CONFIG_RTL8188EU=m
-CONFIG_RTL8812AU=m
+CONFIG_RTL8188EUS=m
CONFIG_WLAN_VENDOR_XRADIO=m
CONFIG_XRADIO_NON_POWER_OF_TWO_BLOCKSIZES=y
# CONFIG_XRADIO_5GHZ_SUPPORT is not set
# CONFIG_XRADIO_WAPI_SUPPORT is not set
CONFIG_XRADIO_USE_EXTENSIONS=y
+CONFIG_RTL8812AU=m
CONFIG_WLAN_VENDOR_ZYDAS=y
# CONFIG_USB_ZD1201 is not set
# CONFIG_ZD1211RW is not set
diff --git a/config/kernel/linux-sunxi-legacy.config b/config/kernel/linux-sunxi-legacy.config
index 251cbc9e8..b9f64dfdf 100644
--- a/config/kernel/linux-sunxi-legacy.config
+++ b/config/kernel/linux-sunxi-legacy.config
@@ -1,13 +1,13 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm 4.19.72 Kernel Configuration
+# Linux/arm 4.19.88 Kernel Configuration
#
#
-# Compiler: arm-linux-gnueabihf-gcc (Linaro GCC 7.4-2019.02) 7.4.1 20181213 [linaro-7.4-2019.02 revision 56ec6f6b99cc167ff0c2f8e1a2eed33b1edc85d4]
+# Compiler: arm-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 8.3.0
#
CONFIG_CC_IS_GCC=y
-CONFIG_GCC_VERSION=70401
+CONFIG_GCC_VERSION=80300
CONFIG_CLANG_VERSION=0
CONFIG_CC_HAS_ASM_GOTO=y
CONFIG_IRQ_WORK=y
@@ -2429,7 +2429,7 @@ CONFIG_WLAN_VENDOR_TI=y
# CONFIG_WL18XX is not set
# CONFIG_WLCORE is not set
CONFIG_RTL8822BU=m
-CONFIG_RTL8188EU=m
+CONFIG_RTL8188EUS=m
CONFIG_RTL8812AU=m
CONFIG_WLAN_VENDOR_XRADIO=m
CONFIG_XRADIO_NON_POWER_OF_TWO_BLOCKSIZES=y
@@ -4179,10 +4179,10 @@ CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
#
# Frame buffer Devices
#
-CONFIG_FB=y
-# CONFIG_FIRMWARE_EDID is not set
CONFIG_FB_CMDLINE=y
CONFIG_FB_NOTIFY=y
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -4795,7 +4795,6 @@ CONFIG_USB_SERIAL_DEBUG=m
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_SEVSEG is not set
-# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
@@ -5370,7 +5369,6 @@ CONFIG_ARM_SMMU=y
# Rpmsg drivers
#
# CONFIG_RPMSG_VIRTIO is not set
-# CONFIG_SOUNDWIRE is not set
#
# SOC (System On Chip) specific Drivers
diff --git a/lib/compilation-prepare.sh b/lib/compilation-prepare.sh
index ad42e0e53..a4d4d77ef 100644
--- a/lib/compilation-prepare.sh
+++ b/lib/compilation-prepare.sh
@@ -152,12 +152,34 @@ compilation_prepare()
fi
+ # Wireless drivers for Xradio XR819 chipsets
+ if linux-version compare $version ge 3.14 && [ "$EXTRAWIFI" == yes ]; then
+ display_alert "Adding" "Wireless drivers for Xradio XR819 chipsets" "info"
+ fetch_from_repo "https://github.com/karabek/xradio" "xradio" "branch:master" "yes"
+ cd ${SRC}/cache/sources/${LINUXSOURCEDIR}
+ rm -rf ${SRC}/cache/sources/${LINUXSOURCEDIR}/drivers/net/wireless/xradio
+ mkdir -p ${SRC}/cache/sources/${LINUXSOURCEDIR}/drivers/net/wireless/xradio/
+ cp ${SRC}/cache/sources/xradio/master/*.{h,c} \
+ ${SRC}/cache/sources/${LINUXSOURCEDIR}/drivers/net/wireless/xradio/
+
+ # Makefile
+ cp ${SRC}/cache/sources/xradio/master/Makefile \
+ ${SRC}/cache/sources/${LINUXSOURCEDIR}/drivers/net/wireless/xradio/Makefile
+ cp ${SRC}/cache/sources/xradio/master/Kconfig \
+ ${SRC}/cache/sources/${LINUXSOURCEDIR}/drivers/net/wireless/xradio/Kconfig
+
+ # Add to section Makefile
+ echo "obj-\$(CONFIG_WLAN_VENDOR_XRADIO) += xradio/" >> $SRC/cache/sources/${LINUXSOURCEDIR}/drivers/net/wireless/Makefile
+ sed -i '/source "drivers\/net\/wireless\/ti\/Kconfig"/a source "drivers\/net\/wireless\/xradio\/Kconfig"' \
+ $SRC/cache/sources/${LINUXSOURCEDIR}/drivers/net/wireless/Kconfig
+
+ fi
# Wireless drivers for Realtek 8188EU 8188EUS and 8188ETV chipsets
- if linux-version compare $version ge 3.14 && [ "$EXTRAWIFI" == yes ]; then
+ if linux-version compare $version ge 3.14 && [ "$LINUXFAMILY" == sunxi ] && [ "$EXTRAWIFI" == yes ]; then
# attach to specifics tag or branch
local rtl8811euver="branch:v5.3.9"
diff --git a/patch/kernel/sunxi-current/wifi-add-xradio.patch b/patch/kernel/sunxi-current/wifi-add-xradio.patch
deleted file mode 100644
index edf765e6d..000000000
--- a/patch/kernel/sunxi-current/wifi-add-xradio.patch
+++ /dev/null
@@ -1,18814 +0,0 @@
-diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
-index b84d8a3..7779c1d 100644
---- a/drivers/net/wireless/Kconfig
-+++ b/drivers/net/wireless/Kconfig
-@@ -48,6 +48,7 @@ source "drivers/net/wireless/realtek/Kconfig"
- source "drivers/net/wireless/rsi/Kconfig"
- source "drivers/net/wireless/st/Kconfig"
- source "drivers/net/wireless/ti/Kconfig"
-+source "drivers/net/wireless/xradio/Kconfig"
- source "drivers/net/wireless/zydas/Kconfig"
- source "drivers/net/wireless/quantenna/Kconfig"
-
-diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
-index 1681dbc..ab14e53 100644
---- a/drivers/net/wireless/Makefile
-+++ b/drivers/net/wireless/Makefile
-@@ -21,6 +21,7 @@ obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/
- obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
- obj-$(CONFIG_WLAN_VENDOR_ST) += st/
- obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
-+obj-$(CONFIG_WLAN_VENDOR_XRADIO) += xradio/
- obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
- obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/
-
-diff --git a/drivers/net/wireless/xradio/.7z b/drivers/net/wireless/xradio/.7z
-new file mode 100644
-index 0000000..4f8fc9c
-Binary files /dev/null and b/drivers/net/wireless/xradio/.7z differ
-diff --git a/drivers/net/wireless/xradio/Kconfig b/drivers/net/wireless/xradio/Kconfig
-new file mode 100644
-index 0000000..d3925ec
---- /dev/null
-+++ b/drivers/net/wireless/xradio/Kconfig
-@@ -0,0 +1,49 @@
-+# SPDX-License-Identifier: GPL-2.0-only
-+
-+config WLAN_VENDOR_XRADIO
-+ tristate "XRADIO WLAN support"
-+ depends on MAC80211
-+ default y
-+ ---help---
-+ If you have a wireless card belonging to this class, say Y.
-+
-+ Note that the answer to this question doesn't directly affect the
-+ kernel: saying N will just cause the configurator to skip all
-+ the questions about cards. If you say Y, you will be asked for
-+ your specific card in the following questions.
-+
-+if WLAN_VENDOR_XRADIO
-+
-+config XRADIO_NON_POWER_OF_TWO_BLOCKSIZES
-+ bool "Platform supports non-power-of-two SDIO transfer"
-+ depends on WLAN_VENDOR_XRADIO
-+ default y
-+ ---help---
-+ Say N here only if you are running the driver on a platform
-+ which does not have support for non-power-of-two SDIO transfer.
-+ If unsure, say Y.
-+
-+config XRADIO_5GHZ_SUPPORT
-+ bool "5GHz band support"
-+ depends on WLAN_VENDOR_XRADIO
-+ default n
-+ ---help---
-+ Say Y if your device supports 5GHz band. If unsure, say N.
-+
-+config XRADIO_WAPI_SUPPORT
-+ bool "WAPI support"
-+ depends on WLAN_VENDOR_XRADIO
-+ default n
-+ ---help---
-+ Say Y if your compat-wireless support WAPI.
-+ If unsure, say N.
-+
-+config XRADIO_USE_EXTENSIONS
-+ bool "Extensions for WFD and PS mode"
-+ depends on WLAN_VENDOR_XRADIO
-+ default y
-+ ---help---
-+ Say Y if you want to include XR extensions
-+ If unsure, say Y.
-+
-+endif # WLAN_VENDOR_XRADIO
-diff --git a/drivers/net/wireless/xradio/LICENSE b/drivers/net/wireless/xradio/LICENSE
-new file mode 100644
-index 0000000..23cb790
---- /dev/null
-+++ b/drivers/net/wireless/xradio/LICENSE
-@@ -0,0 +1,339 @@
-+ GNU GENERAL PUBLIC LICENSE
-+ Version 2, June 1991
-+
-+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+
-+ Preamble
-+
-+ The licenses for most software are designed to take away your
-+freedom to share and change it. By contrast, the GNU General Public
-+License is intended to guarantee your freedom to share and change free
-+software--to make sure the software is free for all its users. This
-+General Public License applies to most of the Free Software
-+Foundation's software and to any other program whose authors commit to
-+using it. (Some other Free Software Foundation software is covered by
-+the GNU Lesser General Public License instead.) You can apply it to
-+your programs, too.
-+
-+ When we speak of free software, we are referring to freedom, not
-+price. Our General Public Licenses are designed to make sure that you
-+have the freedom to distribute copies of free software (and charge for
-+this service if you wish), that you receive source code or can get it
-+if you want it, that you can change the software or use pieces of it
-+in new free programs; and that you know you can do these things.
-+
-+ To protect your rights, we need to make restrictions that forbid
-+anyone to deny you these rights or to ask you to surrender the rights.
-+These restrictions translate to certain responsibilities for you if you
-+distribute copies of the software, or if you modify it.
-+
-+ For example, if you distribute copies of such a program, whether
-+gratis or for a fee, you must give the recipients all the rights that
-+you have. You must make sure that they, too, receive or can get the
-+source code. And you must show them these terms so they know their
-+rights.
-+
-+ We protect your rights with two steps: (1) copyright the software, and
-+(2) offer you this license which gives you legal permission to copy,
-+distribute and/or modify the software.
-+
-+ Also, for each author's protection and ours, we want to make certain
-+that everyone understands that there is no warranty for this free
-+software. If the software is modified by someone else and passed on, we
-+want its recipients to know that what they have is not the original, so
-+that any problems introduced by others will not reflect on the original
-+authors' reputations.
-+
-+ Finally, any free program is threatened constantly by software
-+patents. We wish to avoid the danger that redistributors of a free
-+program will individually obtain patent licenses, in effect making the
-+program proprietary. To prevent this, we have made it clear that any
-+patent must be licensed for everyone's free use or not licensed at all.
-+
-+ The precise terms and conditions for copying, distribution and
-+modification follow.
-+
-+ GNU GENERAL PUBLIC LICENSE
-+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-+
-+ 0. This License applies to any program or other work which contains
-+a notice placed by the copyright holder saying it may be distributed
-+under the terms of this General Public License. The "Program", below,
-+refers to any such program or work, and a "work based on the Program"
-+means either the Program or any derivative work under copyright law:
-+that is to say, a work containing the Program or a portion of it,
-+either verbatim or with modifications and/or translated into another
-+language. (Hereinafter, translation is included without limitation in
-+the term "modification".) Each licensee is addressed as "you".
-+
-+Activities other than copying, distribution and modification are not
-+covered by this License; they are outside its scope. The act of
-+running the Program is not restricted, and the output from the Program
-+is covered only if its contents constitute a work based on the
-+Program (independent of having been made by running the Program).
-+Whether that is true depends on what the Program does.
-+
-+ 1. You may copy and distribute verbatim copies of the Program's
-+source code as you receive it, in any medium, provided that you
-+conspicuously and appropriately publish on each copy an appropriate
-+copyright notice and disclaimer of warranty; keep intact all the
-+notices that refer to this License and to the absence of any warranty;
-+and give any other recipients of the Program a copy of this License
-+along with the Program.
-+
-+You may charge a fee for the physical act of transferring a copy, and
-+you may at your option offer warranty protection in exchange for a fee.
-+
-+ 2. You may modify your copy or copies of the Program or any portion
-+of it, thus forming a work based on the Program, and copy and
-+distribute such modifications or work under the terms of Section 1
-+above, provided that you also meet all of these conditions:
-+
-+ a) You must cause the modified files to carry prominent notices
-+ stating that you changed the files and the date of any change.
-+
-+ b) You must cause any work that you distribute or publish, that in
-+ whole or in part contains or is derived from the Program or any
-+ part thereof, to be licensed as a whole at no charge to all third
-+ parties under the terms of this License.
-+
-+ c) If the modified program normally reads commands interactively
-+ when run, you must cause it, when started running for such
-+ interactive use in the most ordinary way, to print or display an
-+ announcement including an appropriate copyright notice and a
-+ notice that there is no warranty (or else, saying that you provide
-+ a warranty) and that users may redistribute the program under
-+ these conditions, and telling the user how to view a copy of this
-+ License. (Exception: if the Program itself is interactive but
-+ does not normally print such an announcement, your work based on
-+ the Program is not required to print an announcement.)
-+
-+These requirements apply to the modified work as a whole. If
-+identifiable sections of that work are not derived from the Program,
-+and can be reasonably considered independent and separate works in
-+themselves, then this License, and its terms, do not apply to those
-+sections when you distribute them as separate works. But when you
-+distribute the same sections as part of a whole which is a work based
-+on the Program, the distribution of the whole must be on the terms of
-+this License, whose permissions for other licensees extend to the
-+entire whole, and thus to each and every part regardless of who wrote it.
-+
-+Thus, it is not the intent of this section to claim rights or contest
-+your rights to work written entirely by you; rather, the intent is to
-+exercise the right to control the distribution of derivative or
-+collective works based on the Program.
-+
-+In addition, mere aggregation of another work not based on the Program
-+with the Program (or with a work based on the Program) on a volume of
-+a storage or distribution medium does not bring the other work under
-+the scope of this License.
-+
-+ 3. You may copy and distribute the Program (or a work based on it,
-+under Section 2) in object code or executable form under the terms of
-+Sections 1 and 2 above provided that you also do one of the following:
-+
-+ a) Accompany it with the complete corresponding machine-readable
-+ source code, which must be distributed under the terms of Sections
-+ 1 and 2 above on a medium customarily used for software interchange; or,
-+
-+ b) Accompany it with a written offer, valid for at least three
-+ years, to give any third party, for a charge no more than your
-+ cost of physically performing source distribution, a complete
-+ machine-readable copy of the corresponding source code, to be
-+ distributed under the terms of Sections 1 and 2 above on a medium
-+ customarily used for software interchange; or,
-+
-+ c) Accompany it with the information you received as to the offer
-+ to distribute corresponding source code. (This alternative is
-+ allowed only for noncommercial distribution and only if you
-+ received the program in object code or executable form with such
-+ an offer, in accord with Subsection b above.)
-+
-+The source code for a work means the preferred form of the work for
-+making modifications to it. For an executable work, complete source
-+code means all the source code for all modules it contains, plus any
-+associated interface definition files, plus the scripts used to
-+control compilation and installation of the executable. However, as a
-+special exception, the source code distributed need not include
-+anything that is normally distributed (in either source or binary
-+form) with the major components (compiler, kernel, and so on) of the
-+operating system on which the executable runs, unless that component
-+itself accompanies the executable.
-+
-+If distribution of executable or object code is made by offering
-+access to copy from a designated place, then offering equivalent
-+access to copy the source code from the same place counts as
-+distribution of the source code, even though third parties are not
-+compelled to copy the source along with the object code.
-+
-+ 4. You may not copy, modify, sublicense, or distribute the Program
-+except as expressly provided under this License. Any attempt
-+otherwise to copy, modify, sublicense or distribute the Program is
-+void, and will automatically terminate your rights under this License.
-+However, parties who have received copies, or rights, from you under
-+this License will not have their licenses terminated so long as such
-+parties remain in full compliance.
-+
-+ 5. You are not required to accept this License, since you have not
-+signed it. However, nothing else grants you permission to modify or
-+distribute the Program or its derivative works. These actions are
-+prohibited by law if you do not accept this License. Therefore, by
-+modifying or distributing the Program (or any work based on the
-+Program), you indicate your acceptance of this License to do so, and
-+all its terms and conditions for copying, distributing or modifying
-+the Program or works based on it.
-+
-+ 6. Each time you redistribute the Program (or any work based on the
-+Program), the recipient automatically receives a license from the
-+original licensor to copy, distribute or modify the Program subject to
-+these terms and conditions. You may not impose any further
-+restrictions on the recipients' exercise of the rights granted herein.
-+You are not responsible for enforcing compliance by third parties to
-+this License.
-+
-+ 7. If, as a consequence of a court judgment or allegation of patent
-+infringement or for any other reason (not limited to patent issues),
-+conditions are imposed on you (whether by court order, agreement or
-+otherwise) that contradict the conditions of this License, they do not
-+excuse you from the conditions of this License. If you cannot
-+distribute so as to satisfy simultaneously your obligations under this
-+License and any other pertinent obligations, then as a consequence you
-+may not distribute the Program at all. For example, if a patent
-+license would not permit royalty-free redistribution of the Program by
-+all those who receive copies directly or indirectly through you, then
-+the only way you could satisfy both it and this License would be to
-+refrain entirely from distribution of the Program.
-+
-+If any portion of this section is held invalid or unenforceable under
-+any particular circumstance, the balance of the section is intended to
-+apply and the section as a whole is intended to apply in other
-+circumstances.
-+
-+It is not the purpose of this section to induce you to infringe any
-+patents or other property right claims or to contest validity of any
-+such claims; this section has the sole purpose of protecting the
-+integrity of the free software distribution system, which is
-+implemented by public license practices. Many people have made
-+generous contributions to the wide range of software distributed
-+through that system in reliance on consistent application of that
-+system; it is up to the author/donor to decide if he or she is willing
-+to distribute software through any other system and a licensee cannot
-+impose that choice.
-+
-+This section is intended to make thoroughly clear what is believed to
-+be a consequence of the rest of this License.
-+
-+ 8. If the distribution and/or use of the Program is restricted in
-+certain countries either by patents or by copyrighted interfaces, the
-+original copyright holder who places the Program under this License
-+may add an explicit geographical distribution limitation excluding
-+those countries, so that distribution is permitted only in or among
-+countries not thus excluded. In such case, this License incorporates
-+the limitation as if written in the body of this License.
-+
-+ 9. The Free Software Foundation may publish revised and/or new versions
-+of the General Public License from time to time. Such new versions will
-+be similar in spirit to the present version, but may differ in detail to
-+address new problems or concerns.
-+
-+Each version is given a distinguishing version number. If the Program
-+specifies a version number of this License which applies to it and "any
-+later version", you have the option of following the terms and conditions
-+either of that version or of any later version published by the Free
-+Software Foundation. If the Program does not specify a version number of
-+this License, you may choose any version ever published by the Free Software
-+Foundation.
-+
-+ 10. If you wish to incorporate parts of the Program into other free
-+programs whose distribution conditions are different, write to the author
-+to ask for permission. For software which is copyrighted by the Free
-+Software Foundation, write to the Free Software Foundation; we sometimes
-+make exceptions for this. Our decision will be guided by the two goals
-+of preserving the free status of all derivatives of our free software and
-+of promoting the sharing and reuse of software generally.
-+
-+ NO WARRANTY
-+
-+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-+REPAIR OR CORRECTION.
-+
-+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-+POSSIBILITY OF SUCH DAMAGES.
-+
-+ END OF TERMS AND CONDITIONS
-+
-+ How to Apply These Terms to Your New Programs
-+
-+ If you develop a new program, and you want it to be of the greatest
-+possible use to the public, the best way to achieve this is to make it
-+free software which everyone can redistribute and change under these terms.
-+
-+ To do so, attach the following notices to the program. It is safest
-+to attach them to the start of each source file to most effectively
-+convey the exclusion of warranty; and each file should have at least
-+the "copyright" line and a pointer to where the full notice is found.
-+
-+ {description}
-+ Copyright (C) {year} {fullname}
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License along
-+ with this program; if not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-+
-+Also add information on how to contact you by electronic and paper mail.
-+
-+If the program is interactive, make it output a short notice like this
-+when it starts in an interactive mode:
-+
-+ Gnomovision version 69, Copyright (C) year name of author
-+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-+ This is free software, and you are welcome to redistribute it
-+ under certain conditions; type `show c' for details.
-+
-+The hypothetical commands `show w' and `show c' should show the appropriate
-+parts of the General Public License. Of course, the commands you use may
-+be called something other than `show w' and `show c'; they could even be
-+mouse-clicks or menu items--whatever suits your program.
-+
-+You should also get your employer (if you work as a programmer) or your
-+school, if any, to sign a "copyright disclaimer" for the program, if
-+necessary. Here is a sample; alter the names:
-+
-+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
-+
-+ {signature of Ty Coon}, 1 April 1989
-+ Ty Coon, President of Vice
-+
-+This General Public License does not permit incorporating your program into
-+proprietary programs. If your program is a subroutine library, you may
-+consider it more useful to permit linking proprietary applications with the
-+library. If this is what you want to do, use the GNU Lesser General
-+Public License instead of this License.
-diff --git a/drivers/net/wireless/xradio/Makefile b/drivers/net/wireless/xradio/Makefile
-new file mode 100644
-index 0000000..3e7e5ed
---- /dev/null
-+++ b/drivers/net/wireless/xradio/Makefile
-@@ -0,0 +1,57 @@
-+# SPDX-License-Identifier: GPL-2.0-only
-+
-+# Standalone Makefile - uncomment for out-of-tree compilation
-+#CONFIG_WLAN_VENDOR_XRADIO := m
-+#CONFIG_XRADIO_USE_EXTENSIONS := y
-+#CONFIG_XRADIO_WAPI_SUPPORT := n
-+
-+# Kernel part
-+
-+obj-$(CONFIG_WLAN_VENDOR_XRADIO) += xradio_wlan.o
-+
-+xradio_wlan-objs := \
-+ fwio.o \
-+ tx.o \
-+ rx.o \
-+ main.o \
-+ queue.o \
-+ hwio.o \
-+ bh.o \
-+ wsm.o \
-+ sta.o \
-+ ap.o \
-+ keys.o \
-+ scan.o \
-+ module.o \
-+ sdio.o \
-+ pm.o \
-+ ht.o \
-+ p2p.o
-+
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DMCAST_FWDING
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DXRADIO_SUSPEND_RESUME_FILTER_ENABLE
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DAP_AGGREGATE_FW_FIX
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DAP_HT_CAP_UPDATE
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DAP_HT_COMPAT_FIX
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DCONFIG_XRADIO_DUMP_ON_ERROR
-+
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DCONFIG_XRADIO_SUSPEND_POWER_OFF
-+
-+# Extra IE for probe response from upper layer is needed in P2P GO
-+# For offloading probe response to FW, the extra IE must be included
-+# in the probe response template
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DPROBE_RESP_EXTRA_IE
-+
-+# Modified by wzw
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DTES_P2P_0002_ROC_RESTART
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DTES_P2P_000B_EXTEND_INACTIVITY_CNT
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DTES_P2P_000B_DISABLE_EAPOL_FILTER
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DXRADIO_USE_LONG_DTIM_PERIOD
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DXRADIO_USE_LONG_KEEP_ALIVE_PERIOD
-+
-+#ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DDEBUG
-+#ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DXRADIO_DISABLE_HW_CRYPTO
-+
-+# <5.3>
-+#ldflags-$(CONFIG_WLAN_VENDOR_XRADIO) += --strip-debug
-+
-diff --git a/drivers/net/wireless/xradio/ap.c b/drivers/net/wireless/xradio/ap.c
-new file mode 100644
-index 0000000..5276c5a
---- /dev/null
-+++ b/drivers/net/wireless/xradio/ap.c
-@@ -0,0 +1,1624 @@
-+/*
-+ * STA and AP APIs for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "xradio.h"
-+#include "sta.h"
-+#include "ap.h"
-+#include "bh.h"
-+#include "net/mac80211.h"
-+
-+#define XRADIO_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ))
-+#define XRADIO_ENABLE_ARP_FILTER_OFFLOAD 3
-+
-+#ifndef ERP_INFO_BYTE_OFFSET
-+#define ERP_INFO_BYTE_OFFSET 2
-+#endif
-+
-+static int xradio_upload_beacon(struct xradio_vif *priv);
-+#ifdef PROBE_RESP_EXTRA_IE
-+static int xradio_upload_proberesp(struct xradio_vif *priv);
-+#endif
-+static int xradio_upload_pspoll(struct xradio_vif *priv);
-+static int xradio_upload_null(struct xradio_vif *priv);
-+static int xradio_upload_qosnull(struct xradio_vif *priv);
-+static int xradio_start_ap(struct xradio_vif *priv);
-+static int xradio_update_beaconing(struct xradio_vif *priv);
-+/*
-+static int xradio_enable_beaconing(struct xradio_vif *priv,
-+ bool enable);
-+*/
-+static void __xradio_sta_notify(struct xradio_vif *priv,
-+ enum sta_notify_cmd notify_cmd,
-+ int link_id);
-+
-+/* ******************************************************************** */
-+/* AP API */
-+int xradio_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
-+{
-+ struct xradio_sta_priv *sta_priv = (struct xradio_sta_priv *)&sta->drv_priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct xradio_link_entry *entry;
-+ struct sk_buff *skb;
-+#ifdef AP_AGGREGATE_FW_FIX
-+ struct xradio_common *hw_priv = hw->priv;
-+#endif
-+
-+ if (priv->mode != NL80211_IFTYPE_AP) {
-+ return 0;
-+ }
-+
-+ sta_priv->priv = priv;
-+ sta_priv->link_id = xradio_find_link_id(priv, sta->addr);
-+ if (WARN_ON(!sta_priv->link_id)) {
-+ /* Impossible error */
-+ wiphy_debug(hw->wiphy, "No more link IDs available.\n");
-+ return -ENOENT;
-+ }
-+
-+ entry = &priv->link_id_db[sta_priv->link_id - 1];
-+ spin_lock_bh(&priv->ps_state_lock);
-+ if ((sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) ==
-+ IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) {
-+ priv->sta_asleep_mask |= BIT(sta_priv->link_id);
-+ }
-+ entry->status = XRADIO_LINK_HARD;
-+ while ((skb = skb_dequeue(&entry->rx_queue)))
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+#ifdef AP_AGGREGATE_FW_FIX
-+ hw_priv->connected_sta_cnt++;
-+ if(hw_priv->connected_sta_cnt>1) {
-+ wsm_lock_tx(hw_priv);
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
-+ XRADIO_RX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
-+ priv->if_id));
-+ wsm_unlock_tx(hw_priv);
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+int xradio_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_sta_priv *sta_priv =
-+ (struct xradio_sta_priv *)&sta->drv_priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct xradio_link_entry *entry;
-+
-+ if (priv->mode != NL80211_IFTYPE_AP || !sta_priv->link_id) {
-+ wiphy_warn(hw->wiphy, "no station to remove\n");
-+ return 0;
-+ }
-+
-+ entry = &priv->link_id_db[sta_priv->link_id - 1];
-+ spin_lock_bh(&priv->ps_state_lock);
-+ entry->status = XRADIO_LINK_RESERVE;
-+ entry->timestamp = jiffies;
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->link_id_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ flush_workqueue(hw_priv->workqueue);
-+
-+#ifdef AP_AGGREGATE_FW_FIX
-+ hw_priv->connected_sta_cnt--;
-+ if(hw_priv->connected_sta_cnt <= 1) {
-+ if ((priv->if_id != 1) ||
-+ ((priv->if_id == 1) && hw_priv->is_go_thru_go_neg)) {
-+ wsm_lock_tx(hw_priv);
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
-+ XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
-+ priv->if_id));
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+static void __xradio_sta_notify(struct xradio_vif *priv,
-+ enum sta_notify_cmd notify_cmd,
-+ int link_id)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u32 bit, prev;
-+
-+ /* Zero link id means "for all link IDs" */
-+ if (link_id)
-+ bit = BIT(link_id);
-+ else if (WARN_ON_ONCE(notify_cmd != STA_NOTIFY_AWAKE))
-+ bit = 0;
-+ else
-+ bit = priv->link_id_map;
-+ prev = priv->sta_asleep_mask & bit;
-+
-+ switch (notify_cmd) {
-+ case STA_NOTIFY_SLEEP:
-+ if (!prev) {
-+ if (priv->buffered_multicasts &&
-+ !priv->sta_asleep_mask)
-+ queue_work(hw_priv->workqueue,
-+ &priv->multicast_start_work);
-+ priv->sta_asleep_mask |= bit;
-+ }
-+ break;
-+ case STA_NOTIFY_AWAKE:
-+ if (prev) {
-+ priv->sta_asleep_mask &= ~bit;
-+ priv->pspoll_mask &= ~bit;
-+ if (priv->tx_multicast && link_id &&
-+ !priv->sta_asleep_mask)
-+ queue_work(hw_priv->workqueue,
-+ &priv->multicast_stop_work);
-+ xradio_bh_wakeup(hw_priv);
-+ }
-+ break;
-+ }
-+}
-+
-+void xradio_sta_notify(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ enum sta_notify_cmd notify_cmd,
-+ struct ieee80211_sta *sta)
-+{
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct xradio_sta_priv *sta_priv = (struct xradio_sta_priv *)&sta->drv_priv;
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ __xradio_sta_notify(priv, notify_cmd, sta_priv->link_id);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+}
-+
-+static void xradio_ps_notify(struct xradio_vif *priv,
-+ int link_id, bool ps)
-+{
-+ if (link_id > MAX_STA_IN_AP_MODE) {
-+ ap_printk(XRADIO_DBG_WARN,"link_id is invalid=%d\n", link_id);
-+ return;
-+ }
-+
-+ ap_printk(XRADIO_DBG_NIY, "%s for LinkId: %d. STAs asleep: %.8X\n",
-+ ps ? "Stop" : "Start", link_id, priv->sta_asleep_mask);
-+
-+ /* TODO:COMBO: __xradio_sta_notify changed. */
-+ __xradio_sta_notify(priv, ps ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE, link_id);
-+}
-+
-+static int xradio_set_tim_impl(struct xradio_vif *priv, bool aid0_bit_set)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct sk_buff *skb;
-+ struct wsm_update_ie update_ie = {
-+ .what = WSM_UPDATE_IE_BEACON,
-+ .count = 1,
-+ };
-+ u16 tim_offset, tim_length;
-+ ap_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+ ap_printk(XRADIO_DBG_MSG, "%s mcast: %s.\n", __func__,
-+ aid0_bit_set ? "ena" : "dis");
-+
-+ skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, &tim_offset, &tim_length);
-+ if (!skb) {
-+ __xradio_flush(hw_priv, true, priv->if_id);
-+ return -ENOENT;
-+ }
-+
-+ if (tim_offset && tim_length >= 6) {
-+ /* Ignore DTIM count from mac80211:
-+ * firmware handles DTIM internally. */
-+ skb->data[tim_offset + 2] = 0;
-+
-+ /* Set/reset aid0 bit */
-+ if (aid0_bit_set)
-+ skb->data[tim_offset + 4] |= 1;
-+ else
-+ skb->data[tim_offset + 4] &= ~1;
-+ }
-+
-+ update_ie.ies = &skb->data[tim_offset];
-+ update_ie.length = tim_length;
-+ //filter same tim info, yangfh
-+ if(memcmp(priv->last_tim, update_ie.ies, tim_length)) {
-+ WARN_ON(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
-+ memcpy(priv->last_tim, update_ie.ies, tim_length);
-+ ap_printk(XRADIO_DBG_MSG,"%02x %02x %02x %02x %02x %02x\n",
-+ update_ie.ies[0], update_ie.ies[1], update_ie.ies[2],
-+ update_ie.ies[3], update_ie.ies[4], update_ie.ies[5]);
-+ }
-+
-+ dev_kfree_skb(skb);
-+
-+ return 0;
-+}
-+
-+void xradio_set_tim_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv = container_of(work, struct xradio_vif, set_tim_work);
-+ xradio_set_tim_impl(priv, priv->aid0_bit_set);
-+}
-+
-+int xradio_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
-+ bool set)
-+{
-+ struct xradio_sta_priv *sta_priv = (struct xradio_sta_priv *)&sta->drv_priv;
-+ struct xradio_vif *priv = sta_priv->priv;
-+
-+ WARN_ON(priv->mode != NL80211_IFTYPE_AP);
-+ queue_work(priv->hw_priv->workqueue, &priv->set_tim_work);
-+ return 0;
-+}
-+
-+void xradio_set_cts_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, set_cts_work.work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u8 erp_ie[3] = {WLAN_EID_ERP_INFO, 0x1, 0};
-+ struct wsm_update_ie update_ie = {
-+ .what = WSM_UPDATE_IE_BEACON,
-+ .count = 1,
-+ .ies = erp_ie,
-+ .length = 3,
-+ };
-+ u32 erp_info;
-+ __le32 use_cts_prot;
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ erp_info = priv->erp_info;
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ use_cts_prot = (erp_info & WLAN_ERP_USE_PROTECTION)? __cpu_to_le32(1) : 0;
-+
-+ erp_ie[ERP_INFO_BYTE_OFFSET] = erp_info;
-+
-+ ap_printk(XRADIO_DBG_MSG, "ERP information 0x%x\n", erp_info);
-+
-+ /* TODO:COMBO: If 2 interfaces are on the same channel they share
-+ the same ERP values */
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_NON_ERP_PROTECTION,
-+ &use_cts_prot, sizeof(use_cts_prot), priv->if_id));
-+ /* If STA Mode update_ie is not required */
-+ if (priv->mode != NL80211_IFTYPE_STATION) {
-+ WARN_ON(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
-+ }
-+
-+ return;
-+}
-+
-+static int xradio_set_btcoexinfo(struct xradio_vif *priv)
-+{
-+ struct wsm_override_internal_txrate arg;
-+ int ret = 0;
-+
-+ if (priv->mode == NL80211_IFTYPE_STATION) {
-+ /* Plumb PSPOLL and NULL template */
-+ WARN_ON(xradio_upload_pspoll(priv));
-+ WARN_ON(xradio_upload_null(priv));
-+ } else {
-+ return 0;
-+ }
-+
-+ memset(&arg, 0, sizeof(struct wsm_override_internal_txrate));
-+
-+ if (!priv->vif->p2p) {
-+ /* STATION mode */
-+ if (priv->bss_params.operationalRateSet & ~0xF) {
-+ ap_printk(XRADIO_DBG_NIY, "STA has ERP rates\n");
-+ /* G or BG mode */
-+ arg.internalTxRate = (__ffs(
-+ priv->bss_params.operationalRateSet & ~0xF));
-+ } else {
-+ ap_printk(XRADIO_DBG_NIY, "STA has non ERP rates\n");
-+ /* B only mode */
-+ arg.internalTxRate = (__ffs(
-+ priv->association_mode.basicRateSet));
-+ }
-+ arg.nonErpInternalTxRate = (__ffs(
-+ priv->association_mode.basicRateSet));
-+ } else {
-+ /* P2P mode */
-+ arg.internalTxRate = (__ffs(
-+ priv->bss_params.operationalRateSet & ~0xF));
-+ arg.nonErpInternalTxRate = (__ffs(
-+ priv->bss_params.operationalRateSet & ~0xF));
-+ }
-+
-+ ap_printk(XRADIO_DBG_NIY, "BTCOEX_INFO" "MODE %d, internalTxRate : %x,"
-+ "nonErpInternalTxRate: %x\n", priv->mode, arg.internalTxRate,
-+ arg.nonErpInternalTxRate);
-+
-+ ret = WARN_ON(wsm_write_mib(xrwl_vifpriv_to_hwpriv(priv),
-+ WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE,
-+ &arg, sizeof(arg), priv->if_id));
-+
-+ return ret;
-+}
-+
-+void xradio_bss_info_changed(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_bss_conf *info,
-+ u32 changed)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (changed & BSS_CHANGED_BSSID) {
-+ memcpy(priv->bssid, info->bssid, ETH_ALEN);
-+ xradio_setup_mac_pvif(priv);
-+ }
-+
-+ /* TODO: BSS_CHANGED_IBSS */
-+ if (changed & BSS_CHANGED_ARP_FILTER) {
-+ struct wsm_arp_ipv4_filter filter = {0};
-+ int i;
-+ ap_printk(XRADIO_DBG_MSG, "[STA] BSS_CHANGED_ARP_FILTER cnt: %d\n",
-+ info->arp_addr_cnt);
-+
-+ if (info->arp_addr_cnt){
-+ if (vif->type == NL80211_IFTYPE_STATION)
-+ filter.enable = (u32)XRADIO_ENABLE_ARP_FILTER_OFFLOAD;
-+ else if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ filter.enable = (u32)(1<<1);
-+ else
-+ filter.enable = 0;
-+ }
-+
-+ /* Currently only one IP address is supported by firmware.
-+ * In case of more IPs arp filtering will be disabled. */
-+ if (info->arp_addr_cnt > 0 &&
-+ info->arp_addr_cnt <= WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES) {
-+ for (i = 0; i < info->arp_addr_cnt; i++) {
-+ filter.ipv4Address[i] = info->arp_addr_list[i];
-+ ap_printk(XRADIO_DBG_NIY, "[STA]addr[%d]: 0x%X\n", i, filter.ipv4Address[i]);
-+ }
-+ } else
-+ filter.enable = 0;
-+
-+ if (filter.enable)
-+ xradio_set_arpreply(dev, vif);
-+
-+ priv->filter4.enable = filter.enable;
-+ ap_printk(XRADIO_DBG_NIY, "[STA]arp ip filter enable: %d\n", __le32_to_cpu(filter.enable));
-+
-+ if (wsm_set_arp_ipv4_filter(hw_priv, &filter, priv->if_id))
-+ WARN_ON(1);
-+
-+ if (filter.enable &&
-+ (priv->join_status == XRADIO_JOIN_STATUS_STA)) {
-+ /* Firmware requires that value for this 1-byte field must
-+ * be specified in units of 500us. Values above the 128ms
-+ * threshold are not supported. */
-+ //if (info->dynamic_ps_timeout >= 0x80)
-+ // priv->powersave_mode.fastPsmIdlePeriod = 0xFF;
-+ //else
-+ // priv->powersave_mode.fastPsmIdlePeriod = info->dynamic_ps_timeout << 1;
-+
-+ priv->powersave_mode.fastPsmIdlePeriod = 200;//when connected,the dev->conf.dynamic_ps_timeout value is 0
-+ priv->powersave_mode.apPsmChangePeriod = 200; //100ms, add by yangfh
-+ ap_printk(XRADIO_DBG_NIY, "[STA]fastPsmIdle=%d, apPsmChange=%d\n",
-+ priv->powersave_mode.fastPsmIdlePeriod,
-+ priv->powersave_mode.apPsmChangePeriod);
-+
-+ if (priv->setbssparams_done) {
-+ int ret = 0;
-+ struct wsm_set_pm pm = priv->powersave_mode;
-+ if (priv->user_power_set_true)
-+ priv->powersave_mode.pmMode = priv->user_pm_mode;
-+ else if ((priv->power_set_true &&
-+ ((priv->powersave_mode.pmMode == WSM_PSM_ACTIVE) ||
-+ (priv->powersave_mode.pmMode == WSM_PSM_PS))) ||
-+ !priv->power_set_true)
-+ priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
-+
-+ ret = xradio_set_pm (priv, &priv->powersave_mode);
-+ if(ret)
-+ priv->powersave_mode = pm;
-+ } else {
-+ priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
-+ }
-+ priv->power_set_true = 0;
-+ priv->user_power_set_true = 0;
-+ }
-+ }
-+
-+ if (changed & BSS_CHANGED_BEACON) {
-+ ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_BEACON\n");
-+#ifdef HIDDEN_SSID
-+ if(priv->join_status != XRADIO_JOIN_STATUS_AP) {
-+ priv->hidden_ssid = info->hidden_ssid;
-+ priv->ssid_length = info->ssid_len;
-+ memcpy(priv->ssid, info->ssid, info->ssid_len);
-+ } else
-+ ap_printk(XRADIO_DBG_NIY, "priv->join_status=%d\n", priv->join_status);
-+#endif
-+ WARN_ON(xradio_upload_beacon(priv));
-+ WARN_ON(xradio_update_beaconing(priv));
-+ }
-+
-+ if (changed & BSS_CHANGED_BEACON_ENABLED) {
-+ ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_BEACON_ENABLED dummy\n");
-+ priv->enable_beacon = info->enable_beacon;
-+ }
-+
-+ if (changed & BSS_CHANGED_BEACON_INT) {
-+ ap_printk(XRADIO_DBG_NIY, "CHANGED_BEACON_INT\n");
-+ /* Restart AP only when connected */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(xradio_update_beaconing(priv));
-+ }
-+
-+
-+ if (changed & BSS_CHANGED_ASSOC) {
-+ wsm_lock_tx(hw_priv);
-+ priv->wep_default_key_id = -1;
-+ wsm_unlock_tx(hw_priv);
-+
-+ if (!info->assoc /* && !info->ibss_joined */) {
-+ priv->cqm_link_loss_count = XRADIO_LINK_LOSS_THOLD_DEF;
-+ priv->cqm_beacon_loss_count = XRADIO_BSS_LOSS_THOLD_DEF;
-+ priv->cqm_tx_failure_thold = 0;
-+ }
-+ priv->cqm_tx_failure_count = 0;
-+ }
-+
-+ if (changed &
-+ (BSS_CHANGED_ASSOC |
-+ BSS_CHANGED_BASIC_RATES |
-+ BSS_CHANGED_ERP_PREAMBLE |
-+ BSS_CHANGED_HT |
-+ BSS_CHANGED_ERP_SLOT)) {
-+ int is_combo = 0;
-+ int i;
-+ struct xradio_vif *tmp_priv;
-+ ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_ASSOC.\n");
-+ if (info->assoc) { /* TODO: ibss_joined */
-+ struct ieee80211_sta *sta = NULL;
-+ if (info->dtim_period)
-+ priv->join_dtim_period = info->dtim_period;
-+ priv->beacon_int = info->beacon_int;
-+
-+ /* Associated: kill join timeout */
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+
-+ rcu_read_lock();
-+ if (info->bssid)
-+ sta = ieee80211_find_sta(vif, info->bssid);
-+ if (sta) {
-+ /* TODO:COMBO:Change this once
-+ * mac80211 changes are available */
-+ BUG_ON(!hw_priv->channel);
-+ hw_priv->ht_oper.ht_cap = sta->ht_cap;
-+ priv->bss_params.operationalRateSet =__cpu_to_le32(
-+ xradio_rate_mask_to_wsm(hw_priv, sta->supp_rates[hw_priv->channel->band]));
-+ /* TODO by Icenowy: I think this may lead to some problems. */
-+// hw_priv->ht_oper.channel_type = info->channel_type;
-+ hw_priv->ht_oper.operation_mode = info->ht_operation_mode;
-+ } else {
-+ memset(&hw_priv->ht_oper, 0, sizeof(hw_priv->ht_oper));
-+ priv->bss_params.operationalRateSet = -1;
-+ }
-+ rcu_read_unlock();
-+ priv->htcap = (sta && xradio_is_ht(&hw_priv->ht_oper));
-+ xradio_for_each_vif(hw_priv, tmp_priv, i) {
-+ if (!tmp_priv)
-+ continue;
-+ if (tmp_priv->join_status >= XRADIO_JOIN_STATUS_STA)
-+ is_combo++;
-+ }
-+
-+ if (is_combo > 1) {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ ap_printk(XRADIO_DBG_WARN, "%sASSOC is_combo %d\n",
-+ (priv->join_status == XRADIO_JOIN_STATUS_STA)?"[STA] ":"",
-+ hw_priv->vif0_throttle);
-+ } else if ((priv->join_status == XRADIO_JOIN_STATUS_STA) && priv->htcap) {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11N_THROTTLE;
-+ ap_printk(XRADIO_DBG_WARN, "[STA] ASSOC HTCAP 11N %d\n",hw_priv->vif0_throttle);
-+ } else {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ ap_printk(XRADIO_DBG_WARN, "ASSOC not_combo 11BG %d\n",hw_priv->vif0_throttle);
-+ }
-+
-+ if (sta) {
-+ __le32 val = 0;
-+ if (hw_priv->ht_oper.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) {
-+ ap_printk(XRADIO_DBG_NIY,"[STA] Non-GF STA present\n");
-+ /* Non Green field capable STA */
-+ val = __cpu_to_le32(BIT(1));
-+ }
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MID_ID_SET_HT_PROTECTION,
-+ &val, sizeof(val), priv->if_id));
-+ }
-+
-+ priv->association_mode.greenfieldMode = xradio_ht_greenfield(&hw_priv->ht_oper);
-+ priv->association_mode.flags =
-+ WSM_ASSOCIATION_MODE_SNOOP_ASSOC_FRAMES |
-+ WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE |
-+ WSM_ASSOCIATION_MODE_USE_HT_MODE |
-+ WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET |
-+ WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING;
-+
-+ priv->association_mode.preambleType =
-+ (info->use_short_preamble ? WSM_JOIN_PREAMBLE_SHORT : WSM_JOIN_PREAMBLE_LONG);
-+ priv->association_mode.basicRateSet = __cpu_to_le32(
-+ xradio_rate_mask_to_wsm(hw_priv,info->basic_rates));
-+ priv->association_mode.mpduStartSpacing =
-+ xradio_ht_ampdu_density(&hw_priv->ht_oper);
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //priv->cqm_beacon_loss_count = info->cqm_beacon_miss_thold;
-+ //priv->cqm_tx_failure_thold = info->cqm_tx_fail_thold;
-+ //priv->cqm_tx_failure_count = 0;
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+
-+ priv->bss_params.beaconLostCount = (priv->cqm_beacon_loss_count ?
-+ priv->cqm_beacon_loss_count : priv->cqm_link_loss_count);
-+
-+ priv->bss_params.aid = info->aid;
-+
-+ if (priv->join_dtim_period < 1)
-+ priv->join_dtim_period = 1;
-+
-+ ap_printk(XRADIO_DBG_MSG, "[STA] DTIM %d, interval: %d\n",
-+ priv->join_dtim_period, priv->beacon_int);
-+ ap_printk(XRADIO_DBG_MSG, "[STA] Preamble: %d, " \
-+ "Greenfield: %d, Aid: %d, Rates: 0x%.8X, Basic: 0x%.8X\n",
-+ priv->association_mode.preambleType,
-+ priv->association_mode.greenfieldMode,
-+ priv->bss_params.aid,
-+ priv->bss_params.operationalRateSet,
-+ priv->association_mode.basicRateSet);
-+ WARN_ON(wsm_set_association_mode(hw_priv, &priv->association_mode, priv->if_id));
-+ WARN_ON(wsm_keep_alive_period(hw_priv, XRADIO_KEEP_ALIVE_PERIOD /* sec */,
-+ priv->if_id));
-+ WARN_ON(wsm_set_bss_params(hw_priv, &priv->bss_params, priv->if_id));
-+ priv->setbssparams_done = true;
-+#ifdef XRADIO_USE_LONG_DTIM_PERIOD
-+{
-+ int join_dtim_period_extend;
-+ if (priv->join_dtim_period <= 3) {
-+ join_dtim_period_extend = priv->join_dtim_period * 3;
-+ } else if (priv->join_dtim_period <= 5) {
-+ join_dtim_period_extend = priv->join_dtim_period * 2;
-+ } else {
-+ join_dtim_period_extend = priv->join_dtim_period;
-+ }
-+ WARN_ON(wsm_set_beacon_wakeup_period(hw_priv,
-+ ((priv->beacon_int * join_dtim_period_extend) > MAX_BEACON_SKIP_TIME_MS
-+ ? 1 : join_dtim_period_extend) , 0, priv->if_id));
-+}
-+#else
-+ WARN_ON(wsm_set_beacon_wakeup_period(hw_priv,
-+ ((priv->beacon_int * priv->join_dtim_period) > MAX_BEACON_SKIP_TIME_MS
-+ ? 1 : priv->join_dtim_period) , 0, priv->if_id));
-+#endif
-+ if (priv->htcap) {
-+ wsm_lock_tx(hw_priv);
-+ /* Statically enabling block ack for TX/RX */
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv, hw_priv->ba_tid_mask,
-+ hw_priv->ba_tid_mask, priv->if_id));
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ /*set ps active,avoid that when connecting process,the device sleeps,then can't receive pkts.*/
-+ if (changed & BSS_CHANGED_ASSOC)
-+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+ if (priv->vif->p2p) {
-+ ap_printk(XRADIO_DBG_NIY, "[STA] Setting p2p powersave configuration.\n");
-+ WARN_ON(wsm_set_p2p_ps_modeinfo(hw_priv, &priv->p2p_ps_modeinfo, priv->if_id));
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //xradio_notify_noa(priv, XRADIO_NOA_NOTIFICATION_DELAY);
-+#endif
-+ }
-+
-+ if (priv->mode == NL80211_IFTYPE_STATION)
-+ WARN_ON(xradio_upload_qosnull(priv));
-+
-+ if (hw_priv->is_BT_Present)
-+ WARN_ON(xradio_set_btcoexinfo(priv));
-+#if 0
-+ /* It's better to override internal TX rete; otherwise
-+ * device sends RTS at too high rate. However device
-+ * can't receive CTS at 1 and 2 Mbps. Well, 5.5 is a
-+ * good choice for RTS/CTS, but that means PS poll
-+ * will be sent at the same rate - impact on link
-+ * budget. Not sure what is better.. */
-+
-+ /* Update: internal rate selection algorythm is not
-+ * bad: if device is not receiving CTS at high rate,
-+ * it drops RTS rate.
-+ * So, conclusion: if-0 the code. Keep code just for
-+ * information:
-+ * Do not touch WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE! */
-+
-+ /* ~3 is a bug in device: RTS/CTS is not working at
-+ * low rates */
-+ __le32 internal_tx_rate = __cpu_to_le32(
-+ __ffs(priv->association_mode.basicRateSet & ~3));
-+ WARN_ON(wsm_write_mib(priv, WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE,
-+ &internal_tx_rate,sizeof(internal_tx_rate)));
-+#endif
-+ } else {
-+ memset(&priv->association_mode, 0, sizeof(priv->association_mode));
-+ memset(&priv->bss_params, 0, sizeof(priv->bss_params));
-+ }
-+ }
-+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT)) {
-+ u32 prev_erp_info = priv->erp_info;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ if (info->use_cts_prot)
-+ priv->erp_info |= WLAN_ERP_USE_PROTECTION;
-+ else if (!(prev_erp_info & WLAN_ERP_NON_ERP_PRESENT))
-+ priv->erp_info &= ~WLAN_ERP_USE_PROTECTION;
-+
-+ if (prev_erp_info != priv->erp_info)
-+ queue_delayed_work(hw_priv->workqueue, &priv->set_cts_work, 0*HZ);
-+ }
-+ }
-+
-+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_SLOT)) {
-+ __le32 slot_time = info->use_short_slot ? __cpu_to_le32(9) : __cpu_to_le32(20);
-+ ap_printk(XRADIO_DBG_MSG, "[STA] Slot time :%d us.\n", __le32_to_cpu(slot_time));
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_SLOT_TIME, &slot_time,
-+ sizeof(slot_time), priv->if_id));
-+ }
-+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_CQM)) {
-+ struct wsm_rcpi_rssi_threshold threshold = {
-+ .rollingAverageCount = 8,
-+ };
-+
-+#if 0
-+ /* For verification purposes */
-+ info->cqm_rssi_thold = -50;
-+ info->cqm_rssi_hyst = 4;
-+#endif /* 0 */
-+
-+ ap_printk(XRADIO_DBG_NIY, "[CQM] RSSI threshold subscribe: %d(+-%d)\n",
-+ info->cqm_rssi_thold, info->cqm_rssi_hyst);
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ priv->cqm_rssi_thold = info->cqm_rssi_thold;
-+ priv->cqm_rssi_hyst = info->cqm_rssi_hyst;
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+
-+ if (info->cqm_rssi_thold || info->cqm_rssi_hyst) {
-+ /* RSSI subscription enabled */
-+ /* TODO: It's not a correct way of setting threshold.
-+ * Upper and lower must be set equal here and adjusted
-+ * in callback. However current implementation is much
-+ * more relaible and stable. */
-+ if (priv->cqm_use_rssi) {
-+ threshold.upperThreshold = info->cqm_rssi_thold + info->cqm_rssi_hyst;
-+ threshold.lowerThreshold = info->cqm_rssi_thold;
-+ } else {
-+ /* convert RSSI to RCPI, RCPI = (RSSI + 110) * 2 */
-+ threshold.upperThreshold = (info->cqm_rssi_thold + info->cqm_rssi_hyst + 110)<<1;
-+ threshold.lowerThreshold = (info->cqm_rssi_thold + 110)<<1;
-+ }
-+ threshold.rssiRcpiMode |= WSM_RCPI_RSSI_THRESHOLD_ENABLE;
-+ } else {
-+ /* There is a bug in FW, see sta.c. We have to enable
-+ * dummy subscription to get correct RSSI values. */
-+ threshold.rssiRcpiMode |= WSM_RCPI_RSSI_THRESHOLD_ENABLE |
-+ WSM_RCPI_RSSI_DONT_USE_UPPER |
-+ WSM_RCPI_RSSI_DONT_USE_LOWER;
-+ }
-+ WARN_ON(wsm_set_rcpi_rssi_threshold(hw_priv, &threshold, priv->if_id));
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //priv->cqm_tx_failure_thold = info->cqm_tx_fail_thold;
-+ //priv->cqm_tx_failure_count = 0;
-+
-+ //if (priv->cqm_beacon_loss_count != info->cqm_beacon_miss_thold) {
-+ // priv->cqm_beacon_loss_count = info->cqm_beacon_miss_thold;
-+ // priv->bss_params.beaconLostCount = (priv->cqm_beacon_loss_count?
-+ // priv->cqm_beacon_loss_count : priv->cqm_link_loss_count);
-+ /* Make sure we are associated before sending
-+ * set_bss_params to firmware */
-+ if (priv->bss_params.aid) {
-+ WARN_ON(wsm_set_bss_params(hw_priv, &priv->bss_params, priv->if_id));
-+ priv->setbssparams_done = true;
-+ }
-+ //}
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ }
-+ /*
-+ * in linux3.4 mac,the enum ieee80211_bss_change variable doesn't have
-+ * BSS_CHANGED_PS and BSS_CHANGED_RETRY_LIMITS enum value.
-+ */
-+#if 0
-+ if (changed & BSS_CHANGED_PS) {
-+ if (info->ps_enabled == false)
-+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
-+ else if (info->dynamic_ps_timeout <= 0)
-+ priv->powersave_mode.pmMode = WSM_PSM_PS;
-+ else
-+ priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
-+
-+ ap_printk(XRADIO_DBG_MSG, "[STA] Aid: %d, Joined: %s, Powersave: %s\n",
-+ priv->bss_params.aid,
-+ priv->join_status == XRADIO_JOIN_STATUS_STA ? "yes" : "no",
-+ (priv->powersave_mode.pmMode == WSM_PSM_ACTIVE ? "WSM_PSM_ACTIVE" :
-+ priv->powersave_mode.pmMode == WSM_PSM_PS ? "WSM_PSM_PS" :
-+ priv->powersave_mode.pmMode == WSM_PSM_FAST_PS ? "WSM_PSM_FAST_PS" :
-+ "UNKNOWN"));
-+
-+ /* Firmware requires that value for this 1-byte field must
-+ * be specified in units of 500us. Values above the 128ms
-+ * threshold are not supported. */
-+ if (info->dynamic_ps_timeout >= 0x80)
-+ priv->powersave_mode.fastPsmIdlePeriod = 0xFF;
-+ else
-+ priv->powersave_mode.fastPsmIdlePeriod = info->dynamic_ps_timeout << 1;
-+ ap_printk(XRADIO_DBG_NIY, "[STA]CHANGED_PS fastPsmIdle=%d, apPsmChange=%d\n",
-+ priv->powersave_mode.fastPsmIdlePeriod,
-+ priv->powersave_mode.apPsmChangePeriod);
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA && priv->bss_params.aid &&
-+ priv->setbssparams_done && priv->filter4.enable)
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+ else
-+ priv->power_set_true = 1;
-+ }
-+
-+ if (changed & BSS_CHANGED_RETRY_LIMITS) {
-+ ap_printk(XRADIO_DBG_NIY, "Retry limits: %d (long), %d (short).\n",
-+ info->retry_long, info->retry_short);
-+ spin_lock_bh(&hw_priv->tx_policy_cache.lock);
-+ /*TODO:COMBO: for now it's still handled per hw and kept
-+ * in xradio_common */
-+ hw_priv->long_frame_max_tx_count = info->retry_long;
-+ hw_priv->short_frame_max_tx_count =
-+ (info->retry_short < 0x0F ? info->retry_short : 0x0F);
-+ hw_priv->hw->max_rate_tries = hw_priv->short_frame_max_tx_count;
-+ spin_unlock_bh(&hw_priv->tx_policy_cache.lock);
-+ /* TBD: I think we don't need tx_policy_force_upload().
-+ * Outdated policies will leave cache in a normal way. */
-+ /* WARN_ON(tx_policy_force_upload(priv)); */
-+ }
-+#endif
-+ /*in linux3.4 mac,the enum ieee80211_bss_change variable doesn't have BSS_CHANGED_P2P_PS enum value*/
-+#if 0
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ if (changed & BSS_CHANGED_P2P_PS) {
-+ struct wsm_p2p_ps_modeinfo *modeinfo;
-+ modeinfo = &priv->p2p_ps_modeinfo;
-+ ap_printk(XRADIO_DBG_NIY, "[AP] BSS_CHANGED_P2P_PS\n");
-+ ap_printk(XRADIO_DBG_NIY, "[AP] Legacy PS: %d for AID %d in %d mode.\n",
-+ info->p2p_ps.legacy_ps, priv->bss_params.aid, priv->join_status);
-+
-+ if (info->p2p_ps.legacy_ps >= 0) {
-+ if (info->p2p_ps.legacy_ps > 0)
-+ priv->powersave_mode.pmMode = WSM_PSM_PS;
-+ else
-+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
-+
-+ if(info->p2p_ps.ctwindow && info->p2p_ps.opp_ps)
-+ priv->powersave_mode.pmMode = WSM_PSM_PS;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA)
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+ }
-+
-+ ap_printk(XRADIO_DBG_MSG, "[AP] CTWindow: %d\n", info->p2p_ps.ctwindow);
-+ if (info->p2p_ps.ctwindow >= 128)
-+ modeinfo->oppPsCTWindow = 127;
-+ else if (info->p2p_ps.ctwindow >= 0)
-+ modeinfo->oppPsCTWindow = info->p2p_ps.ctwindow;
-+
-+ ap_printk(XRADIO_DBG_MSG, "[AP] Opportunistic: %d\n", info->p2p_ps.opp_ps);
-+ switch (info->p2p_ps.opp_ps) {
-+ case 0:
-+ modeinfo->oppPsCTWindow &= ~(BIT(7));
-+ break;
-+ case 1:
-+ modeinfo->oppPsCTWindow |= BIT(7);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ ap_printk(XRADIO_DBG_MSG, "[AP] NOA: %d, %d, %d, %d\n",
-+ info->p2p_ps.count, info->p2p_ps.start,
-+ info->p2p_ps.duration, info->p2p_ps.interval);
-+ /* Notice of Absence */
-+ modeinfo->count = info->p2p_ps.count;
-+
-+ if (info->p2p_ps.count) {
-+ /* In case P2P_GO we need some extra time to be sure
-+ * we will update beacon/probe_resp IEs correctly */
-+#define NOA_DELAY_START_MS 300
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ modeinfo->startTime = __cpu_to_le32(info->p2p_ps.start + NOA_DELAY_START_MS);
-+ else
-+ modeinfo->startTime = __cpu_to_le32(info->p2p_ps.start);
-+ modeinfo->duration = __cpu_to_le32(info->p2p_ps.duration);
-+ modeinfo->interval = __cpu_to_le32(info->p2p_ps.interval);
-+ modeinfo->dtimCount = 1;
-+ modeinfo->reserved = 0;
-+ } else {
-+ modeinfo->dtimCount = 0;
-+ modeinfo->startTime = 0;
-+ modeinfo->reserved = 0;
-+ modeinfo->duration = 0;
-+ modeinfo->interval = 0;
-+ }
-+
-+#if defined(CONFIG_XRADIO_DEBUG)
-+ print_hex_dump_bytes("p2p_set_ps_modeinfo: ", DUMP_PREFIX_NONE,
-+ (u8 *)modeinfo, sizeof(*modeinfo));
-+#endif /* CONFIG_XRADIO_DEBUG */
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA ||
-+ priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ WARN_ON(wsm_set_p2p_ps_modeinfo(hw_priv, modeinfo, priv->if_id));
-+ }
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ /* Temporary solution while firmware don't support NOA change
-+ * notification yet */
-+ xradio_notify_noa(priv, 10);
-+#endif
-+ }
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+#endif
-+ mutex_unlock(&hw_priv->conf_mutex);
-+}
-+
-+void xradio_multicast_start_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, multicast_start_work);
-+ long tmo = priv->join_dtim_period * (priv->beacon_int + 20) * HZ / 1024;
-+
-+ cancel_work_sync(&priv->multicast_stop_work);
-+ if (!priv->aid0_bit_set) {
-+ wsm_lock_tx(priv->hw_priv);
-+ xradio_set_tim_impl(priv, true);
-+ priv->aid0_bit_set = true;
-+ mod_timer(&priv->mcast_timeout, jiffies + tmo);
-+ wsm_unlock_tx(priv->hw_priv);
-+ }
-+}
-+
-+void xradio_multicast_stop_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, multicast_stop_work);
-+
-+ if (priv->aid0_bit_set) {
-+ del_timer_sync(&priv->mcast_timeout);
-+ wsm_lock_tx(priv->hw_priv);
-+ priv->aid0_bit_set = false;
-+ xradio_set_tim_impl(priv, false);
-+ wsm_unlock_tx(priv->hw_priv);
-+ }
-+}
-+
-+void xradio_mcast_timeout(struct timer_list *t)
-+{
-+ struct xradio_vif *priv = from_timer(priv, t, mcast_timeout);
-+
-+ ap_printk(XRADIO_DBG_WARN, "Multicast delivery timeout.\n");
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->tx_multicast = priv->aid0_bit_set && priv->buffered_multicasts;
-+ if (priv->tx_multicast)
-+ xradio_bh_wakeup(xrwl_vifpriv_to_hwpriv(priv));
-+ spin_unlock_bh(&priv->ps_state_lock);
-+}
-+
-+int xradio_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_ampdu_params *params)
-+{
-+ /* Aggregation is implemented fully in firmware,
-+ * including block ack negotiation.
-+ * In case of AMPDU aggregation in RX direction
-+ * re-ordering of packets takes place on host. mac80211
-+ * needs the ADDBA Request to setup reodering.mac80211 also
-+ * sends ADDBA Response which is discarded in the driver as
-+ * FW generates the ADDBA Response on its own.*/
-+ int ret;
-+
-+ switch (params->action) {
-+ case IEEE80211_AMPDU_RX_START:
-+ case IEEE80211_AMPDU_RX_STOP:
-+ /* Just return OK to mac80211 */
-+ ret = 0;
-+ break;
-+ default:
-+ ret = -ENOTSUPP;
-+ }
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+/* WSM callback */
-+void xradio_suspend_resume(struct xradio_vif *priv, struct wsm_suspend_resume *arg)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+#if 0
-+ ap_printk(XRADIO_DBG_MSG, "[AP] %s: %s\n",
-+ arg->stop ? "stop" : "start",
-+ arg->multicast ? "broadcast" : "unicast");
-+#endif
-+ if (arg->multicast) {
-+ bool cancel_tmo = false;
-+ spin_lock_bh(&priv->ps_state_lock);
-+ if (arg->stop) {
-+ priv->tx_multicast = false;
-+ } else {
-+ /* Firmware sends this indication every DTIM if there
-+ * is a STA in powersave connected. There is no reason
-+ * to suspend, following wakeup will consume much more
-+ * power than it could be saved. */
-+ xradio_pm_stay_awake(&hw_priv->pm_state, (priv->join_dtim_period *
-+ (priv->beacon_int + 20) * HZ / 1024));
-+ priv->tx_multicast = priv->aid0_bit_set && priv->buffered_multicasts;
-+ if (priv->tx_multicast) {
-+ cancel_tmo = true;
-+ xradio_bh_wakeup(hw_priv);
-+ }
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ if (cancel_tmo)
-+ del_timer_sync(&priv->mcast_timeout);
-+ } else {
-+ spin_lock_bh(&priv->ps_state_lock);
-+ xradio_ps_notify(priv, arg->link_id, arg->stop);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ if (!arg->stop)
-+ xradio_bh_wakeup(hw_priv);
-+ }
-+ return;
-+}
-+
-+/* ******************************************************************** */
-+/* AP privates */
-+
-+static int xradio_upload_beacon(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_BEACON,
-+ };
-+ struct ieee80211_mgmt *mgmt;
-+ u8 *erp_inf, *ies, *ht_oper;
-+ u32 ies_len;
-+
-+ if (priv->vif->p2p || hw_priv->channel->band == NL80211_BAND_5GHZ)
-+ frame.rate = WSM_TRANSMIT_RATE_6;
-+
-+ frame.skb = ieee80211_beacon_get(priv->hw, priv->vif);
-+ if (WARN_ON(!frame.skb))
-+ return -ENOMEM;
-+
-+ mgmt = (void *)frame.skb->data;
-+ ies = mgmt->u.beacon.variable;
-+ ies_len = frame.skb->len - (u32)(ies - (u8 *)mgmt);
-+
-+ ht_oper = (u8 *)cfg80211_find_ie( WLAN_EID_HT_OPERATION, ies, ies_len);
-+ if (ht_oper) {
-+ /* Enable RIFS*/
-+ ht_oper[3] |= 8;
-+ }
-+
-+ erp_inf = (u8 *)cfg80211_find_ie(WLAN_EID_ERP_INFO, ies, ies_len);
-+ if (erp_inf) {
-+ if (erp_inf[ERP_INFO_BYTE_OFFSET]
-+ & WLAN_ERP_BARKER_PREAMBLE)
-+ priv->erp_info |= WLAN_ERP_BARKER_PREAMBLE;
-+ else
-+ priv->erp_info &= ~WLAN_ERP_BARKER_PREAMBLE;
-+
-+ if (erp_inf[ERP_INFO_BYTE_OFFSET]
-+ & WLAN_ERP_NON_ERP_PRESENT) {
-+ priv->erp_info |= WLAN_ERP_USE_PROTECTION;
-+ priv->erp_info |= WLAN_ERP_NON_ERP_PRESENT;
-+ } else {
-+ priv->erp_info &= ~WLAN_ERP_USE_PROTECTION;
-+ priv->erp_info &= ~WLAN_ERP_NON_ERP_PRESENT;
-+ }
-+ }
-+
-+#ifdef HIDDEN_SSID
-+ if (priv->hidden_ssid) {
-+ u8 *ssid_ie;
-+ u8 ssid_len;
-+
-+ ap_printk(XRADIO_DBG_NIY, "%s: hidden_ssid set\n", __func__);
-+ ssid_ie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
-+ WARN_ON(!ssid_ie);
-+ ssid_len = ssid_ie[1];
-+ if (ssid_len) {
-+ ap_printk(XRADIO_DBG_MSG, "hidden_ssid with zero content ssid\n");
-+ ssid_ie[1] = 0;
-+ memmove(ssid_ie + 2, ssid_ie + 2 + ssid_len,
-+ (ies + ies_len -
-+ (ssid_ie + 2 + ssid_len)));
-+ frame.skb->len -= ssid_len;
-+ } else {
-+ ap_printk(XRADIO_DBG_WARN, "hidden ssid with ssid len 0 not supported");
-+ dev_kfree_skb(frame.skb);
-+ return -1;
-+ }
-+ }
-+#endif
-+
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ if (!ret) {
-+#ifdef PROBE_RESP_EXTRA_IE
-+ ret = xradio_upload_proberesp(priv);
-+#else
-+ /* TODO: Distille probe resp; remove TIM
-+ * and other beacon-specific IEs */
-+ *(__le16 *)frame.skb->data = __cpu_to_le16(
-+ IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
-+ frame.frame_type = WSM_FRAME_TYPE_PROBE_RESPONSE;
-+ /* TODO: Ideally probe response template should separately
-+ configured by supplicant through openmac. This is a
-+ temporary work-around known to fail p2p group info
-+ attribute related tests
-+ */
-+ if (0 /* priv->vif->p2p */)
-+ ret = wsm_set_probe_responder(priv, true);
-+ else {
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ WARN_ON(wsm_set_probe_responder(priv, false));
-+ }
-+#endif
-+ }
-+ dev_kfree_skb(frame.skb);
-+
-+ return ret;
-+}
-+
-+#ifdef PROBE_RESP_EXTRA_IE
-+static int xradio_upload_proberesp(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PROBE_RESPONSE,
-+ };
-+#ifdef HIDDEN_SSID
-+ u8 *ssid_ie;
-+#endif
-+
-+ if (priv->vif->p2p || hw_priv->channel->band == NL80211_BAND_5GHZ)
-+ frame.rate = WSM_TRANSMIT_RATE_6;
-+
-+ frame.skb = ieee80211_proberesp_get(priv->hw, priv->vif);
-+ if (WARN_ON(!frame.skb))
-+ return -ENOMEM;
-+
-+#ifdef HIDDEN_SSID
-+ if (priv->hidden_ssid) {
-+ int offset;
-+ u8 ssid_len;
-+ /* we are assuming beacon from upper layer will always contain
-+ zero filled ssid for hidden ap. The beacon shall never have
-+ ssid len = 0.
-+ */
-+
-+ offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
-+ ssid_ie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, frame.skb->data + offset,
-+ frame.skb->len - offset);
-+ ssid_len = ssid_ie[1];
-+ if (ssid_len && (ssid_len == priv->ssid_length)) {
-+ memcpy(ssid_ie + 2, priv->ssid, ssid_len);
-+ } else {
-+ ap_printk(XRADIO_DBG_ERROR, "%s: hidden ssid with mismatched ssid_len %d\n",
-+ __func__, ssid_len);
-+ dev_kfree_skb(frame.skb);
-+ return -1;
-+ }
-+ }
-+#endif
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ WARN_ON(wsm_set_probe_responder(priv, false));
-+
-+ dev_kfree_skb(frame.skb);
-+
-+ return ret;
-+}
-+#endif
-+
-+static int xradio_upload_pspoll(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PS_POLL,
-+ .rate = 0xFF,
-+ };
-+
-+ frame.skb = ieee80211_pspoll_get(priv->hw, priv->vif);
-+ if (WARN_ON(!frame.skb))
-+ return -ENOMEM;
-+ ret = wsm_set_template_frame(xrwl_vifpriv_to_hwpriv(priv), &frame, priv->if_id);
-+ dev_kfree_skb(frame.skb);
-+ return ret;
-+}
-+
-+static int xradio_upload_null(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_NULL,
-+ .rate = 0xFF,
-+ };
-+
-+ frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false);
-+ if (WARN_ON(!frame.skb))
-+ return -ENOMEM;
-+
-+ ret = wsm_set_template_frame(xrwl_vifpriv_to_hwpriv(priv), &frame, priv->if_id);
-+ dev_kfree_skb(frame.skb);
-+ return ret;
-+}
-+
-+static int xradio_upload_qosnull(struct xradio_vif *priv)
-+{
-+ struct ieee80211_qos_hdr* qos_null_template;
-+ struct sk_buff* skb;
-+ int ret = 0;
-+ struct xradio_common *hw_priv =xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_QOS_NULL,
-+ .rate = 0xFF,
-+ };
-+ if (!hw_priv)
-+ ap_printk(XRADIO_DBG_ERROR,"%s: Cannot find xradio_common pointer!\n",__FUNCTION__);
-+ /*set qos template*/
-+ skb = dev_alloc_skb(hw_priv->hw->extra_tx_headroom + sizeof(struct ieee80211_qos_hdr));
-+ if (!skb) {
-+ ap_printk(XRADIO_DBG_ERROR,"%s: failed to allocate buffer for qos nullfunc template!\n",__FUNCTION__);
-+ return -1;
-+ }
-+ skb_reserve(skb, hw_priv->hw->extra_tx_headroom);
-+ qos_null_template = (struct ieee80211_qos_hdr *)skb_put(skb,sizeof(struct ieee80211_qos_hdr));
-+ memset(qos_null_template, 0, sizeof(struct ieee80211_qos_hdr));
-+ memcpy(qos_null_template->addr1, priv->vif->bss_conf.bssid, ETH_ALEN);
-+ memcpy(qos_null_template->addr2, priv->vif->addr, ETH_ALEN);
-+ memcpy(qos_null_template->addr3, priv->vif->bss_conf.bssid, ETH_ALEN);
-+ qos_null_template->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
-+ IEEE80211_STYPE_QOS_NULLFUNC |
-+ IEEE80211_FCTL_TODS);
-+ frame.skb = skb;
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ dev_kfree_skb(frame.skb);
-+ return ret;
-+}
-+
-+/* This API is nolonegr present in WSC */
-+#if 0
-+static int xradio_enable_beaconing(struct xradio_vif *priv,
-+ bool enable)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_beacon_transmit transmit = {
-+ .enableBeaconing = enable,
-+ };
-+
-+ return wsm_beacon_transmit(hw_priv, &transmit, priv->if_id);
-+}
-+#endif
-+
-+static int xradio_start_ap(struct xradio_vif *priv)
-+{
-+ int ret;
-+#ifndef HIDDEN_SSID
-+ const u8 *ssidie;
-+ struct sk_buff *skb;
-+ int offset;
-+#endif
-+ struct ieee80211_bss_conf *conf = &priv->vif->bss_conf;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_start start = {
-+ .mode = priv->vif->p2p ? WSM_START_MODE_P2P_GO : WSM_START_MODE_AP,
-+ /* TODO:COMBO:Change once mac80211 support is available */
-+ .band = (hw_priv->channel->band == NL80211_BAND_5GHZ) ?
-+ WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G,
-+ .channelNumber = hw_priv->channel->hw_value,
-+ .beaconInterval = conf->beacon_int,
-+ .DTIMPeriod = conf->dtim_period,
-+ .preambleType = conf->use_short_preamble ?
-+ WSM_JOIN_PREAMBLE_SHORT :WSM_JOIN_PREAMBLE_LONG,
-+ .probeDelay = 100,
-+ .basicRateSet = xradio_rate_mask_to_wsm(hw_priv, conf->basic_rates),
-+ };
-+
-+#ifdef TES_P2P_000B_EXTEND_INACTIVITY_CNT
-+ ///w, TES_P2P_000B WorkAround:
-+ ///w, when inactivity count of a peer device is zero,
-+ ///w, which will reset while receiving a peer device frame,
-+ ///w, firmware will disconnect with it.
-+ ///w, due to some reason, such as scan/phy error, we miss these frame.
-+ ///w, then we can't keep connection with peer device.
-+ ///w, we set the min_inactivity value to large as WorkAround.
-+ //min_inactivity be modified to 20, yangfh.
-+ struct wsm_inactivity inactivity = {
-+ .min_inactivity = 20,
-+ .max_inactivity = 10,
-+ };
-+#else
-+ struct wsm_inactivity inactivity = {
-+ .min_inactivity = 9,
-+ .max_inactivity = 1,
-+ };
-+#endif
-+
-+ ap_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+
-+ if (priv->if_id)
-+ start.mode |= WSM_FLAG_MAC_INSTANCE_1;
-+ else
-+ start.mode &= ~WSM_FLAG_MAC_INSTANCE_1;
-+
-+ hw_priv->connected_sta_cnt = 0;
-+
-+#ifndef HIDDEN_SSID
-+ /* Get SSID */
-+ skb = ieee80211_beacon_get(priv->hw, priv->vif);
-+ if (WARN_ON(!skb)) {
-+ ap_printk(XRADIO_DBG_ERROR,"%s, ieee80211_beacon_get failed\n", __func__);
-+ return -ENOMEM;
-+ }
-+
-+ offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
-+ ssidie = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, skb->len - offset);
-+
-+ memset(priv->ssid, 0, sizeof(priv->ssid));
-+ if (ssidie) {
-+ priv->ssid_length = ssidie[1];
-+ if (WARN_ON(priv->ssid_length > sizeof(priv->ssid)))
-+ priv->ssid_length = sizeof(priv->ssid);
-+ memcpy(priv->ssid, &ssidie[2], priv->ssid_length);
-+ } else {
-+ priv->ssid_length = 0;
-+ }
-+ dev_kfree_skb(skb);
-+#endif
-+
-+ priv->beacon_int = conf->beacon_int;
-+ priv->join_dtim_period = conf->dtim_period;
-+ memset(&priv->last_tim[0], 0, sizeof(priv->last_tim)); //yangfh
-+
-+ start.ssidLength = priv->ssid_length;
-+ memcpy(&start.ssid[0], priv->ssid, start.ssidLength);
-+
-+ memset(&priv->link_id_db, 0, sizeof(priv->link_id_db));
-+
-+ ap_printk(XRADIO_DBG_NIY, "[AP] ch: %d(%d), bcn: %d(%d),"
-+ "bss_rate: 0x%.8X, ssid: %.*s.\n",
-+ start.channelNumber, start.band,
-+ start.beaconInterval, start.DTIMPeriod,
-+ start.basicRateSet, start.ssidLength, start.ssid);
-+ ret = WARN_ON(wsm_start(hw_priv, &start, priv->if_id));
-+
-+ if (!ret && priv->vif->p2p) {
-+ ap_printk(XRADIO_DBG_NIY,"[AP] Setting p2p powersave configuration.\n");
-+ WARN_ON(wsm_set_p2p_ps_modeinfo(hw_priv,
-+ &priv->p2p_ps_modeinfo, priv->if_id));
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //xradio_notify_noa(priv, XRADIO_NOA_NOTIFICATION_DELAY);
-+#endif
-+ }
-+
-+ /*Set Inactivity time*/
-+ if(!(strstr(&start.ssid[0], "6.1.12"))) {
-+ wsm_set_inactivity(hw_priv, &inactivity, priv->if_id);
-+ }
-+ if (!ret) {
-+#ifndef AP_AGGREGATE_FW_FIX
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
-+ XRADIO_RX_BLOCK_ACK_DISABLED_FOR_ALL_TID, priv->if_id));
-+#else
-+ if ((priv->if_id ==1) && !hw_priv->is_go_thru_go_neg)
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID, //modified for WFD by yangfh
-+ XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID, priv->if_id));
-+ else
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
-+ XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID, priv->if_id));
-+#endif
-+ priv->join_status = XRADIO_JOIN_STATUS_AP;
-+ /* xradio_update_filtering(priv); */
-+ }
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ ap_printk(XRADIO_DBG_WARN, "vif%d, AP/GO mode THROTTLE=%d\n", priv->if_id,
-+ priv->if_id==0?hw_priv->vif0_throttle:hw_priv->vif1_throttle);
-+ return ret;
-+}
-+
-+static int xradio_update_beaconing(struct xradio_vif *priv)
-+{
-+ struct ieee80211_bss_conf *conf = &priv->vif->bss_conf;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_reset reset = {
-+ .link_id = 0,
-+ .reset_statistics = true,
-+ };
-+ ap_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+
-+ if (priv->mode == NL80211_IFTYPE_AP) {
-+ /* TODO: check if changed channel, band */
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP ||
-+ priv->beacon_int != conf->beacon_int) {
-+ ap_printk(XRADIO_DBG_WARN, "ap restarting!\n");
-+ wsm_lock_tx(hw_priv);
-+ if (priv->join_status != XRADIO_JOIN_STATUS_PASSIVE)
-+ WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+ WARN_ON(xradio_start_ap(priv));
-+ wsm_unlock_tx(hw_priv);
-+ } else
-+ ap_printk(XRADIO_DBG_NIY, "ap started join_status: %d\n", priv->join_status);
-+ }
-+ return 0;
-+}
-+
-+int xradio_find_link_id(struct xradio_vif *priv, const u8 *mac)
-+{
-+ int i, ret = 0;
-+ spin_lock_bh(&priv->ps_state_lock);
-+ for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
-+ if (!memcmp(mac, priv->link_id_db[i].mac, ETH_ALEN) &&
-+ priv->link_id_db[i].status) {
-+ priv->link_id_db[i].timestamp = jiffies;
-+ ret = i + 1;
-+ break;
-+ }
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ return ret;
-+}
-+
-+int xradio_alloc_link_id(struct xradio_vif *priv, const u8 *mac)
-+{
-+ int i, ret = 0;
-+ unsigned long max_inactivity = 0;
-+ unsigned long now = jiffies;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
-+ if (!priv->link_id_db[i].status) {
-+ ret = i + 1;
-+ break;
-+ } else if (priv->link_id_db[i].status != XRADIO_LINK_HARD &&
-+ !hw_priv->tx_queue_stats.link_map_cache[i + 1]) {
-+ unsigned long inactivity = now - priv->link_id_db[i].timestamp;
-+ if (inactivity < max_inactivity)
-+ continue;
-+ max_inactivity = inactivity;
-+ ret = i + 1;
-+ }
-+ }
-+ if (ret) {
-+ struct xradio_link_entry *entry = &priv->link_id_db[ret - 1];
-+ ap_printk(XRADIO_DBG_NIY, "STA added, link_id: %d\n", ret);
-+ entry->status = XRADIO_LINK_RESERVE;
-+ memcpy(&entry->mac, mac, ETH_ALEN);
-+ memset(&entry->buffered, 0, XRADIO_MAX_TID);
-+ skb_queue_head_init(&entry->rx_queue);
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->link_id_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ } else {
-+ ap_printk(XRADIO_DBG_WARN, "Early: no more link IDs available.\n");
-+ }
-+
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ return ret;
-+}
-+
-+void xradio_link_id_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv = container_of(work, struct xradio_vif, link_id_work);
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+ wsm_flush_tx(hw_priv);
-+ xradio_link_id_gc_work(&priv->link_id_gc_work.work);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_link_id_gc_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, link_id_gc_work.work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_map_link map_link = {
-+ .link_id = 0,
-+ };
-+ unsigned long now = jiffies;
-+ unsigned long next_gc = -1;
-+ long ttl;
-+ bool need_reset;
-+ u32 mask;
-+ int i;
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP)
-+ return;
-+
-+ wsm_lock_tx(hw_priv);
-+ spin_lock_bh(&priv->ps_state_lock);
-+ for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
-+ need_reset = false;
-+ mask = BIT(i + 1);
-+ if (priv->link_id_db[i].status == XRADIO_LINK_RESERVE ||
-+ (priv->link_id_db[i].status == XRADIO_LINK_HARD &&
-+ !(priv->link_id_map & mask))) {
-+ if (priv->link_id_map & mask) {
-+ priv->sta_asleep_mask &= ~mask;
-+ priv->pspoll_mask &= ~mask;
-+ need_reset = true;
-+ }
-+ priv->link_id_map |= mask;
-+ if (priv->link_id_db[i].status != XRADIO_LINK_HARD)
-+ priv->link_id_db[i].status = XRADIO_LINK_SOFT;
-+ memcpy(map_link.mac_addr, priv->link_id_db[i].mac, ETH_ALEN);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ if (need_reset) {
-+ WARN_ON(xrwl_unmap_link(priv, i + 1));
-+ }
-+ map_link.link_id = i + 1;
-+ WARN_ON(wsm_map_link(hw_priv, &map_link, priv->if_id));
-+ next_gc = min(next_gc, XRADIO_LINK_ID_GC_TIMEOUT);
-+ spin_lock_bh(&priv->ps_state_lock);
-+ } else if (priv->link_id_db[i].status == XRADIO_LINK_SOFT) {
-+ ttl = priv->link_id_db[i].timestamp - now + XRADIO_LINK_ID_GC_TIMEOUT;
-+ if (ttl <= 0) {
-+ need_reset = true;
-+ priv->link_id_db[i].status = XRADIO_LINK_OFF;
-+ priv->link_id_map &= ~mask;
-+ priv->sta_asleep_mask &= ~mask;
-+ priv->pspoll_mask &= ~mask;
-+ memset(map_link.mac_addr, 0, ETH_ALEN);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ WARN_ON(xrwl_unmap_link(priv, i + 1));
-+ spin_lock_bh(&priv->ps_state_lock);
-+ } else {
-+ next_gc = min_t(unsigned long, next_gc, ttl);
-+ }
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ } else if (priv->link_id_db[i].status == XRADIO_LINK_RESET ||
-+ priv->link_id_db[i].status == XRADIO_LINK_RESET_REMAP) {
-+ int status = priv->link_id_db[i].status;
-+ priv->link_id_db[i].status = XRADIO_LINK_OFF;
-+ priv->link_id_db[i].timestamp = now;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ WARN_ON(xrwl_unmap_link(priv, i + 1));
-+ if (status == XRADIO_LINK_RESET_REMAP) {
-+ memcpy(map_link.mac_addr, priv->link_id_db[i].mac, ETH_ALEN);
-+ map_link.link_id = i + 1;
-+ WARN_ON(wsm_map_link(hw_priv, &map_link, priv->if_id));
-+ next_gc = min(next_gc, XRADIO_LINK_ID_GC_TIMEOUT);
-+ priv->link_id_db[i].status = priv->link_id_db[i].prev_status;
-+ }
-+ spin_lock_bh(&priv->ps_state_lock);
-+#endif
-+ }
-+ if (need_reset) {
-+ skb_queue_purge(&priv->link_id_db[i].rx_queue);
-+ ap_printk(XRADIO_DBG_NIY, "STA removed, link_id: %d\n", i + 1);
-+ }
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ if (next_gc != -1)
-+ queue_delayed_work(hw_priv->workqueue, &priv->link_id_gc_work, next_gc);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+#if 0
-+void xradio_notify_noa(struct xradio_vif *priv, int delay)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct cfg80211_p2p_ps p2p_ps = {0};
-+ struct wsm_p2p_ps_modeinfo *modeinfo;
-+ modeinfo = &priv->p2p_ps_modeinfo;
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP)
-+ return;
-+
-+ if (delay)
-+ msleep(delay);
-+
-+ if (!WARN_ON(wsm_get_p2p_ps_modeinfo(hw_priv, modeinfo))) {
-+#if defined(CONFIG_XRADIO_DEBUG)
-+ print_hex_dump_bytes("[AP] p2p_get_ps_modeinfo: ", DUMP_PREFIX_NONE,
-+ (u8 *)modeinfo, sizeof(*modeinfo));
-+#endif /* CONFIG_XRADIO_DEBUG */
-+ p2p_ps.opp_ps = !!(modeinfo->oppPsCTWindow & BIT(7));
-+ p2p_ps.ctwindow = modeinfo->oppPsCTWindow & (~BIT(7));
-+ p2p_ps.count = modeinfo->count;
-+ p2p_ps.start = __le32_to_cpu(modeinfo->startTime);
-+ p2p_ps.duration = __le32_to_cpu(modeinfo->duration);
-+ p2p_ps.interval = __le32_to_cpu(modeinfo->interval);
-+ p2p_ps.index = modeinfo->reserved;
-+
-+ ieee80211_p2p_noa_notify(priv->vif, &p2p_ps, GFP_KERNEL);
-+ }
-+}
-+#endif
-+#endif
-+int xrwl_unmap_link(struct xradio_vif *priv, int link_id)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int ret = 0;
-+
-+ if (is_hardware_xradio(hw_priv)) {
-+ struct wsm_map_link maplink = {
-+ .link_id = link_id,
-+ .unmap = true,
-+ };
-+ if (link_id)
-+ memcpy(&maplink.mac_addr[0], priv->link_id_db[link_id - 1].mac, ETH_ALEN);
-+ return wsm_map_link(hw_priv, &maplink, priv->if_id);
-+ } else {
-+ struct wsm_reset reset = {
-+ .link_id = link_id,
-+ .reset_statistics = true,
-+ };
-+ ret = wsm_reset(hw_priv, &reset, priv->if_id);
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ return ret;
-+ }
-+}
-+#ifdef AP_HT_CAP_UPDATE
-+void xradio_ht_oper_update_work(struct work_struct *work)
-+{
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+ u8 *ht_oper, *ies;
-+ u32 ies_len;
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, ht_oper_update_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_update_ie update_ie = {
-+ .what = WSM_UPDATE_IE_BEACON,
-+ .count = 1,
-+ };
-+
-+ skb = ieee80211_beacon_get(priv->hw, priv->vif);
-+ if (WARN_ON(!skb))
-+ return;
-+
-+ mgmt = (void *)skb->data;
-+ ies = mgmt->u.beacon.variable;
-+ ies_len = skb->len - (u32)(ies - (u8 *)mgmt);
-+ ht_oper= (u8 *)cfg80211_find_ie( WLAN_EID_HT_OPERATION, ies, ies_len);
-+ if(ht_oper && priv->ht_oper == HT_INFO_MASK) {
-+ ht_oper[HT_INFO_OFFSET] |= 0x11;
-+ update_ie.ies = ht_oper;
-+ update_ie.length = HT_INFO_IE_LEN;
-+ WARN_ON(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
-+ }
-+ dev_kfree_skb(skb);
-+}
-+#endif
-diff --git a/drivers/net/wireless/xradio/ap.h b/drivers/net/wireless/xradio/ap.h
-new file mode 100644
-index 0000000..9d55fb8
---- /dev/null
-+++ b/drivers/net/wireless/xradio/ap.h
-@@ -0,0 +1,63 @@
-+/*
-+ * STA and AP APIs for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef AP_H_INCLUDED
-+#define AP_H_INCLUDED
-+
-+#define XRADIO_NOA_NOTIFICATION_DELAY 10
-+
-+#ifdef AP_HT_CAP_UPDATE
-+#define HT_INFO_OFFSET 4
-+#define HT_INFO_MASK 0x0011
-+#define HT_INFO_IE_LEN 22
-+#endif
-+
-+int xradio_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
-+ bool set);
-+int xradio_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta);
-+int xradio_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta);
-+void xradio_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
-+ enum sta_notify_cmd notify_cmd,
-+ struct ieee80211_sta *sta);
-+void xradio_bss_info_changed(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_bss_conf *info,
-+ u32 changed);
-+int xradio_ampdu_action(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_ampdu_params *params);
-+/* enum ieee80211_ampdu_mlme_action action,
-+ struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-+ u8 buf_size);*/
-+
-+void xradio_suspend_resume(struct xradio_vif *priv,
-+ struct wsm_suspend_resume *arg);
-+void xradio_set_tim_work(struct work_struct *work);
-+void xradio_set_cts_work(struct work_struct *work);
-+void xradio_multicast_start_work(struct work_struct *work);
-+void xradio_multicast_stop_work(struct work_struct *work);
-+void xradio_mcast_timeout(struct timer_list *t);
-+int xradio_find_link_id(struct xradio_vif *priv, const u8 *mac);
-+int xradio_alloc_link_id(struct xradio_vif *priv, const u8 *mac);
-+void xradio_link_id_work(struct work_struct *work);
-+void xradio_link_id_gc_work(struct work_struct *work);
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+/*in linux3.4 mac,it does't have the noa pass*/
-+//void xradio_notify_noa(struct xradio_vif *priv, int delay);
-+#endif
-+int xrwl_unmap_link(struct xradio_vif *priv, int link_id);
-+#ifdef AP_HT_CAP_UPDATE
-+void xradio_ht_oper_update_work(struct work_struct *work);
-+#endif
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/bh.c b/drivers/net/wireless/xradio/bh.c
-new file mode 100644
-index 0000000..7666329
---- /dev/null
-+++ b/drivers/net/wireless/xradio/bh.c
-@@ -0,0 +1,836 @@
-+/*
-+ * Data Transmission thread implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "bh.h"
-+#include "hwio.h"
-+#include "wsm.h"
-+#include "sdio.h"
-+
-+/* TODO: Verify these numbers with WSM specification. */
-+#define DOWNLOAD_BLOCK_SIZE_WR (0x1000 - 4)
-+/* an SPI message cannot be bigger than (2"12-1)*2 bytes
-+ * "*2" to cvt to bytes */
-+#define MAX_SZ_RD_WR_BUFFERS (DOWNLOAD_BLOCK_SIZE_WR*2)
-+#define PIGGYBACK_CTRL_REG (2)
-+#define EFFECTIVE_BUF_SIZE (MAX_SZ_RD_WR_BUFFERS - PIGGYBACK_CTRL_REG)
-+
-+/* Suspend state privates */
-+enum xradio_bh_pm_state {
-+ XRADIO_BH_RESUMED = 0,
-+ XRADIO_BH_SUSPEND,
-+ XRADIO_BH_SUSPENDED,
-+ XRADIO_BH_RESUME,
-+};
-+typedef int (*xradio_wsm_handler)(struct xradio_common *hw_priv, u8 *data, size_t size);
-+
-+#ifdef MCAST_FWDING
-+int wsm_release_buffer_to_fw(struct xradio_vif *priv, int count);
-+#endif
-+static int xradio_bh(void *arg);
-+
-+int xradio_register_bh(struct xradio_common *hw_priv)
-+{
-+ int ret = 0;
-+
-+ atomic_set(&hw_priv->bh_tx, 0);
-+ atomic_set(&hw_priv->bh_term, 0);
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_RESUMED);
-+ hw_priv->buf_id_tx = 0;
-+ hw_priv->buf_id_rx = 0;
-+ init_waitqueue_head(&hw_priv->bh_wq);
-+ init_waitqueue_head(&hw_priv->bh_evt_wq);
-+
-+ hw_priv->bh_thread = kthread_run(&xradio_bh, hw_priv, XRADIO_BH_THREAD);
-+ if (IS_ERR(hw_priv->bh_thread)) {
-+ ret = PTR_ERR(hw_priv->bh_thread);
-+ hw_priv->bh_thread = NULL;
-+ }
-+
-+ return ret;
-+}
-+
-+void xradio_unregister_bh(struct xradio_common *hw_priv)
-+{
-+ struct task_struct *thread = hw_priv->bh_thread;
-+
-+ if (WARN_ON(!thread))
-+ return;
-+
-+ hw_priv->bh_thread = NULL;
-+ kthread_stop(thread);
-+#ifdef HAS_PUT_TASK_STRUCT
-+ put_task_struct(thread);
-+#endif
-+ dev_dbg(hw_priv->pdev, "Unregister success.\n");
-+}
-+
-+void xradio_irq_handler(struct xradio_common *hw_priv)
-+{
-+ xradio_bh_wakeup(hw_priv);
-+}
-+
-+void xradio_bh_wakeup(struct xradio_common *hw_priv)
-+{
-+ atomic_set(&hw_priv->bh_tx, 1);
-+ wake_up(&hw_priv->bh_wq);
-+}
-+
-+int xradio_bh_suspend(struct xradio_common *hw_priv)
-+{
-+#ifdef MCAST_FWDING
-+ int i =0;
-+ struct xradio_vif *priv = NULL;
-+#endif
-+
-+ if (hw_priv->bh_error) {
-+ return -EINVAL;
-+ }
-+
-+#ifdef MCAST_FWDING
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ if ( (priv->multicast_filter.enable)
-+ && (priv->join_status == XRADIO_JOIN_STATUS_AP) ) {
-+ wsm_release_buffer_to_fw(priv,
-+ (hw_priv->wsm_caps.numInpChBufs - 1));
-+ break;
-+ }
-+ }
-+#endif
-+
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_SUSPEND);
-+ wake_up(&hw_priv->bh_wq);
-+ return wait_event_timeout(hw_priv->bh_evt_wq, (hw_priv->bh_error ||
-+ XRADIO_BH_SUSPENDED == atomic_read(&hw_priv->bh_suspend)),
-+ 1 * HZ)? 0 : -ETIMEDOUT;
-+}
-+
-+int xradio_bh_resume(struct xradio_common *hw_priv)
-+{
-+#ifdef MCAST_FWDING
-+ int ret;
-+ int i =0;
-+ struct xradio_vif *priv =NULL;
-+#endif
-+
-+
-+ if (hw_priv->bh_error) {
-+ return -EINVAL;
-+ }
-+
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_RESUME);
-+ wake_up(&hw_priv->bh_wq);
-+
-+#ifdef MCAST_FWDING
-+ ret = wait_event_timeout(hw_priv->bh_evt_wq, (hw_priv->bh_error ||
-+ XRADIO_BH_RESUMED == atomic_read(&hw_priv->bh_suspend))
-+ ,1 * HZ)? 0 : -ETIMEDOUT;
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ if ((priv->join_status == XRADIO_JOIN_STATUS_AP) &&
-+ (priv->multicast_filter.enable)) {
-+ u8 count = 0;
-+ WARN_ON(wsm_request_buffer_request(priv, &count));
-+ dev_dbg(hw_priv->pdev, "Reclaim Buff %d \n",count);
-+ break;
-+ }
-+ }
-+
-+ return ret;
-+#else
-+ return wait_event_timeout(hw_priv->bh_evt_wq,hw_priv->bh_error ||
-+ (XRADIO_BH_RESUMED == atomic_read(&hw_priv->bh_suspend)),
-+ 1 * HZ) ? 0 : -ETIMEDOUT;
-+#endif
-+
-+}
-+
-+static inline void wsm_alloc_tx_buffer(struct xradio_common *hw_priv)
-+{
-+ ++hw_priv->hw_bufs_used;
-+}
-+
-+int wsm_release_tx_buffer(struct xradio_common *hw_priv, int count)
-+{
-+ int ret = 0;
-+ int hw_bufs_used = hw_priv->hw_bufs_used;
-+
-+ hw_priv->hw_bufs_used -= count;
-+ if (WARN_ON(hw_priv->hw_bufs_used < 0)) {
-+ /* Tx data patch stops when all but one hw buffers are used.
-+ So, re-start tx path in case we find hw_bufs_used equals
-+ numInputChBufs - 1.
-+ */
-+ dev_err(hw_priv->pdev, "hw_bufs_used=%d, count=%d.\n",
-+ hw_priv->hw_bufs_used, count);
-+ ret = -1;
-+ } else if (hw_bufs_used >= (hw_priv->wsm_caps.numInpChBufs - 1))
-+ ret = 1;
-+ if (!hw_priv->hw_bufs_used)
-+ wake_up(&hw_priv->bh_evt_wq);
-+ return ret;
-+}
-+
-+int wsm_release_vif_tx_buffer(struct xradio_common *hw_priv, int if_id, int count)
-+{
-+ int ret = 0;
-+
-+ hw_priv->hw_bufs_used_vif[if_id] -= count;
-+ if (!hw_priv->hw_bufs_used_vif[if_id])
-+ wake_up(&hw_priv->bh_evt_wq);
-+
-+ if (WARN_ON(hw_priv->hw_bufs_used_vif[if_id] < 0))
-+ ret = -1;
-+ return ret;
-+}
-+#ifdef MCAST_FWDING
-+int wsm_release_buffer_to_fw(struct xradio_vif *priv, int count)
-+{
-+ int i;
-+ u8 flags;
-+ struct wsm_buf *buf;
-+ size_t buf_len;
-+ struct wsm_hdr *wsm;
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP) {
-+ return 0;
-+ }
-+ dev_dbg(hw_priv->pdev, "Rel buffer to FW %d, %d\n", count, hw_priv->hw_bufs_used);
-+
-+ for (i = 0; i < count; i++) {
-+ if ((hw_priv->hw_bufs_used + 1) < hw_priv->wsm_caps.numInpChBufs) {
-+ flags = i ? 0: 0x1;
-+
-+ wsm_alloc_tx_buffer(hw_priv);
-+ buf = &hw_priv->wsm_release_buf[i];
-+ buf_len = buf->data - buf->begin;
-+
-+ /* Add sequence number */
-+ wsm = (struct wsm_hdr *)buf->begin;
-+ BUG_ON(buf_len < sizeof(*wsm));
-+
-+ wsm->id &= __cpu_to_le32(~WSM_TX_SEQ(WSM_TX_SEQ_MAX));
-+ wsm->id |= cpu_to_le32(WSM_TX_SEQ(hw_priv->wsm_tx_seq));
-+
-+ dev_dbg(hw_priv->pdev, "REL %d\n", hw_priv->wsm_tx_seq);
-+ if (WARN_ON(xradio_data_write(hw_priv, buf->begin, buf_len))) {
-+ break;
-+ }
-+ hw_priv->buf_released = 1;
-+ hw_priv->wsm_tx_seq = (hw_priv->wsm_tx_seq + 1) & WSM_TX_SEQ_MAX;
-+ } else
-+ break;
-+ }
-+
-+ if (i == count) {
-+ return 0;
-+ }
-+
-+ /* Should not be here */
-+ dev_dbg(hw_priv->pdev, "Error, Less HW buf %d,%d.\n",
-+ hw_priv->hw_bufs_used, hw_priv->wsm_caps.numInpChBufs);
-+ WARN_ON(1);
-+ return -1;
-+}
-+#endif
-+
-+/* reserve a packet for the case dev_alloc_skb failed in bh.*/
-+int xradio_init_resv_skb(struct xradio_common *hw_priv)
-+{
-+ int len = (SDIO_BLOCK_SIZE<<2) + WSM_TX_EXTRA_HEADROOM + \
-+ 8 + 12; /* TKIP IV + ICV and MIC */
-+
-+ hw_priv->skb_reserved = dev_alloc_skb(len);
-+ if (hw_priv->skb_reserved) {
-+ hw_priv->skb_resv_len = len;
-+ } else {
-+ dev_warn(hw_priv->pdev, "xr_alloc_skb failed(%d)\n", len);
-+ }
-+ return 0;
-+}
-+
-+void xradio_deinit_resv_skb(struct xradio_common *hw_priv)
-+{
-+ if (hw_priv->skb_reserved) {
-+ dev_kfree_skb(hw_priv->skb_reserved);
-+ hw_priv->skb_reserved = NULL;
-+ hw_priv->skb_resv_len = 0;
-+ }
-+}
-+
-+int xradio_realloc_resv_skb(struct xradio_common *hw_priv,
-+ struct sk_buff *skb)
-+{
-+ if (!hw_priv->skb_reserved && hw_priv->skb_resv_len) {
-+ hw_priv->skb_reserved = dev_alloc_skb(hw_priv->skb_resv_len);
-+ if (!hw_priv->skb_reserved) {
-+ hw_priv->skb_reserved = skb;
-+ dev_warn(hw_priv->pdev, "xr_alloc_skb failed(%d)\n",
-+ hw_priv->skb_resv_len);
-+ return -1;
-+ }
-+ }
-+ return 0; /* realloc sbk success, deliver to upper.*/
-+}
-+
-+static inline struct sk_buff *xradio_get_resv_skb(struct xradio_common *hw_priv,
-+ size_t len)
-+{ struct sk_buff *skb = NULL;
-+ if (hw_priv->skb_reserved && len <= hw_priv->skb_resv_len) {
-+ skb = hw_priv->skb_reserved;
-+ hw_priv->skb_reserved = NULL;
-+ }
-+ return skb;
-+}
-+
-+static inline int xradio_put_resv_skb(struct xradio_common *hw_priv,
-+ struct sk_buff *skb)
-+{
-+ if (!hw_priv->skb_reserved && hw_priv->skb_resv_len) {
-+ hw_priv->skb_reserved = skb;
-+ return 0;
-+ }
-+ return 1; /* sbk not put to reserve*/
-+}
-+
-+static struct sk_buff *xradio_get_skb(struct xradio_common *hw_priv, size_t len)
-+{
-+ struct sk_buff *skb = NULL;
-+ size_t alloc_len = (len > SDIO_BLOCK_SIZE) ? len : SDIO_BLOCK_SIZE;
-+
-+ /* TKIP IV + TKIP ICV and MIC - Piggyback.*/
-+ alloc_len += WSM_TX_EXTRA_HEADROOM + 8 + 12- 2;
-+ if (len > SDIO_BLOCK_SIZE || !hw_priv->skb_cache) {
-+ skb = dev_alloc_skb(alloc_len);
-+ /* In AP mode RXed SKB can be looped back as a broadcast.
-+ * Here we reserve enough space for headers. */
-+ if (skb) {
-+ skb_reserve(skb, WSM_TX_EXTRA_HEADROOM + 8 /* TKIP IV */
-+ - WSM_RX_EXTRA_HEADROOM);
-+ } else {
-+ skb = xradio_get_resv_skb(hw_priv, alloc_len);
-+ if (skb) {
-+ dev_dbg(hw_priv->pdev, "get skb_reserved(%d)!\n", alloc_len);
-+ skb_reserve(skb, WSM_TX_EXTRA_HEADROOM + 8 /* TKIP IV */
-+ - WSM_RX_EXTRA_HEADROOM);
-+ } else {
-+ dev_dbg(hw_priv->pdev, "xr_alloc_skb failed(%d)!\n", alloc_len);
-+ }
-+ }
-+ } else {
-+ skb = hw_priv->skb_cache;
-+ hw_priv->skb_cache = NULL;
-+ }
-+ return skb;
-+}
-+
-+static void xradio_put_skb(struct xradio_common *hw_priv, struct sk_buff *skb)
-+{
-+ if (hw_priv->skb_cache)
-+ dev_kfree_skb(skb);
-+ else
-+ hw_priv->skb_cache = skb;
-+}
-+
-+static int xradio_bh_read_ctrl_reg(struct xradio_common *hw_priv,
-+ u16 *ctrl_reg)
-+{
-+ int ret;
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONTROL_REG_ID, ctrl_reg);
-+ if (ret) {
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONTROL_REG_ID, ctrl_reg);
-+ if (ret) {
-+ hw_priv->bh_error = 1;
-+ dev_err(hw_priv->pdev, "Failed to read control register.\n");
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+static int xradio_device_wakeup(struct xradio_common *hw_priv)
-+{
-+ u16 ctrl_reg;
-+ int ret, i=0;
-+
-+ /* To force the device to be always-on, the host sets WLAN_UP to 1 */
-+ ret = xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, HIF_CTRL_WUP_BIT);
-+ if (WARN_ON(ret))
-+ return ret;
-+
-+ ret = xradio_bh_read_ctrl_reg(hw_priv, &ctrl_reg);
-+ if (WARN_ON(ret))
-+ return ret;
-+
-+ /* If the device returns WLAN_RDY as 1, the device is active and will
-+ * remain active. */
-+ while (!(ctrl_reg & HIF_CTRL_RDY_BIT) && i < 500) {
-+ ret = xradio_bh_read_ctrl_reg(hw_priv, &ctrl_reg);
-+ msleep(1);
-+ i++;
-+ }
-+ if (unlikely(i >= 500)) {
-+ dev_err(hw_priv->pdev, "Device cannot wakeup.\n");
-+ return -1;
-+ } else if (unlikely(i >= 50))
-+ dev_warn(hw_priv->pdev, "Device wakeup time=%dms.\n", i);
-+ dev_dbg(hw_priv->pdev, "Device awake, t=%dms.\n", i);
-+ return 1;
-+}
-+
-+/* Must be called from BH thraed. */
-+void xradio_enable_powersave(struct xradio_vif *priv,
-+ bool enable)
-+{
-+ priv->powersave_enabled = enable;
-+}
-+
-+static void xradio_bh_rx_dump(struct device *dev, u8 *data, size_t len){
-+#ifdef DEBUG
-+ static const char *msgnames[0xffff] = {
-+ // 0x4?? is a sync response to a command
-+ [0x0404] = "tx confirm",
-+ [0x0406] = "mib confirm",
-+ [0x0407] = "scan started",
-+ [0x0409] = "configuration confirm",
-+ [0x040a] = "reset confirm",
-+ [0x040b] = "join confirm",
-+ [0x040c] = "key added",
-+ [0x040d] = "key removed",
-+ [0x0410] = "pm confirm",
-+ [0x0411] = "set bss params",
-+ [0x0412] = "tx queue params",
-+ [0x0413] = "edca confirm",
-+ [0x0417] = "start confirm",
-+ [0x041b] = "update ie confirm",
-+ [0x041c] = "map link confirm",
-+ // 0x8?? seem to be async responses or events
-+ [0x0801] = "firmware startup complete",
-+ [0x0804] = "rx",
-+ [0x0805] = "event",
-+ [0x0806] = "scan complete",
-+ [0x0810] = "set pm indication"
-+ };
-+
-+ u16 msgid, ifid;
-+ u16 *p = (u16 *)data;
-+ msgid = (*(p + 1)) & 0xC3F;
-+ ifid = (*(p + 1)) >> 6;
-+ ifid &= 0xF;
-+ const char *msgname = msgnames[msgid];
-+ if(msgid == 0x804 && ifid == 2){
-+ msgname = "scan result";
-+ }
-+
-+ dev_dbg(dev, "vif %d: sdio rx, msgid %s(0x%.4X) len %d\n",
-+ ifid, msgname, msgid, *p);
-+// print_hex_dump_bytes("<-- ", DUMP_PREFIX_NONE,
-+// data, min(len, (size_t) 64));
-+#endif
-+}
-+
-+#define READLEN(ctrl) ((ctrl & HIF_CTRL_NEXT_LEN_MASK) << 1) //read_len=ctrl_reg*2.
-+
-+static int xradio_bh_rx_availlen(struct xradio_common *hw_priv){
-+ u16 ctrl_reg = 0;
-+ if (xradio_bh_read_ctrl_reg(hw_priv, &ctrl_reg)) {
-+ return -EIO;
-+ }
-+ return READLEN(ctrl_reg);
-+}
-+
-+static int xradio_bh_rx(struct xradio_common *hw_priv, u16* nextlen) {
-+ size_t read_len = 0;
-+ struct sk_buff *skb_rx = NULL;
-+ struct wsm_hdr *wsm;
-+ size_t wsm_len;
-+ int wsm_id;
-+ u8 wsm_seq;
-+ size_t alloc_len;
-+ u8 *data;
-+ int ret;
-+
-+ read_len = *nextlen > 0 ? *nextlen : xradio_bh_rx_availlen(hw_priv);
-+ if(read_len <= 0)
-+ return read_len;
-+
-+ if (read_len < sizeof(struct wsm_hdr) || (read_len > EFFECTIVE_BUF_SIZE)) {
-+ dev_err(hw_priv->pdev, "Invalid read len: %d", read_len);
-+ return -1;
-+ }
-+
-+ /* Add SIZE of PIGGYBACK reg (CONTROL Reg)
-+ * to the NEXT Message length + 2 Bytes for SKB */
-+ read_len = read_len + 2;
-+
-+ alloc_len = sdio_align_len(hw_priv, read_len);
-+ /* Check if not exceeding XRADIO capabilities */
-+ if (WARN_ON_ONCE(alloc_len > EFFECTIVE_BUF_SIZE)) {
-+ dev_err(hw_priv->pdev, "Read aligned len: %d\n", alloc_len);
-+ }
-+
-+ /* Get skb buffer. */
-+ skb_rx = xradio_get_skb(hw_priv, alloc_len);
-+ if (!skb_rx) {
-+ dev_err(hw_priv->pdev, "xradio_get_skb failed.\n");
-+ return -ENOMEM;
-+ }
-+ skb_trim(skb_rx, 0);
-+ skb_put(skb_rx, read_len);
-+ data = skb_rx->data;
-+ if (!data) {
-+ dev_err(hw_priv->pdev, "skb data is NULL.\n");
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ /* Read data from device. */
-+ if (xradio_data_read(hw_priv, data, alloc_len)) {
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ /* the ctrl register is appened to the end of the wsm frame
-+ * so we can use this to avoid reading the control register
-+ * again for the next read .. but if this is invalid we'll
-+ * do an invalid read and the firmware will crash so this
-+ * probably needs some sort of validation */
-+ *nextlen = READLEN(__le16_to_cpu(((__le16 *) data)[(alloc_len >> 1) - 1]));
-+
-+ /* check wsm length. */
-+ wsm = (struct wsm_hdr *) data;
-+ wsm_len = __le32_to_cpu(wsm->len);
-+
-+ if (WARN_ON(wsm_len > read_len)) {
-+ dev_err(hw_priv->pdev, "wsm is bigger than data read, read %d but frame is %d\n",
-+ read_len, wsm_len);
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ /* dump rx data. */
-+ xradio_bh_rx_dump(hw_priv->pdev, data, wsm_len);
-+
-+ /* extract wsm id and seq. */
-+ wsm_id = __le32_to_cpu(wsm->id) & 0xFFF;
-+ wsm_seq = (__le32_to_cpu(wsm->id) >> 13) & 7;
-+ skb_trim(skb_rx, wsm_len);
-+
-+ /* process exceptions. */
-+ if (wsm_id == 0) {
-+ printk("wtf?\n");
-+ ret = 0;
-+ goto out;
-+ } else if (unlikely(wsm_id == 0x0800)) {
-+ dev_err(hw_priv->pdev, "firmware exception!\n");
-+ wsm_handle_exception(hw_priv, &data[sizeof(*wsm)],
-+ wsm_len - sizeof(*wsm));
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ hw_priv->wsm_rx_seq = (wsm_seq + 1) & 7;
-+
-+ /* Process tx frames confirm. */
-+ if (wsm_id & 0x0400) {
-+ if (wsm_release_tx_buffer(hw_priv, 1) < 0) {
-+ dev_err(hw_priv->pdev, "tx buffer < 0.\n");
-+ ret = -1;
-+ goto out;
-+ }
-+ }
-+
-+ /* WSM processing frames. */
-+ if (wsm_handle_rx(hw_priv, wsm_id, wsm, &skb_rx)) {
-+ dev_err(hw_priv->pdev, "wsm_handle_rx failed.\n");
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ ret = 1;
-+
-+out:
-+ /* Reclaim the SKB buffer */
-+ if (skb_rx) {
-+ if (xradio_put_resv_skb(hw_priv, skb_rx))
-+ xradio_put_skb(hw_priv, skb_rx);
-+ }
-+
-+ return ret;
-+}
-+
-+static void xradio_bh_tx_dump(struct device *dev, u8 *data, size_t len){
-+#ifdef DEBUG
-+ static const char *msgnames[0xffff] = {
-+ [0x0004] = "tx",
-+ [0x0006] = "MIB",
-+ [0x0007] = "start scan",
-+ [0x0009] = "configure",
-+ [0x000A] = "reset",
-+ [0x000B] = "join",
-+ [0x000C] = "add key",
-+ [0x000D] = "remove key",
-+ [0x0010] = "set pm",
-+ [0x0011] = "set bss params",
-+ [0x0012] = "set tx queue params",
-+ [0x0013] = "set edca",
-+ [0x0017] = "start",
-+ [0x001b] = "update ie",
-+ [0x001c] = "map link",
-+ };
-+ static const char *mibnames[0xffff] = {
-+ [0x0003] = "DOT11_SLOT_TIME",
-+ [0x1002] = "TEMPLATE_FRAME",
-+ [0x1003] = "RX_FILTER",
-+ [0x1004] = "BEACON_FILTER_TABLE",
-+ [0x1005] = "BEACON_FILTER_ENABLE",
-+ [0x1006] = "OPERATIONAL POWER MODE",
-+ [0x1007] = "BEACON_WAKEUP_PERIOD",
-+ [0x1009] = "RCPI_RSSI_THRESHOLD",
-+ [0x1010] = "SET_ASSOCIATION_MODE",
-+ [0x100e] = "BLOCK_ACK_POLICY",
-+ [0x100f] = "OVERRIDE_INTERNAL_TX_RATE",
-+ [0x1013] = "SET_UAPSD_INFORMATION",
-+ [0x1016] = "SET_TX_RATE_RETRY_POLICY",
-+ [0x1020] = "PROTECTED_MGMT_POLICY",
-+ [0x1021] = "SET_HT_PROTECTION",
-+ [0x1024] = "USE_MULTI_TX_CONF",
-+ [0x1025] = "KEEP_ALIVE_PERIOD",
-+ [0x1026] = "DISABLE_BSSID_FILTER",
-+ [0x1035] = "SET_INACTIVITY",
-+ };
-+
-+ u16 msgid, ifid, mib;
-+ u16 *p = (u16 *)data;
-+ msgid = (*(p + 1)) & 0x3F;
-+ ifid = (*(p + 1)) >> 6;
-+ ifid &= 0xF;
-+ mib = *(p + 2);
-+
-+ WARN_ON(msgnames[msgid] == NULL);
-+
-+ if (msgid == 0x0006) {
-+ dev_dbg(dev, "vif %d: sdio tx, msgid %s(0x%.4X) len %d MIB %s(0x%.4X)\n",
-+ ifid, msgnames[msgid], msgid,*p, mibnames[mib], mib);
-+ } else {
-+ dev_dbg(dev, "vif %d: sdio tx, msgid %s(0x%.4X) len %d\n", ifid, msgnames[msgid], msgid, *p);
-+ }
-+
-+// print_hex_dump_bytes("--> ", DUMP_PREFIX_NONE, data,
-+// min(len, (size_t) 64));
-+#endif
-+}
-+
-+static int xradio_bh_tx(struct xradio_common *hw_priv){
-+ int txavailable;
-+ int txburst;
-+ int vif_selected;
-+ struct wsm_hdr *wsm;
-+ size_t tx_len;
-+ int ret;
-+ u8 *data;
-+
-+ BUG_ON(hw_priv->hw_bufs_used > hw_priv->wsm_caps.numInpChBufs);
-+ txavailable = hw_priv->wsm_caps.numInpChBufs - hw_priv->hw_bufs_used;
-+ if (txavailable) {
-+ /* Wake up the devices */
-+ if (hw_priv->device_can_sleep) {
-+ ret = xradio_device_wakeup(hw_priv);
-+ if (WARN_ON(ret < 0)) {
-+ return -1;
-+ } else if (ret) {
-+ hw_priv->device_can_sleep = false;
-+ } else { /* Wait for "awake" interrupt */
-+ dev_dbg(hw_priv->pdev,
-+ "need to wait for device to wake before doing tx\n");
-+ return 0;
-+ }
-+ }
-+ /* Increase Tx buffer*/
-+ wsm_alloc_tx_buffer(hw_priv);
-+
-+ /* Get data to send and send it. */
-+ ret = wsm_get_tx(hw_priv, &data, &tx_len, &txburst, &vif_selected);
-+ if (ret <= 0) {
-+ wsm_release_tx_buffer(hw_priv, 1);
-+ if (WARN_ON(ret < 0)) {
-+ dev_err(hw_priv->pdev, "wsm_get_tx=%d.\n", ret);
-+ return -ENOMEM;
-+ } else {
-+ return 0;
-+ }
-+ } else {
-+ wsm = (struct wsm_hdr *) data;
-+ BUG_ON(tx_len < sizeof(*wsm));
-+ BUG_ON(__le32_to_cpu(wsm->len) != tx_len);
-+
-+ /* Align tx length and check it. */
-+ if (tx_len <= 8)
-+ tx_len = 16;
-+ tx_len = sdio_align_len(hw_priv, tx_len);
-+
-+ /* Check if not exceeding XRADIO capabilities */
-+ if (tx_len > EFFECTIVE_BUF_SIZE) {
-+ dev_warn(hw_priv->pdev, "Write aligned len: %d\n", tx_len);
-+ }
-+
-+ /* Make sequence number. */
-+ wsm->id &= __cpu_to_le32(~WSM_TX_SEQ(WSM_TX_SEQ_MAX));
-+ wsm->id |= cpu_to_le32(WSM_TX_SEQ(hw_priv->wsm_tx_seq));
-+
-+ /* Send the data to devices. */
-+ if (WARN_ON(xradio_data_write(hw_priv, data, tx_len))) {
-+ wsm_release_tx_buffer(hw_priv, 1);
-+ dev_err(hw_priv->pdev, "xradio_data_write failed\n");
-+ return -EIO;
-+ }
-+
-+ xradio_bh_tx_dump(hw_priv->pdev, data, tx_len);
-+
-+ /* Process after data have sent. */
-+ if (vif_selected != -1) {
-+ hw_priv->hw_bufs_used_vif[vif_selected]++;
-+ }
-+ wsm_txed(hw_priv, data);
-+ hw_priv->wsm_tx_seq = (hw_priv->wsm_tx_seq + 1) & WSM_TX_SEQ_MAX;
-+
-+ return 1;
-+ }
-+ } else
-+ return 0;
-+}
-+
-+static int xradio_bh_exchange(struct xradio_common *hw_priv) {
-+ int rxdone;
-+ int txdone;
-+ u16 nextlen = 0;
-+
-+ /* query stuck frames in firmware. */
-+ if (atomic_xchg(&hw_priv->query_cnt, 0)) {
-+ if (schedule_work(&hw_priv->query_work) <= 0)
-+ atomic_add(1, &hw_priv->query_cnt);
-+ }
-+
-+ /* keep doing tx and rx until they both stop or we are told
-+ * to terminate */
-+ do {
-+ txdone = xradio_bh_tx(hw_priv);
-+ if (txdone < 0) {
-+ break;
-+ }
-+ rxdone = xradio_bh_rx(hw_priv, &nextlen);
-+ if (rxdone < 0) {
-+ break;
-+ }
-+ } while ((txdone > 0 || rxdone > 0) && !kthread_should_stop());
-+ return 0;
-+}
-+
-+static int xradio_bh(void *arg)
-+{
-+ struct xradio_common *hw_priv = arg;
-+ int term, suspend;
-+ int wake = 0;
-+ long timeout;
-+ long status;
-+
-+ for (;;) {
-+ timeout = HZ / 30;
-+
-+ // wait for something to happen or a timeout
-+ status = wait_event_interruptible_timeout(hw_priv->bh_wq, ( {
-+ wake = atomic_xchg(&hw_priv->bh_tx, 0);
-+ term = kthread_should_stop();
-+ suspend = atomic_read(&hw_priv->bh_suspend);
-+ (wake || term || suspend);}), timeout);
-+
-+ if (wake) {
-+ if(xradio_bh_exchange(hw_priv) < 0){
-+ break;
-+ }
-+ } else if (term) {
-+ dev_dbg(hw_priv->pdev, "xradio_bh exit!\n");
-+ break;
-+ } else if (status < 0) {
-+ dev_err(hw_priv->pdev, "bh_error=%d, status=%ld\n",
-+ hw_priv->bh_error, status);
-+ break;
-+ } else if (!status) {
-+ /* check if there is data waiting but we missed the interrupt*/
-+ if (xradio_bh_rx_availlen(hw_priv) > 0) {
-+ dev_warn(hw_priv->pdev, "missed interrupt!\n");
-+ if(xradio_bh_exchange(hw_priv) < 0){
-+ break;
-+ }
-+ }
-+ /* There are some frames to be confirmed. */
-+ else if (hw_priv->hw_bufs_used) {
-+ long timeout = 0;
-+ bool pending = 0;
-+ dev_dbg(hw_priv->pdev, "Need confirm:%d!\n",
-+ hw_priv->hw_bufs_used);
-+ /* Check if frame transmission is timed out. */
-+ pending = xradio_query_txpkt_timeout(hw_priv, XRWL_ALL_IFS,
-+ hw_priv->pending_frame_id, &timeout);
-+ /* There are some frames confirm time out. */
-+ if (pending && timeout < 0) {
-+ dev_err(hw_priv->pdev, "query_txpkt_timeout:%ld!\n",
-+ timeout);
-+ break;
-+ }
-+ } //else if (!txpending){
-+ //if (hw_priv->powersave_enabled && !hw_priv->device_can_sleep && !atomic_read(&hw_priv->recent_scan)) {
-+ // /* Device is idle, we can go to sleep. */
-+ // dev_dbg(hw_priv->pdev, "Device idle(timeout), can sleep.\n");
-+ // WARN_ON(xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, 0));
-+ // hw_priv->device_can_sleep = true;
-+ //}
-+ //continue;
-+ //}
-+ } else if (suspend) {
-+ dev_dbg(hw_priv->pdev, "Host suspend request.\n");
-+ /* Check powersave setting again. */
-+ if (hw_priv->powersave_enabled) {
-+ dev_dbg(hw_priv->pdev,
-+ "Device idle(host suspend), can sleep.\n");
-+ WARN_ON(xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, 0));
-+ hw_priv->device_can_sleep = true;
-+ }
-+
-+ /* bh thread go to suspend. */
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_SUSPENDED);
-+ wake_up(&hw_priv->bh_evt_wq);
-+ status = wait_event_interruptible(hw_priv->bh_wq,
-+ XRADIO_BH_RESUME == atomic_read(&hw_priv->bh_suspend));
-+
-+ if (status < 0) {
-+ dev_err(hw_priv->pdev, "Failed to wait for resume: %ld.\n",
-+ status);
-+ break;
-+ }
-+ dev_dbg(hw_priv->pdev, "Host resume.\n");
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_RESUMED);
-+ wake_up(&hw_priv->bh_evt_wq);
-+ }
-+ } /* for (;;)*/
-+
-+ dev_err(hw_priv->pdev, "bh thread exiting\n");
-+
-+ return 0;
-+}
-diff --git a/drivers/net/wireless/xradio/bh.h b/drivers/net/wireless/xradio/bh.h
-new file mode 100644
-index 0000000..ca9187e
---- /dev/null
-+++ b/drivers/net/wireless/xradio/bh.h
-@@ -0,0 +1,36 @@
-+/*
-+ * Data Transmission thread for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_BH_H
-+#define XRADIO_BH_H
-+
-+#define XRADIO_BH_THREAD "xradio_bh"
-+
-+/* extern */ struct xradio_common;
-+
-+#define SDIO_BLOCK_SIZE (528)
-+
-+int xradio_register_bh(struct xradio_common *hw_priv);
-+void xradio_unregister_bh(struct xradio_common *hw_priv);
-+void xradio_irq_handler(struct xradio_common *hw_priv);
-+void xradio_bh_wakeup(struct xradio_common *hw_priv);
-+int xradio_bh_suspend(struct xradio_common *hw_priv);
-+int xradio_bh_resume(struct xradio_common *hw_priv);
-+/* Must be called from BH thread. */
-+void xradio_enable_powersave(struct xradio_vif *priv, bool enable);
-+int wsm_release_tx_buffer(struct xradio_common *hw_priv, int count);
-+int wsm_release_vif_tx_buffer(struct xradio_common *hw_priv, int if_id,
-+ int count);
-+int xradio_init_resv_skb(struct xradio_common *hw_priv);
-+void xradio_deinit_resv_skb(struct xradio_common *hw_priv);
-+int xradio_realloc_resv_skb(struct xradio_common *hw_priv,
-+ struct sk_buff *skb);
-+#endif /* XRADIO_BH_H */
-diff --git a/drivers/net/wireless/xradio/common.h b/drivers/net/wireless/xradio/common.h
-new file mode 100644
-index 0000000..1ce23de
---- /dev/null
-+++ b/drivers/net/wireless/xradio/common.h
-@@ -0,0 +1,101 @@
-+/*
-+ * Common interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_COMMON_H
-+#define XRADIO_COMMON_H
-+
-+/*******************************************************
-+ interfaces for parse frame protocol info.
-+********************************************************/
-+#define LLC_LEN 8
-+#define LLC_TYPE_OFF 6 //Ether type offset
-+#define IP_PROTO_OFF 9 //protocol offset
-+#define IP_S_ADD_OFF 12
-+#define IP_D_ADD_OFF 16
-+#define UDP_LEN 8
-+//DHCP
-+#define DHCP_BOOTP_C 68
-+#define DHCP_BOOTP_S 67
-+#define UDP_BOOTP_LEN 236 //exclude "Options:64"
-+#define BOOTP_OPS_LEN 64
-+#define DHCP_MAGIC 0x63825363
-+#define DHCP_DISCOVER 0x01
-+#define DHCP_OFFER 0x02
-+#define DHCP_REQUEST 0x03
-+#define DHCP_DECLINE 0x04
-+#define DHCP_ACK 0x05
-+#define DHCP_NACK 0x06
-+#define DHCP_RELEASE 0x07
-+
-+//LLC layer.
-+static inline bool is_SNAP(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data) == 0xAAAA && llc_data[2] == 0x03); //0xAA, 0xAA, 0x03.
-+}
-+
-+static inline bool is_STP(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data) == 0xAAAA && llc_data[2] == 0x03); //0x42, 0x42, 0x03.
-+}
-+
-+//IP/IPV6/ARP layer...
-+static inline bool is_ip(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data+LLC_TYPE_OFF) == cpu_to_be16(ETH_P_IP)); //0x0800
-+}
-+static inline bool is_ipv6(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data+LLC_TYPE_OFF) == cpu_to_be16(ETH_P_IPV6)); //0x08dd
-+}
-+static inline bool is_arp(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data+LLC_TYPE_OFF) == cpu_to_be16(ETH_P_ARP)); //0x0806
-+}
-+static inline bool is_8021x(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data+LLC_TYPE_OFF) == cpu_to_be16(ETH_P_PAE)); //0x888E
-+}
-+
-+//TCP/UDP layer...
-+static inline bool is_tcp(u8* llc_data)
-+{
-+ return (bool)(llc_data[LLC_LEN+IP_PROTO_OFF] == IPPROTO_TCP); //
-+}
-+
-+static inline bool is_udp(u8* llc_data)
-+{
-+ return (bool)(llc_data[LLC_LEN+IP_PROTO_OFF] == IPPROTO_UDP); //
-+}
-+
-+static inline bool is_icmp(u8* llc_data)
-+{
-+ return (bool)(llc_data[LLC_LEN+IP_PROTO_OFF] == IPPROTO_ICMP); //
-+}
-+
-+static inline bool is_igmp(u8* llc_data)
-+{
-+ return (bool)(llc_data[LLC_LEN+IP_PROTO_OFF] == IPPROTO_IGMP); //
-+}
-+
-+static inline bool is_dhcp(u8* llc_data)
-+{
-+ u8* ip_hdr = llc_data+LLC_LEN;
-+ if(!is_ip(llc_data))
-+ return (bool)0;
-+ if(ip_hdr[IP_PROTO_OFF] == IPPROTO_UDP) {
-+ u8* udp_hdr = ip_hdr+((ip_hdr[0]&0xf)<<2); //ihl:words
-+ return (bool)((((udp_hdr[0]<<8)|udp_hdr[1]) == DHCP_BOOTP_C) || //DHCP client
-+ (((udp_hdr[0]<<8)|udp_hdr[1]) == DHCP_BOOTP_S)); //DHCP server
-+ }
-+ return (bool)0;
-+}
-+
-+#endif //XRADIO_COMMON_H
-diff --git a/drivers/net/wireless/xradio/debug.h b/drivers/net/wireless/xradio/debug.h
-new file mode 100644
-index 0000000..30a59f3
---- /dev/null
-+++ b/drivers/net/wireless/xradio/debug.h
-@@ -0,0 +1,22 @@
-+/*
-+ * DebugFS code for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef XRADIO_DEBUG_H_INCLUDED
-+#define XRADIO_DEBUG_H_INCLUDED
-+
-+#define xradio_dbg(level, ...)
-+#define txrx_printk(level, ...)
-+#define wsm_printk(level, ...)
-+#define sta_printk(level, ...)
-+#define scan_printk(level, ...)
-+#define ap_printk(level, ...)
-+#define pm_printk(level, ...)
-+
-+#endif /* XRADIO_DEBUG_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/fwio.c b/drivers/net/wireless/xradio/fwio.c
-new file mode 100644
-index 0000000..cfb45eb
---- /dev/null
-+++ b/drivers/net/wireless/xradio/fwio.c
-@@ -0,0 +1,560 @@
-+/*
-+ * Firmware I/O implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "fwio.h"
-+#include "hwio.h"
-+#include "bh.h"
-+#include "sdio.h"
-+
-+/* Macroses are local. */
-+#define APB_WRITE(reg, val) \
-+ do { \
-+ ret = xradio_apb_write_32(hw_priv, APB_ADDR(reg), (val)); \
-+ if (ret < 0) { \
-+ dev_err(hw_priv->pdev, \
-+ "%s: can't write %s at line %d.\n", \
-+ __func__, #reg, __LINE__); \
-+ goto error; \
-+ } \
-+ } while (0)
-+#define APB_READ(reg, val) \
-+ do { \
-+ ret = xradio_apb_read_32(hw_priv, APB_ADDR(reg), &(val)); \
-+ if (ret < 0) { \
-+ dev_err(hw_priv->pdev, \
-+ "%s: can't read %s at line %d.\n", \
-+ __func__, #reg, __LINE__); \
-+ goto error; \
-+ } \
-+ } while (0)
-+#define REG_WRITE(reg, val) \
-+ do { \
-+ ret = xradio_reg_write_32(hw_priv, (reg), (val)); \
-+ if (ret < 0) { \
-+ dev_err(hw_priv->pdev, \
-+ "%s: can't write %s at line %d.\n", \
-+ __func__, #reg, __LINE__); \
-+ goto error; \
-+ } \
-+ } while (0)
-+#define REG_READ(reg, val) \
-+ do { \
-+ ret = xradio_reg_read_32(hw_priv, (reg), &(val)); \
-+ if (ret < 0) { \
-+ dev_err(hw_priv->pdev, \
-+ "%s: can't read %s at line %d.\n", \
-+ __func__, #reg, __LINE__); \
-+ goto error; \
-+ } \
-+ } while (0)
-+
-+
-+static int xradio_get_hw_type(u32 config_reg_val, int *major_revision)
-+{
-+ int hw_type = -1;
-+ u32 hif_type = (config_reg_val >> 24) & 0x4;
-+ //u32 hif_vers = (config_reg_val >> 31) & 0x1;
-+
-+ /* Check if we have XRADIO*/
-+ if (hif_type == 0x4) {
-+ *major_revision = 0x4;
-+ hw_type = HIF_HW_TYPE_XRADIO;
-+ } else {
-+ //hw type unknown.
-+ *major_revision = 0x0;
-+ }
-+ return hw_type;
-+}
-+
-+/*
-+ * This function is called to Parse the SDD file
-+ * to extract some informations
-+ */
-+static int xradio_parse_sdd(struct xradio_common *hw_priv, u32 *dpll)
-+{
-+ int ret = 0;
-+ const char *sdd_path = NULL;
-+ struct xradio_sdd *pElement = NULL;
-+ int parsedLength = 0;
-+
-+ BUG_ON(hw_priv->sdd != NULL);
-+
-+ /* select and load sdd file depend on hardware version. */
-+ switch (hw_priv->hw_revision) {
-+ case XR819_HW_REV0:
-+ sdd_path = XR819_SDD_FILE;
-+ break;
-+ default:
-+ dev_dbg(hw_priv->pdev, "unknown hardware version.\n");
-+ return ret;
-+ }
-+
-+ ret = request_firmware(&hw_priv->sdd, sdd_path, hw_priv->pdev);
-+ if (unlikely(ret)) {
-+ dev_dbg(hw_priv->pdev, "can't load sdd file %s.\n",
-+ sdd_path);
-+ return ret;
-+ }
-+
-+ //parse SDD config.
-+ hw_priv->is_BT_Present = false;
-+ pElement = (struct xradio_sdd *)hw_priv->sdd->data;
-+ parsedLength += (FIELD_OFFSET(struct xradio_sdd, data) + pElement->length);
-+ pElement = FIND_NEXT_ELT(pElement);
-+
-+ while (parsedLength < hw_priv->sdd->size) {
-+ switch (pElement->id) {
-+ case SDD_PTA_CFG_ELT_ID:
-+ hw_priv->conf_listen_interval = (*((u16 *)pElement->data+1) >> 7) & 0x1F;
-+ hw_priv->is_BT_Present = true;
-+ xradio_dbg(XRADIO_DBG_NIY, "PTA element found.Listen Interval %d\n",
-+ hw_priv->conf_listen_interval);
-+ break;
-+ case SDD_REFERENCE_FREQUENCY_ELT_ID:
-+ switch(*((uint16_t*)pElement->data)) {
-+ case 0x32C8:
-+ *dpll = 0x1D89D241;
-+ break;
-+ case 0x3E80:
-+ *dpll = 0x1E1;
-+ break;
-+ case 0x41A0:
-+ *dpll = 0x124931C1;
-+ break;
-+ case 0x4B00:
-+ *dpll = 0x191;
-+ break;
-+ case 0x5DC0:
-+ *dpll = 0x141;
-+ break;
-+ case 0x6590:
-+ *dpll = 0x0EC4F121;
-+ break;
-+ case 0x8340:
-+ *dpll = 0x92490E1;
-+ break;
-+ case 0x9600:
-+ *dpll = 0x100010C1;
-+ break;
-+ case 0x9C40:
-+ *dpll = 0xC1;
-+ break;
-+ case 0xBB80:
-+ *dpll = 0xA1;
-+ break;
-+ case 0xCB20:
-+ *dpll = 0x7627091;
-+ break;
-+ default:
-+ *dpll = DPLL_INIT_VAL_XRADIO;
-+ xradio_dbg(XRADIO_DBG_WARN, "Unknown Reference clock frequency."
-+ "Use default DPLL value=0x%08x.", DPLL_INIT_VAL_XRADIO);
-+ break;
-+ }
-+ default:
-+ break;
-+ }
-+ parsedLength += (FIELD_OFFSET(struct xradio_sdd, data) + pElement->length);
-+ pElement = FIND_NEXT_ELT(pElement);
-+ }
-+
-+ dev_dbg(hw_priv->pdev, "sdd size=%d parse len=%d.\n",
-+ hw_priv->sdd->size, parsedLength);
-+
-+ //
-+ if (hw_priv->is_BT_Present == false) {
-+ hw_priv->conf_listen_interval = 0;
-+ xradio_dbg(XRADIO_DBG_NIY, "PTA element NOT found.\n");
-+ }
-+ return ret;
-+}
-+
-+static int xradio_firmware(struct xradio_common *hw_priv)
-+{
-+ int ret, block, num_blocks;
-+ unsigned i;
-+ u32 val32;
-+ u32 put = 0, get = 0;
-+ u8 *buf = NULL;
-+ const char *fw_path;
-+ const struct firmware *firmware = NULL;
-+
-+ switch (hw_priv->hw_revision) {
-+ case XR819_HW_REV0:
-+ fw_path = XR819_FIRMWARE;
-+ break;
-+ default:
-+ dev_dbg(hw_priv->pdev, "invalid silicon revision %d.\n",
-+ hw_priv->hw_revision);
-+ return -EINVAL;
-+ }
-+ /* Initialize common registers */
-+ APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, DOWNLOAD_ARE_YOU_HERE);
-+ APB_WRITE(DOWNLOAD_PUT_REG, 0);
-+ APB_WRITE(DOWNLOAD_GET_REG, 0);
-+ APB_WRITE(DOWNLOAD_STATUS_REG, DOWNLOAD_PENDING);
-+ APB_WRITE(DOWNLOAD_FLAGS_REG, 0);
-+
-+ /* Release CPU from RESET */
-+ REG_READ(HIF_CONFIG_REG_ID, val32);
-+ val32 &= ~HIF_CONFIG_CPU_RESET_BIT;
-+ REG_WRITE(HIF_CONFIG_REG_ID, val32);
-+
-+ /* Enable Clock */
-+ val32 &= ~HIF_CONFIG_CPU_CLK_DIS_BIT;
-+ REG_WRITE(HIF_CONFIG_REG_ID, val32);
-+
-+ /* Load a firmware file */
-+ ret = request_firmware(&firmware, fw_path, hw_priv->pdev);
-+ if (ret) {
-+ dev_dbg(hw_priv->pdev, "can't load firmware file %s.\n",
-+ fw_path);
-+ goto error;
-+ }
-+ BUG_ON(!firmware->data);
-+
-+ buf = kmalloc(DOWNLOAD_BLOCK_SIZE, GFP_KERNEL);
-+ if (!buf) {
-+ dev_dbg(hw_priv->pdev, "can't allocate firmware buffer.\n");
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ /* Check if the bootloader is ready */
-+ for (i = 0; i < 100; i++/*= 1 + i / 2*/) {
-+ APB_READ(DOWNLOAD_IMAGE_SIZE_REG, val32);
-+ if (val32 == DOWNLOAD_I_AM_HERE)
-+ break;
-+ mdelay(10);
-+ } /* End of for loop */
-+ if (val32 != DOWNLOAD_I_AM_HERE) {
-+ dev_dbg(hw_priv->pdev, "bootloader is not ready.\n");
-+ ret = -ETIMEDOUT;
-+ goto error;
-+ }
-+
-+ /* Calculcate number of download blocks */
-+ num_blocks = (firmware->size - 1) / DOWNLOAD_BLOCK_SIZE + 1;
-+
-+ /* Updating the length in Download Ctrl Area */
-+ val32 = firmware->size; /* Explicit cast from size_t to u32 */
-+ APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, val32);
-+
-+ /* Firmware downloading loop */
-+ for (block = 0; block < num_blocks ; block++) {
-+ size_t tx_size;
-+ size_t block_size;
-+
-+ /* check the download status */
-+ APB_READ(DOWNLOAD_STATUS_REG, val32);
-+ if (val32 != DOWNLOAD_PENDING) {
-+ dev_dbg(hw_priv->pdev, "bootloader reported error %d.\n",
-+ val32);
-+ ret = -EIO;
-+ goto error;
-+ }
-+
-+ /* loop until put - get <= 24K */
-+ for (i = 0; i < 100; i++) {
-+ APB_READ(DOWNLOAD_GET_REG, get);
-+ if ((put - get) <= (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE))
-+ break;
-+ mdelay(i);
-+ }
-+
-+ if ((put - get) > (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) {
-+ dev_dbg(hw_priv->pdev, "Timeout waiting for FIFO.\n");
-+ ret = -ETIMEDOUT;
-+ goto error;
-+ }
-+
-+ /* calculate the block size */
-+ tx_size = block_size = min((size_t)(firmware->size - put), (size_t)DOWNLOAD_BLOCK_SIZE);
-+ memcpy(buf, &firmware->data[put], block_size);
-+
-+ if (block_size < DOWNLOAD_BLOCK_SIZE) {
-+ memset(&buf[block_size], 0, DOWNLOAD_BLOCK_SIZE - block_size);
-+ tx_size = DOWNLOAD_BLOCK_SIZE;
-+ }
-+
-+ /* send the block to sram */
-+ ret = xradio_apb_write(hw_priv, APB_ADDR(DOWNLOAD_FIFO_OFFSET + (put & (DOWNLOAD_FIFO_SIZE - 1))),
-+ buf, tx_size);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "%s: can't write block at line %d.\n", __func__, __LINE__);
-+ goto error;
-+ }
-+
-+ /* update the put register */
-+ put += block_size;
-+ APB_WRITE(DOWNLOAD_PUT_REG, put);
-+ } /* End of firmware download loop */
-+
-+ /* Wait for the download completion */
-+ for (i = 0; i < 300; i += 1 + i / 2) {
-+ APB_READ(DOWNLOAD_STATUS_REG, val32);
-+ if (val32 != DOWNLOAD_PENDING)
-+ break;
-+ mdelay(i);
-+ }
-+ if (val32 != DOWNLOAD_SUCCESS) {
-+ dev_dbg(hw_priv->pdev, "wait for download completion failed. " \
-+ "Read: 0x%.8X\n", val32);
-+ ret = -ETIMEDOUT;
-+ goto error;
-+ } else {
-+ dev_dbg(hw_priv->pdev, "Firmware completed.\n");
-+ ret = 0;
-+ }
-+
-+error:
-+ if(buf)
-+ kfree(buf);
-+ if (firmware) {
-+ release_firmware(firmware);
-+ }
-+ return ret;
-+}
-+
-+static int xradio_bootloader(struct xradio_common *hw_priv)
-+{
-+ const char *bl_path = XR819_BOOTLOADER;
-+ u32 addr = AHB_MEMORY_ADDRESS;
-+ int ret;
-+ u32 i;
-+ u32 *data;
-+ const struct firmware *bootloader;
-+
-+ /* Load a bootloader file */
-+ ret = request_firmware(&bootloader, bl_path, hw_priv->pdev);
-+ if (ret) {
-+ dev_dbg(hw_priv->pdev, "can't load bootloader file %s.\n",
-+ bl_path);
-+ goto error;
-+ }
-+
-+ /* Down bootloader. */
-+ data = (u32 *)bootloader->data;
-+ for(i = 0; i < (bootloader->size)/4; i++, addr+=4) {
-+ REG_WRITE(HIF_SRAM_BASE_ADDR_REG_ID, addr);
-+ REG_WRITE(HIF_AHB_DPORT_REG_ID,data[i]);
-+ }
-+ dev_dbg(hw_priv->pdev, "Bootloader complete\n");
-+
-+error:
-+ if(bootloader) {
-+ release_firmware(bootloader);
-+ }
-+ return ret;
-+}
-+
-+bool test_retry = false;
-+int xradio_load_firmware(struct xradio_common *hw_priv)
-+{
-+ int ret;
-+ int i;
-+ u32 val32;
-+ u16 val16;
-+ u32 dpll = 0;
-+ int major_revision;
-+
-+ /* Read CONFIG Register Value - We will read 32 bits */
-+ ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't read config register, err=%d.\n",
-+ ret);
-+ return ret;
-+ }
-+
-+ //check hardware type and revision.
-+ hw_priv->hw_type = xradio_get_hw_type(val32, &major_revision);
-+ switch (hw_priv->hw_type) {
-+ case HIF_HW_TYPE_XRADIO:
-+ dev_dbg(hw_priv->pdev, "HW_TYPE_XRADIO detected.\n");
-+ break;
-+ default:
-+ dev_dbg(hw_priv->pdev, "Unknown hardware: %d.\n",
-+ hw_priv->hw_type);
-+ return -ENOTSUPP;
-+ }
-+ if (major_revision == 4) {
-+ hw_priv->hw_revision = XR819_HW_REV0;
-+ dev_dbg(hw_priv->pdev, "XRADIO_HW_REV 1.0 detected.\n");
-+ } else {
-+ dev_dbg(hw_priv->pdev, "Unsupported major revision %d.\n",
-+ major_revision);
-+ return -ENOTSUPP;
-+ }
-+
-+ //load sdd file, and get config from it.
-+ ret = xradio_parse_sdd(hw_priv, &dpll);
-+ if (ret < 0) {
-+ return ret;
-+ }
-+
-+ //set dpll initial value and check.
-+ ret = xradio_reg_write_32(hw_priv, HIF_TSET_GEN_R_W_REG_ID, dpll);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't write DPLL register.\n");
-+ goto out;
-+ }
-+ msleep(5);
-+ ret = xradio_reg_read_32(hw_priv, HIF_TSET_GEN_R_W_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't read DPLL register.\n");
-+ goto out;
-+ }
-+ if (val32 != dpll) {
-+ dev_dbg(hw_priv->pdev, "unable to initialise " \
-+ "DPLL register. Wrote 0x%.8X, read 0x%.8X.\n",
-+ dpll, val32);
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ /* Set wakeup bit in device */
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONTROL_REG_ID, &val16);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "set_wakeup: can't read control register.\n");
-+ goto out;
-+ }
-+ ret = xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, val16 | HIF_CTRL_WUP_BIT);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "set_wakeup: can't write control register.\n");
-+ goto out;
-+ }
-+
-+ /* Wait for wakeup */
-+ for (i = 0 ; i < 300 ; i += 1 + i / 2) {
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONTROL_REG_ID, &val16);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "Wait_for_wakeup: "
-+ "can't read control register.\n");
-+ goto out;
-+ }
-+ if (val16 & HIF_CTRL_RDY_BIT) {
-+ break;
-+ }
-+ msleep(i);
-+ }
-+ if ((val16 & HIF_CTRL_RDY_BIT) == 0) {
-+ dev_dbg(hw_priv->pdev, "Wait for wakeup:"
-+ "device is not responding.\n");
-+ ret = -ETIMEDOUT;
-+ goto out;
-+ } else {
-+ dev_dbg(hw_priv->pdev, "WLAN device is ready.\n");
-+ }
-+
-+ /* Checking for access mode and download firmware. */
-+ ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "check_access_mode: "
-+ "can't read config register.\n");
-+ goto out;
-+ }
-+ if (val32 & HIF_CONFIG_ACCESS_MODE_BIT) {
-+ /* Down bootloader. */
-+ ret = xradio_bootloader(hw_priv);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't download bootloader.\n");
-+ goto out;
-+ }
-+ /* Down firmware. */
-+ ret = xradio_firmware(hw_priv);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't download firmware.\n");
-+ goto out;
-+ }
-+ } else {
-+ dev_dbg(hw_priv->pdev, "check_access_mode: "
-+ "device is already in QUEUE mode.\n");
-+ /* TODO: verify this branch. Do we need something to do? */
-+ }
-+
-+ if (HIF_HW_TYPE_XRADIO == hw_priv->hw_type) {
-+ /* If device is XRADIO the IRQ enable/disable bits
-+ * are in CONFIG register */
-+ ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "enable_irq: can't read " \
-+ "config register.\n");
-+ goto unsubscribe;
-+ }
-+ ret = xradio_reg_write_32(hw_priv, HIF_CONFIG_REG_ID,
-+ val32 | HIF_CONF_IRQ_RDY_ENABLE);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "enable_irq: can't write " \
-+ "config register.\n");
-+ goto unsubscribe;
-+ }
-+ } else {
-+ /* If device is XRADIO the IRQ enable/disable bits
-+ * are in CONTROL register */
-+ /* Enable device interrupts - Both DATA_RDY and WLAN_RDY */
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONFIG_REG_ID, &val16);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "enable_irq: can't read " \
-+ "control register.\n");
-+ goto unsubscribe;
-+ }
-+ ret = xradio_reg_write_16(hw_priv, HIF_CONFIG_REG_ID,
-+ val16 | HIF_CTRL_IRQ_RDY_ENABLE);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "enable_irq: can't write " \
-+ "control register.\n");
-+ goto unsubscribe;
-+ }
-+
-+ }
-+
-+ /* Configure device for MESSSAGE MODE */
-+ ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "set_mode: can't read config register.\n");
-+ goto unsubscribe;
-+ }
-+ ret = xradio_reg_write_32(hw_priv, HIF_CONFIG_REG_ID,
-+ val32 & ~HIF_CONFIG_ACCESS_MODE_BIT);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "set_mode: can't write config register.\n");
-+ goto unsubscribe;
-+ }
-+
-+ /* Unless we read the CONFIG Register we are
-+ * not able to get an interrupt */
-+ mdelay(10);
-+ xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ return 0;
-+
-+unsubscribe:
-+out:
-+ if (hw_priv->sdd) {
-+ release_firmware(hw_priv->sdd);
-+ hw_priv->sdd = NULL;
-+ }
-+ return ret;
-+}
-+
-+int xradio_dev_deinit(struct xradio_common *hw_priv)
-+{
-+ if (hw_priv->sdd) {
-+ release_firmware(hw_priv->sdd);
-+ hw_priv->sdd = NULL;
-+ }
-+ return 0;
-+}
-diff --git a/drivers/net/wireless/xradio/fwio.h b/drivers/net/wireless/xradio/fwio.h
-new file mode 100644
-index 0000000..b5efeb1
---- /dev/null
-+++ b/drivers/net/wireless/xradio/fwio.h
-@@ -0,0 +1,33 @@
-+/*
-+ * Firmware APIs for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef FWIO_H_INCLUDED
-+#define FWIO_H_INCLUDED
-+
-+#define XR819_HW_REV0 (8190)
-+#define XR819_BOOTLOADER ("xr819/boot_xr819.bin")
-+#define XR819_FIRMWARE ("xr819/fw_xr819.bin")
-+#define XR819_SDD_FILE ("xr819/sdd_xr819.bin")
-+
-+#define SDD_PTA_CFG_ELT_ID 0xEB
-+#define SDD_REFERENCE_FREQUENCY_ELT_ID 0xC5
-+#define FIELD_OFFSET(type, field) ((u8 *)&((type *)0)->field - (u8 *)0)
-+#define FIND_NEXT_ELT(e) (struct xradio_sdd *)((u8 *)&e->data + e->length)
-+struct xradio_sdd {
-+ u8 id;
-+ u8 length;
-+ u8 data[];
-+};
-+
-+struct xradio_common;
-+int xradio_load_firmware(struct xradio_common *hw_priv);
-+int xradio_dev_deinit(struct xradio_common *hw_priv);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/ht.c b/drivers/net/wireless/xradio/ht.c
-new file mode 100644
-index 0000000..a9b3630
---- /dev/null
-+++ b/drivers/net/wireless/xradio/ht.c
-@@ -0,0 +1,86 @@
-+#include
-+
-+#include "xradio.h"
-+#include "sta.h"
-+
-+#define AG_RATE_INDEX 6 //11a/g rate for important short frames in 5G.
-+
-+#ifdef AP_HT_COMPAT_FIX
-+#define AP_COMPAT_THRESHOLD 2000
-+#define AP_COMPAT_MIN_CNT 200
-+u8 ap_compat_bssid[ETH_ALEN] = {0};
-+int xradio_apcompat_detect(struct xradio_vif *priv, u8 rx_rate)
-+{
-+ if (rx_rate < AG_RATE_INDEX) {
-+ priv->ht_compat_cnt++;
-+ txrx_printk(XRADIO_DBG_MSG,"%s:rate=%d.\n", __func__, rx_rate);
-+ } else {
-+ priv->ht_compat_det |= 1;
-+ priv->ht_compat_cnt = 0;
-+ txrx_printk(XRADIO_DBG_NIY,"%s:HT compat detect\n", __func__);
-+ return 0;
-+ }
-+
-+ /* Enhance compatibility with some illegal APs.*/
-+ if (priv->ht_compat_cnt > AP_COMPAT_THRESHOLD ||
-+ (priv->ht_compat_cnt > AP_COMPAT_MIN_CNT &&
-+ priv->bssid[0] == 0xC8 &&
-+ priv->bssid[1] == 0x3A &&
-+ priv->bssid[2] == 0x35)) {
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ memcpy(ap_compat_bssid, priv->bssid, ETH_ALEN);
-+ wms_send_disassoc_to_self(hw_priv, priv);
-+ txrx_printk(XRADIO_DBG_WARN, "%s:SSID=%s, BSSID=" \
-+ "%02x:%02x:%02x:%02x:%02x:%02x\n", __func__, priv->ssid,
-+ ap_compat_bssid[0], ap_compat_bssid[1],
-+ ap_compat_bssid[2], ap_compat_bssid[3],
-+ ap_compat_bssid[4], ap_compat_bssid[5]);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void xradio_remove_ht_ie(struct xradio_vif *priv, struct sk_buff *skb)
-+{
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-+ u8 *ies = NULL;
-+ size_t ies_len = 0;
-+ u8 *ht_ie = NULL;
-+
-+ if (!mgmt || memcmp(ap_compat_bssid, mgmt->bssid, ETH_ALEN))
-+ return;
-+
-+ if (ieee80211_is_probe_resp(mgmt->frame_control))
-+ ies = mgmt->u.probe_resp.variable;
-+ else if (ieee80211_is_beacon(mgmt->frame_control))
-+ ies = mgmt->u.beacon.variable;
-+ else if (ieee80211_is_assoc_resp(mgmt->frame_control))
-+ ies = mgmt->u.assoc_resp.variable;
-+ else if (ieee80211_is_assoc_req(mgmt->frame_control))
-+ ies = mgmt->u.assoc_req.variable;
-+ else
-+ return;
-+
-+ ies_len = skb->len - (ies - (u8 *)(skb->data));
-+ ht_ie = (u8 *)xradio_get_ie(ies, ies_len, WLAN_EID_HT_CAPABILITY);
-+ if (ht_ie) {
-+ u8 ht_len = *(ht_ie + 1) + 2;
-+ u8 move_len = (ies + ies_len) - (ht_ie + ht_len);
-+ memmove(ht_ie, (ht_ie + ht_len), move_len);
-+ skb_trim(skb, skb->len - ht_len);
-+ ies_len = skb->len - (ies - (u8 *)(skb->data));
-+ ht_ie = (u8 *)xradio_get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
-+ if (ht_ie) {
-+ ht_len = *(ht_ie + 1) + 2;
-+ move_len = (ies + ies_len) - (ht_ie + ht_len);
-+ memmove(ht_ie, (ht_ie + ht_len), move_len);
-+ skb_trim(skb, skb->len - ht_len);
-+ }
-+ }
-+ txrx_printk(XRADIO_DBG_WARN, "%s: BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
-+ __func__,
-+ mgmt->bssid[0], mgmt->bssid[1],
-+ mgmt->bssid[2], mgmt->bssid[3],
-+ mgmt->bssid[4], mgmt->bssid[5]);
-+}
-+#endif //AP_HT_COMPAT_FIX
-\ No newline at end of file
-diff --git a/drivers/net/wireless/xradio/ht.h b/drivers/net/wireless/xradio/ht.h
-new file mode 100644
-index 0000000..346b425
---- /dev/null
-+++ b/drivers/net/wireless/xradio/ht.h
-@@ -0,0 +1,44 @@
-+/*
-+ * HT-related code for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef XRADIO_HT_H_INCLUDED
-+#define XRADIO_HT_H_INCLUDED
-+
-+#include
-+
-+struct xradio_ht_oper {
-+ struct ieee80211_sta_ht_cap ht_cap;
-+ enum nl80211_channel_type channel_type;
-+ u16 operation_mode;
-+};
-+
-+static inline int xradio_is_ht(const struct xradio_ht_oper *ht_oper)
-+{
-+ return ht_oper->channel_type != NL80211_CHAN_NO_HT;
-+}
-+
-+static inline int xradio_ht_greenfield(const struct xradio_ht_oper *ht_oper)
-+{
-+ return (xradio_is_ht(ht_oper) &&
-+ (ht_oper->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
-+ !(ht_oper->operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT));
-+}
-+
-+static inline int xradio_ht_ampdu_density(const struct xradio_ht_oper *ht_oper)
-+{
-+ if (!xradio_is_ht(ht_oper))
-+ return 0;
-+ return ht_oper->ht_cap.ampdu_density;
-+}
-+
-+int xradio_apcompat_detect(struct xradio_vif *priv, u8 rx_rate);
-+void xradio_remove_ht_ie(struct xradio_vif *priv, struct sk_buff *skb);
-+
-+#endif /* XRADIO_HT_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/hwio.c b/drivers/net/wireless/xradio/hwio.c
-new file mode 100644
-index 0000000..b813333
---- /dev/null
-+++ b/drivers/net/wireless/xradio/hwio.c
-@@ -0,0 +1,280 @@
-+/*
-+ * Hardware I/O implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+
-+#include "xradio.h"
-+#include "hwio.h"
-+#include "sdio.h"
-+
-+#define CHECK_ADDR_LEN 1
-+
-+ /* Sdio addr is 4*spi_addr */
-+#define SPI_REG_ADDR_TO_SDIO(spi_reg_addr) ((spi_reg_addr) << 2)
-+#define SDIO_ADDR17BIT(buf_id, mpf, rfu, reg_id_ofs) \
-+ ((((buf_id) & 0x1F) << 7) \
-+ | (((mpf) & 1) << 6) \
-+ | (((rfu) & 1) << 5) \
-+ | (((reg_id_ofs) & 0x1F) << 0))
-+#define MAX_RETRY 3
-+
-+
-+static int __xradio_read(struct xradio_common *hw_priv, u16 addr,
-+ void *buf, size_t buf_len, int buf_id)
-+{
-+ u16 addr_sdio;
-+ u32 sdio_reg_addr_17bit ;
-+
-+#if (CHECK_ADDR_LEN)
-+ /* Check if buffer is aligned to 4 byte boundary */
-+ if (WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
-+ dev_dbg(hw_priv->pdev, "buffer is not aligned.\n");
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ /* Convert to SDIO Register Address */
-+ addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
-+ sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
-+ return sdio_data_read(hw_priv,
-+ sdio_reg_addr_17bit,
-+ buf, buf_len);
-+}
-+
-+static int __xradio_write(struct xradio_common *hw_priv, u16 addr,
-+ const void *buf, size_t buf_len, int buf_id)
-+{
-+ u16 addr_sdio;
-+ u32 sdio_reg_addr_17bit ;
-+
-+#if (CHECK_ADDR_LEN)
-+ /* Check if buffer is aligned to 4 byte boundary */
-+ if (WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
-+ dev_err(hw_priv->pdev, "buffer is not aligned.\n");
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ /* Convert to SDIO Register Address */
-+ addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
-+ sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
-+
-+ return sdio_data_write(hw_priv,
-+ sdio_reg_addr_17bit,
-+ buf, buf_len);
-+}
-+
-+static inline int __xradio_read_reg32(struct xradio_common *hw_priv,
-+ u16 addr, u32 *val)
-+{
-+ return __xradio_read(hw_priv, addr, val, sizeof(val), 0);
-+}
-+
-+static inline int __xradio_write_reg32(struct xradio_common *hw_priv,
-+ u16 addr, u32 val)
-+{
-+ return __xradio_write(hw_priv, addr, &val, sizeof(val), 0);
-+}
-+
-+int xradio_reg_read(struct xradio_common *hw_priv, u16 addr,
-+ void *buf, size_t buf_len)
-+{
-+ int ret;
-+ sdio_lock(hw_priv);
-+ ret = __xradio_read(hw_priv, addr, buf, buf_len, 0);
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_reg_write(struct xradio_common *hw_priv, u16 addr,
-+ const void *buf, size_t buf_len)
-+{
-+ int ret;
-+ sdio_lock(hw_priv);
-+ ret = __xradio_write(hw_priv, addr, buf, buf_len, 0);
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_data_read(struct xradio_common *hw_priv, void *buf, size_t buf_len)
-+{
-+ int ret, retry = 1;
-+ sdio_lock(hw_priv);
-+ {
-+ int buf_id_rx = hw_priv->buf_id_rx;
-+ while (retry <= MAX_RETRY) {
-+ ret = __xradio_read(hw_priv, HIF_IN_OUT_QUEUE_REG_ID, buf,
-+ buf_len, buf_id_rx + 1);
-+ if (!ret) {
-+ buf_id_rx = (buf_id_rx + 1) & 3;
-+ hw_priv->buf_id_rx = buf_id_rx;
-+ break;
-+ } else {
-+ //~dgp this retrying stuff is silly as it can crash the fw if there is nothing to read
-+ dev_err(hw_priv->pdev, "data read error :%d - attempt %d of %d\n", ret, retry, MAX_RETRY);
-+ retry++;
-+ mdelay(1);
-+ }
-+ }
-+ }
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_data_write(struct xradio_common *hw_priv, const void *buf,
-+ size_t buf_len)
-+{
-+ int ret, retry = 1;
-+ sdio_lock(hw_priv);
-+ {
-+ int buf_id_tx = hw_priv->buf_id_tx;
-+ while (retry <= MAX_RETRY) {
-+ ret = __xradio_write(hw_priv, HIF_IN_OUT_QUEUE_REG_ID, buf,
-+ buf_len, buf_id_tx);
-+ if (!ret) {
-+ buf_id_tx = (buf_id_tx + 1) & 31;
-+ hw_priv->buf_id_tx = buf_id_tx;
-+ break;
-+ } else {
-+ dev_err(hw_priv->pdev, "data write error :%d - attempt %d - %d\n", ret, retry, MAX_RETRY);
-+ retry++;
-+ mdelay(1);
-+ }
-+ }
-+ }
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_indirect_read(struct xradio_common *hw_priv, u32 addr, void *buf,
-+ size_t buf_len, u32 prefetch, u16 port_addr)
-+{
-+ u32 val32 = 0;
-+ int i, ret;
-+
-+ if ((buf_len / 2) >= 0x1000) {
-+ dev_err(hw_priv->pdev, "Can't read more than 0xfff words.\n");
-+ return -EINVAL;
-+ goto out;
-+ }
-+
-+ sdio_lock(hw_priv);
-+ /* Write address */
-+ ret = __xradio_write_reg32(hw_priv, HIF_SRAM_BASE_ADDR_REG_ID, addr);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write address register.\n");
-+ goto out;
-+ }
-+
-+ /* Read CONFIG Register Value - We will read 32 bits */
-+ ret = __xradio_read_reg32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't read config register.\n");
-+ goto out;
-+ }
-+
-+ /* Set PREFETCH bit */
-+ ret = __xradio_write_reg32(hw_priv, HIF_CONFIG_REG_ID, val32 | prefetch);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write prefetch bit.\n");
-+ goto out;
-+ }
-+
-+ /* Check for PRE-FETCH bit to be cleared */
-+ for (i = 0; i < 20; i++) {
-+ ret = __xradio_read_reg32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't check prefetch bit.\n");
-+ goto out;
-+ }
-+ if (!(val32 & prefetch))
-+ break;
-+ mdelay(i);
-+ }
-+
-+ if (val32 & prefetch) {
-+ dev_err(hw_priv->pdev, "Prefetch bit is not cleared.\n");
-+ goto out;
-+ }
-+
-+ /* Read data port */
-+ ret = __xradio_read(hw_priv, port_addr, buf, buf_len, 0);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't read data port.\n");
-+ goto out;
-+ }
-+
-+out:
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_apb_write(struct xradio_common *hw_priv, u32 addr, const void *buf,
-+ size_t buf_len)
-+{
-+ int ret;
-+
-+ if ((buf_len / 2) >= 0x1000) {
-+ dev_err(hw_priv->pdev, "Can't wrire more than 0xfff words.\n");
-+ return -EINVAL;
-+ }
-+
-+ sdio_lock(hw_priv);
-+
-+ /* Write address */
-+ ret = __xradio_write_reg32(hw_priv, HIF_SRAM_BASE_ADDR_REG_ID, addr);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write address register.\n");
-+ goto out;
-+ }
-+
-+ /* Write data port */
-+ ret = __xradio_write(hw_priv, HIF_SRAM_DPORT_REG_ID, buf, buf_len, 0);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write data port.\n");
-+ goto out;
-+ }
-+
-+out:
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_ahb_write(struct xradio_common *hw_priv, u32 addr, const void *buf,
-+ size_t buf_len)
-+{
-+ int ret;
-+
-+ if ((buf_len / 2) >= 0x1000) {
-+ dev_err(hw_priv->pdev, "Can't wrire more than 0xfff words.\n");
-+ return -EINVAL;
-+ }
-+
-+ sdio_lock(hw_priv);
-+
-+ /* Write address */
-+ ret = __xradio_write_reg32(hw_priv, HIF_SRAM_BASE_ADDR_REG_ID, addr);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write address register.\n");
-+ goto out;
-+ }
-+
-+ /* Write data port */
-+ ret = __xradio_write(hw_priv, HIF_AHB_DPORT_REG_ID, buf, buf_len, 0);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write data port.\n");
-+ goto out;
-+ }
-+
-+out:
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-diff --git a/drivers/net/wireless/xradio/hwio.h b/drivers/net/wireless/xradio/hwio.h
-new file mode 100644
-index 0000000..531c2b8
---- /dev/null
-+++ b/drivers/net/wireless/xradio/hwio.h
-@@ -0,0 +1,229 @@
-+/*
-+ * hardware interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_HWIO_H_INCLUDED
-+#define XRADIO_HWIO_H_INCLUDED
-+
-+/* extern */ struct xradio_common;
-+
-+/* DPLL initial values */
-+#define DPLL_INIT_VAL_XRADIO (0x0EC4F121)
-+
-+/* Hardware Type Definitions */
-+#define HIF_HW_TYPE_XRADIO (1)
-+
-+
-+/* boot loader start address in SRAM */
-+#define DOWNLOAD_BOOT_LOADER_OFFSET (0x00000000)
-+/* 32K, 0x4000 to 0xDFFF */
-+#define DOWNLOAD_FIFO_OFFSET (0x00004000)
-+/* 32K */
-+#define DOWNLOAD_FIFO_SIZE (0x00008000)
-+/* 128 bytes, 0xFF80 to 0xFFFF */
-+#define DOWNLOAD_CTRL_OFFSET (0x0000FF80)
-+#define DOWNLOAD_CTRL_DATA_DWORDS (32-6)
-+
-+/* Download control area */
-+struct download_cntl_t {
-+ /* size of whole firmware file (including Cheksum), host init */
-+ u32 ImageSize;
-+ /* downloading flags */
-+ u32 Flags;
-+ /* No. of bytes put into the download, init & updated by host */
-+ u32 Put;
-+ /* last traced program counter, last ARM reg_pc */
-+ u32 TracePc;
-+ /* No. of bytes read from the download, host init, device updates */
-+ u32 Get;
-+ /* r0, boot losader status, host init to pending, device updates */
-+ u32 Status;
-+ /* Extra debug info, r1 to r14 if status=r0=DOWNLOAD_EXCEPTION */
-+ u32 DebugData[DOWNLOAD_CTRL_DATA_DWORDS];
-+};
-+
-+#define DOWNLOAD_IMAGE_SIZE_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, ImageSize))
-+#define DOWNLOAD_FLAGS_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, Flags))
-+#define DOWNLOAD_PUT_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, Put))
-+#define DOWNLOAD_TRACE_PC_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, TracePc))
-+#define DOWNLOAD_GET_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, Get))
-+#define DOWNLOAD_STATUS_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, Status))
-+#define DOWNLOAD_DEBUG_DATA_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, DebugData))
-+
-+#define DOWNLOAD_DEBUG_DATA_LEN (108)
-+#define DOWNLOAD_BLOCK_SIZE (1024)
-+
-+/* For boot loader detection */
-+#define DOWNLOAD_ARE_YOU_HERE (0x87654321)
-+#define DOWNLOAD_I_AM_HERE (0x12345678)
-+
-+/* Download error code */
-+#define DOWNLOAD_PENDING (0xFFFFFFFF)
-+#define DOWNLOAD_SUCCESS (0)
-+#define DOWNLOAD_EXCEPTION (1)
-+#define DOWNLOAD_ERR_MEM_1 (2)
-+#define DOWNLOAD_ERR_MEM_2 (3)
-+#define DOWNLOAD_ERR_SOFTWARE (4)
-+#define DOWNLOAD_ERR_FILE_SIZE (5)
-+#define DOWNLOAD_ERR_CHECKSUM (6)
-+#define DOWNLOAD_ERR_OVERFLOW (7)
-+#define DOWNLOAD_ERR_IMAGE (8)
-+#define DOWNLOAD_ERR_HOST (9)
-+#define DOWNLOAD_ERR_ABORT (10)
-+
-+#define SYS_BASE_ADDR_SILICON (0)
-+#define AHB_MEMORY_ADDRESS (SYS_BASE_ADDR_SILICON + 0x08000000)
-+#define PAC_BASE_ADDRESS_SILICON (SYS_BASE_ADDR_SILICON + 0x09000000)
-+#define PAC_SHARED_MEMORY_SILICON (PAC_BASE_ADDRESS_SILICON)
-+#define APB_ADDR(addr) (PAC_SHARED_MEMORY_SILICON + (addr))
-+
-+/* ***************************************************************
-+*Device register definitions
-+*************************************************************** */
-+/* WBF - SPI Register Addresses */
-+#define HIF_ADDR_ID_BASE (0x0000)
-+/* 16/32 bits */
-+#define HIF_CONFIG_REG_ID (0x0000)
-+/* 16/32 bits */
-+#define HIF_CONTROL_REG_ID (0x0001)
-+/* 16 bits, Q mode W/R */
-+#define HIF_IN_OUT_QUEUE_REG_ID (0x0002)
-+/* 32 bits, AHB bus R/W */
-+#define HIF_AHB_DPORT_REG_ID (0x0003)
-+/* 16/32 bits */
-+#define HIF_SRAM_BASE_ADDR_REG_ID (0x0004)
-+/* 32 bits, APB bus R/W */
-+#define HIF_SRAM_DPORT_REG_ID (0x0005)
-+/* 32 bits, t_settle/general */
-+#define HIF_TSET_GEN_R_W_REG_ID (0x0006)
-+/* 16 bits, Q mode read, no length */
-+#define HIF_FRAME_OUT_REG_ID (0x0007)
-+#define HIF_ADDR_ID_MAX (HIF_FRAME_OUT_REG_ID)
-+
-+/* WBF - Control register bit set */
-+/* next o/p length, bit 11 to 0 */
-+#define HIF_CTRL_NEXT_LEN_MASK (0x0FFF)
-+#define HIF_CTRL_WUP_BIT (BIT(12))
-+#define HIF_CTRL_RDY_BIT (BIT(13))
-+#define HIF_CTRL_IRQ_ENABLE (BIT(14))
-+#define HIF_CTRL_RDY_ENABLE (BIT(15))
-+#define HIF_CTRL_IRQ_RDY_ENABLE (BIT(14)|BIT(15))
-+
-+/* SPI Config register bit set */
-+#define HIF_CONFIG_FRAME_BIT (BIT(2))
-+#define HIF_CONFIG_WORD_MODE_BITS (BIT(3)|BIT(4))
-+#define HIF_CONFIG_WORD_MODE_1 (BIT(3))
-+#define HIF_CONFIG_WORD_MODE_2 (BIT(4))
-+#define HIF_CONFIG_ERROR_0_BIT (BIT(5))
-+#define HIF_CONFIG_ERROR_1_BIT (BIT(6))
-+#define HIF_CONFIG_ERROR_2_BIT (BIT(7))
-+/* TBD: Sure??? */
-+#define HIF_CONFIG_CSN_FRAME_BIT (BIT(7))
-+#define HIF_CONFIG_ERROR_3_BIT (BIT(8))
-+#define HIF_CONFIG_ERROR_4_BIT (BIT(9))
-+/* QueueM */
-+#define HIF_CONFIG_ACCESS_MODE_BIT (BIT(10))
-+/* AHB bus */
-+#define HIF_CONFIG_AHB_PFETCH_BIT (BIT(11))
-+#define HIF_CONFIG_CPU_CLK_DIS_BIT (BIT(12))
-+/* APB bus */
-+#define HIF_CONFIG_PFETCH_BIT (BIT(13))
-+/* cpu reset */
-+#define HIF_CONFIG_CPU_RESET_BIT (BIT(14))
-+#define HIF_CONFIG_CLEAR_INT_BIT (BIT(15))
-+
-+/* For XRADIO the IRQ Enable and Ready Bits are in CONFIG register */
-+#define HIF_CONF_IRQ_RDY_ENABLE (BIT(16)|BIT(17))
-+
-+int xradio_data_read(struct xradio_common *hw_priv, void *buf, size_t buf_len);
-+int xradio_data_write(struct xradio_common *hw_priv, const void *buf, size_t buf_len);
-+int xradio_reg_read(struct xradio_common *hw_priv, u16 addr, void *buf, size_t buf_len);
-+int xradio_reg_write(struct xradio_common *hw_priv, u16 addr, const void *buf, size_t buf_len);
-+int xradio_indirect_read(struct xradio_common *hw_priv, u32 addr, void *buf,
-+ size_t buf_len, u32 prefetch, u16 port_addr);
-+int xradio_apb_write(struct xradio_common *hw_priv, u32 addr, const void *buf, size_t buf_len);
-+int xradio_ahb_write(struct xradio_common *hw_priv, u32 addr, const void *buf, size_t buf_len);
-+
-+
-+static inline int xradio_reg_read_16(struct xradio_common *hw_priv,
-+ u16 addr, u16 *val)
-+{
-+ int ret = 0;
-+ u32 bigVal = 0;
-+ ret = xradio_reg_read(hw_priv, addr, &bigVal, sizeof(bigVal));
-+ *val = (u16)bigVal;
-+ return ret;
-+}
-+
-+static inline int xradio_reg_write_16(struct xradio_common *hw_priv,
-+ u16 addr, u16 val)
-+{
-+ u32 bigVal = (u32)val;
-+ return xradio_reg_write(hw_priv, addr, &bigVal, sizeof(bigVal));
-+}
-+
-+static inline int xradio_reg_read_32(struct xradio_common *hw_priv,
-+ u16 addr, u32 *val)
-+{
-+ return xradio_reg_read(hw_priv, addr, val, sizeof(val));
-+}
-+
-+static inline int xradio_reg_write_32(struct xradio_common *hw_priv,
-+ u16 addr, u32 val)
-+{
-+ return xradio_reg_write(hw_priv, addr, &val, sizeof(val));
-+}
-+
-+static inline int xradio_apb_read(struct xradio_common *hw_priv, u32 addr,
-+ void *buf, size_t buf_len)
-+{
-+ return xradio_indirect_read(hw_priv, addr, buf, buf_len, HIF_CONFIG_PFETCH_BIT,
-+ HIF_SRAM_DPORT_REG_ID);
-+}
-+
-+static inline int xradio_ahb_read(struct xradio_common *hw_priv, u32 addr,
-+ void *buf, size_t buf_len)
-+{
-+ return xradio_indirect_read(hw_priv, addr, buf, buf_len, HIF_CONFIG_AHB_PFETCH_BIT,
-+ HIF_AHB_DPORT_REG_ID);
-+}
-+
-+static inline int xradio_apb_read_32(struct xradio_common *hw_priv,
-+ u32 addr, u32 *val)
-+{
-+ return xradio_apb_read(hw_priv, addr, val, sizeof(val));
-+}
-+
-+static inline int xradio_apb_write_32(struct xradio_common *hw_priv,
-+ u32 addr, u32 val)
-+{
-+ return xradio_apb_write(hw_priv, addr, &val, sizeof(val));
-+}
-+
-+static inline int xradio_ahb_read_32(struct xradio_common *hw_priv,
-+ u32 addr, u32 *val)
-+{
-+ return xradio_ahb_read(hw_priv, addr, val, sizeof(val));
-+}
-+
-+static inline int xradio_ahb_write_32(struct xradio_common *hw_priv,
-+ u32 addr, u32 val)
-+{
-+ return xradio_ahb_write(hw_priv, addr, &val, sizeof(val));
-+}
-+
-+#endif /* XRADIO_HWIO_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/keys.c b/drivers/net/wireless/xradio/keys.c
-new file mode 100644
-index 0000000..20050e1
---- /dev/null
-+++ b/drivers/net/wireless/xradio/keys.c
-@@ -0,0 +1,193 @@
-+#include
-+
-+#include "xradio.h"
-+#include "sta.h"
-+#include "keys.h"
-+
-+int xradio_alloc_key(struct xradio_common *hw_priv)
-+{
-+ int idx;
-+
-+ idx = ffs(~hw_priv->key_map) - 1;
-+ if (idx < 0 || idx > WSM_KEY_MAX_INDEX)
-+ return -1;
-+
-+ hw_priv->key_map |= BIT(idx);
-+ hw_priv->keys[idx].entryIndex = idx;
-+ return idx;
-+}
-+
-+void xradio_free_key(struct xradio_common *hw_priv, int idx)
-+{
-+ BUG_ON(!(hw_priv->key_map & BIT(idx)));
-+ memset(&hw_priv->keys[idx], 0, sizeof(hw_priv->keys[idx]));
-+ hw_priv->key_map &= ~BIT(idx);
-+}
-+
-+void xradio_free_keys(struct xradio_common *hw_priv)
-+{
-+ memset(&hw_priv->keys, 0, sizeof(hw_priv->keys));
-+ hw_priv->key_map = 0;
-+}
-+
-+int xradio_upload_keys(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int idx, ret = 0;
-+
-+
-+ for (idx = 0; idx <= WSM_KEY_MAX_IDX; ++idx)
-+ if (hw_priv->key_map & BIT(idx)) {
-+ ret = wsm_add_key(hw_priv, &hw_priv->keys[idx], priv->if_id);
-+ if (ret < 0)
-+ break;
-+ }
-+ return ret;
-+}
-+
-+int xradio_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
-+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-+ struct ieee80211_key_conf *key)
-+{
-+#ifdef XRADIO_DISABLE_HW_CRYPTO
-+ wiphy_info(dev->wiphy, "hw crypto is disabled, ignoring key request\n");
-+ return -EOPNOTSUPP;
-+#else
-+ int ret = -EOPNOTSUPP;
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+
-+ wiphy_dbg(dev->wiphy, "vif %d: set_key cmd %d\n", priv->if_id, (int) cmd);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ if (cmd == SET_KEY) {
-+ u8 *peer_addr = NULL;
-+ int pairwise = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? 1 : 0;
-+ int idx = xradio_alloc_key(hw_priv);
-+ struct wsm_add_key *wsm_key = &hw_priv->keys[idx];
-+
-+ if (idx < 0) {
-+ wiphy_err(dev->wiphy, "xradio_alloc_key failed!\n");
-+ ret = -EINVAL;
-+ goto finally;
-+ }
-+
-+ BUG_ON(pairwise && !sta);
-+ if (sta)
-+ peer_addr = sta->addr;
-+
-+ key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
-+
-+ priv->cipherType = key->cipher;
-+ switch (key->cipher) {
-+ case WLAN_CIPHER_SUITE_WEP40:
-+ case WLAN_CIPHER_SUITE_WEP104:
-+ if (key->keylen > 16) {
-+ xradio_free_key(hw_priv, idx);
-+ wiphy_err(dev->wiphy, "keylen too long=%d!\n", key->keylen);
-+ ret = -EINVAL;
-+ goto finally;
-+ }
-+
-+ if (pairwise) {
-+ wsm_key->type = WSM_KEY_TYPE_WEP_PAIRWISE;
-+ memcpy(wsm_key->wepPairwiseKey.peerAddress, peer_addr, ETH_ALEN);
-+ memcpy(wsm_key->wepPairwiseKey.keyData, &key->key[0], key->keylen);
-+ wsm_key->wepPairwiseKey.keyLength = key->keylen;
-+ } else {
-+ wsm_key->type = WSM_KEY_TYPE_WEP_DEFAULT;
-+ memcpy(wsm_key->wepGroupKey.keyData, &key->key[0], key->keylen);
-+ wsm_key->wepGroupKey.keyLength = key->keylen;
-+ wsm_key->wepGroupKey.keyId = key->keyidx;
-+ }
-+ break;
-+ case WLAN_CIPHER_SUITE_TKIP:
-+ if (pairwise) {
-+ wsm_key->type = WSM_KEY_TYPE_TKIP_PAIRWISE;
-+ memcpy(wsm_key->tkipPairwiseKey.peerAddress, peer_addr, ETH_ALEN);
-+ memcpy(wsm_key->tkipPairwiseKey.tkipKeyData, &key->key[0], 16);
-+ memcpy(wsm_key->tkipPairwiseKey.txMicKey, &key->key[16], 8);
-+ memcpy(wsm_key->tkipPairwiseKey.rxMicKey, &key->key[24], 8);
-+ } else {
-+ size_t mic_offset = (priv->mode == NL80211_IFTYPE_AP) ? 16 : 24;
-+ wsm_key->type = WSM_KEY_TYPE_TKIP_GROUP;
-+ memcpy(wsm_key->tkipGroupKey.tkipKeyData,&key->key[0], 16);
-+ memcpy(wsm_key->tkipGroupKey.rxMicKey, &key->key[mic_offset], 8);
-+
-+ /* TODO: Where can I find TKIP SEQ? */
-+ memset(wsm_key->tkipGroupKey.rxSeqCounter, 0, 8);
-+ wsm_key->tkipGroupKey.keyId = key->keyidx;
-+ }
-+ break;
-+ case WLAN_CIPHER_SUITE_CCMP:
-+ if (pairwise) {
-+ wsm_key->type = WSM_KEY_TYPE_AES_PAIRWISE;
-+ memcpy(wsm_key->aesPairwiseKey.peerAddress, peer_addr, ETH_ALEN);
-+ memcpy(wsm_key->aesPairwiseKey.aesKeyData, &key->key[0], 16);
-+ wiphy_debug(dev->wiphy, "CCMP_PAIRWISE keylen=%d!\n",
-+ key->keylen);
-+ } else {
-+ wsm_key->type = WSM_KEY_TYPE_AES_GROUP;
-+ memcpy(wsm_key->aesGroupKey.aesKeyData, &key->key[0], 16);
-+ /* TODO: Where can I find AES SEQ? */
-+ memset(wsm_key->aesGroupKey.rxSeqCounter, 0, 8);
-+ wsm_key->aesGroupKey.keyId = key->keyidx;
-+ }
-+ break;
-+#ifdef CONFIG_XRADIO_WAPI_SUPPORT
-+ case WLAN_CIPHER_SUITE_SMS4:
-+ if (pairwise) {
-+ wsm_key->type = WSM_KEY_TYPE_WAPI_PAIRWISE;
-+ memcpy(wsm_key->wapiPairwiseKey.peerAddress, peer_addr, ETH_ALEN);
-+ memcpy(wsm_key->wapiPairwiseKey.wapiKeyData, &key->key[0], 16);
-+ memcpy(wsm_key->wapiPairwiseKey.micKeyData, &key->key[16], 16);
-+ wsm_key->wapiPairwiseKey.keyId = key->keyidx;
-+ sta_printk(XRADIO_DBG_NIY,"%s: WAPI_PAIRWISE keylen=%d!\n",
-+ __func__, key->keylen);
-+ } else {
-+ wsm_key->type = WSM_KEY_TYPE_WAPI_GROUP;
-+ memcpy(wsm_key->wapiGroupKey.wapiKeyData, &key->key[0], 16);
-+ memcpy(wsm_key->wapiGroupKey.micKeyData, &key->key[16], 16);
-+ wsm_key->wapiGroupKey.keyId = key->keyidx;
-+ sta_printk(XRADIO_DBG_NIY,"%s: WAPI_GROUP keylen=%d!\n",
-+ __func__, key->keylen);
-+ }
-+ break;
-+#endif /* CONFIG_XRADIO_WAPI_SUPPORT */
-+ default:
-+ wiphy_err(dev->wiphy, "key->cipher unknown(%d)!\n", key->cipher);
-+ xradio_free_key(hw_priv, idx);
-+ ret = -EOPNOTSUPP;
-+ goto finally;
-+ }
-+ ret = WARN_ON(wsm_add_key(hw_priv, wsm_key, priv->if_id));
-+ if (!ret)
-+ key->hw_key_idx = idx;
-+ else
-+ xradio_free_key(hw_priv, idx);
-+
-+ if (!ret && (pairwise || wsm_key->type == WSM_KEY_TYPE_WEP_DEFAULT) &&
-+ (priv->filter4.enable & 0x2))
-+ xradio_set_arpreply(dev, vif);
-+ } else if (cmd == DISABLE_KEY) {
-+ struct wsm_remove_key wsm_key = {
-+ .entryIndex = key->hw_key_idx,
-+ };
-+
-+ if (wsm_key.entryIndex > WSM_KEY_MAX_IDX) {
-+ ret = -EINVAL;
-+ goto finally;
-+ }
-+
-+ xradio_free_key(hw_priv, wsm_key.entryIndex);
-+ ret = wsm_remove_key(hw_priv, &wsm_key, priv->if_id);
-+ } else {
-+ wiphy_err(dev->wiphy, "Unsupported command\n");
-+ }
-+
-+finally:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return ret;
-+#endif // XRADIO_DISABLE_HW_CRYPTO
-+}
-diff --git a/drivers/net/wireless/xradio/keys.h b/drivers/net/wireless/xradio/keys.h
-new file mode 100644
-index 0000000..23c5880
---- /dev/null
-+++ b/drivers/net/wireless/xradio/keys.h
-@@ -0,0 +1,12 @@
-+#ifndef __KEYS_H_
-+#define __KEYS_H_INCLUDED
-+
-+int xradio_alloc_key(struct xradio_common *hw_priv);
-+void xradio_free_key(struct xradio_common *hw_priv, int idx);
-+void xradio_free_keys(struct xradio_common *hw_priv);
-+int xradio_upload_keys(struct xradio_vif *priv);
-+int xradio_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
-+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-+ struct ieee80211_key_conf *key);
-+
-+#endif
-\ No newline at end of file
-diff --git a/drivers/net/wireless/xradio/main.c b/drivers/net/wireless/xradio/main.c
-new file mode 100644
-index 0000000..346710c
---- /dev/null
-+++ b/drivers/net/wireless/xradio/main.c
-@@ -0,0 +1,609 @@
-+/*
-+ * Main code of XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "fwio.h"
-+#include "hwio.h"
-+#include "bh.h"
-+#include "sta.h"
-+#include "ap.h"
-+#include "keys.h"
-+#include "scan.h"
-+#include "pm.h"
-+#include "sdio.h"
-+
-+/* TODO: use rates and channels from the device */
-+#define RATETAB_ENT(_rate, _rateid, _flags) \
-+ { \
-+ .bitrate = (_rate), \
-+ .hw_value = (_rateid), \
-+ .flags = (_flags), \
-+ }
-+
-+static struct ieee80211_rate xradio_rates[] = {
-+ RATETAB_ENT(10, 0, 0),
-+ RATETAB_ENT(20, 1, 0),
-+ RATETAB_ENT(55, 2, 0),
-+ RATETAB_ENT(110, 3, 0),
-+ RATETAB_ENT(60, 6, 0),
-+ RATETAB_ENT(90, 7, 0),
-+ RATETAB_ENT(120, 8, 0),
-+ RATETAB_ENT(180, 9, 0),
-+ RATETAB_ENT(240, 10, 0),
-+ RATETAB_ENT(360, 11, 0),
-+ RATETAB_ENT(480, 12, 0),
-+ RATETAB_ENT(540, 13, 0),
-+};
-+
-+static struct ieee80211_rate xradio_mcs_rates[] = {
-+ RATETAB_ENT(65, 14, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(130, 15, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(195, 16, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(260, 17, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(390, 18, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(520, 19, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(585, 20, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(650, 21, IEEE80211_TX_RC_MCS),
-+};
-+
-+#define xradio_g_rates (xradio_rates + 0)
-+#define xradio_a_rates (xradio_rates + 4)
-+#define xradio_n_rates (xradio_mcs_rates)
-+
-+#define xradio_g_rates_size (ARRAY_SIZE(xradio_rates))
-+#define xradio_a_rates_size (ARRAY_SIZE(xradio_rates) - 4)
-+#define xradio_n_rates_size (ARRAY_SIZE(xradio_mcs_rates))
-+
-+#define CHAN2G(_channel, _freq, _flags) { \
-+ .band = NL80211_BAND_2GHZ, \
-+ .center_freq = (_freq), \
-+ .hw_value = (_channel), \
-+ .flags = (_flags), \
-+ .max_antenna_gain = 0, \
-+ .max_power = 30, \
-+}
-+
-+#define CHAN5G(_channel, _flags) { \
-+ .band = NL80211_BAND_5GHZ, \
-+ .center_freq = 5000 + (5 * (_channel)), \
-+ .hw_value = (_channel), \
-+ .flags = (_flags), \
-+ .max_antenna_gain = 0, \
-+ .max_power = 30, \
-+}
-+
-+static struct ieee80211_channel xradio_2ghz_chantable[] = {
-+ CHAN2G(1, 2412, 0),
-+ CHAN2G(2, 2417, 0),
-+ CHAN2G(3, 2422, 0),
-+ CHAN2G(4, 2427, 0),
-+ CHAN2G(5, 2432, 0),
-+ CHAN2G(6, 2437, 0),
-+ CHAN2G(7, 2442, 0),
-+ CHAN2G(8, 2447, 0),
-+ CHAN2G(9, 2452, 0),
-+ CHAN2G(10, 2457, 0),
-+ CHAN2G(11, 2462, 0),
-+ CHAN2G(12, 2467, 0),
-+ CHAN2G(13, 2472, 0),
-+ CHAN2G(14, 2484, 0),
-+};
-+
-+static struct ieee80211_supported_band xradio_band_2ghz = {
-+ .channels = xradio_2ghz_chantable,
-+ .n_channels = ARRAY_SIZE(xradio_2ghz_chantable),
-+ .bitrates = xradio_g_rates,
-+ .n_bitrates = xradio_g_rates_size,
-+ .ht_cap = {
-+ .cap = IEEE80211_HT_CAP_GRN_FLD |
-+ (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT),
-+ .ht_supported = 1,
-+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_32K,
-+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
-+ .mcs = {
-+ .rx_mask[0] = 0xFF,
-+ .rx_highest = __cpu_to_le16(0x41),
-+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
-+ },
-+ },
-+};
-+
-+static const unsigned long xradio_ttl[] = {
-+ 1 * HZ, /* VO */
-+ 2 * HZ, /* VI */
-+ 5 * HZ, /* BE */
-+ 10 * HZ /* BK */
-+};
-+
-+static const struct ieee80211_ops xradio_ops = {
-+ .start = xradio_start,
-+ .stop = xradio_stop,
-+ .add_interface = xradio_add_interface,
-+ .remove_interface = xradio_remove_interface,
-+ .change_interface = xradio_change_interface,
-+ .tx = xradio_tx,
-+ .hw_scan = xradio_hw_scan,
-+#ifdef ROAM_OFFLOAD
-+ .sched_scan_start = xradio_hw_sched_scan_start,
-+ .sched_scan_stop = xradio_hw_sched_scan_stop,
-+#endif /*ROAM_OFFLOAD*/
-+ .set_tim = xradio_set_tim,
-+ .sta_notify = xradio_sta_notify,
-+ .sta_add = xradio_sta_add,
-+ .sta_remove = xradio_sta_remove,
-+ .set_key = xradio_set_key,
-+ .set_rts_threshold = xradio_set_rts_threshold,
-+ .config = xradio_config,
-+ .bss_info_changed = xradio_bss_info_changed,
-+ .prepare_multicast = xradio_prepare_multicast,
-+ .configure_filter = xradio_configure_filter,
-+ .conf_tx = xradio_conf_tx,
-+ .get_stats = xradio_get_stats,
-+ .ampdu_action = xradio_ampdu_action,
-+ .flush = xradio_flush,
-+#ifdef CONFIG_PM
-+ .suspend = xradio_wow_suspend,
-+ .resume = xradio_wow_resume,
-+#endif /* CONFIG_PM */
-+ /* Intentionally not offloaded: */
-+ /*.channel_switch = xradio_channel_switch, */
-+ .remain_on_channel = xradio_remain_on_channel,
-+ .cancel_remain_on_channel = xradio_cancel_remain_on_channel,
-+};
-+
-+
-+/*************************************** functions ***************************************/
-+
-+static void xradio_set_ifce_comb(struct xradio_common *hw_priv,
-+ struct ieee80211_hw *hw)
-+{
-+ hw_priv->if_limits1[0].max = 1;
-+
-+ hw_priv->if_limits1[0].types = BIT(NL80211_IFTYPE_STATION);
-+ hw_priv->if_limits1[1].max = 1;
-+ hw_priv->if_limits1[1].types = BIT(NL80211_IFTYPE_AP);
-+
-+ hw_priv->if_limits2[0].max = 2;
-+ hw_priv->if_limits2[0].types = BIT(NL80211_IFTYPE_STATION);
-+
-+ hw_priv->if_limits3[0].max = 1;
-+
-+ hw_priv->if_limits3[0].types = BIT(NL80211_IFTYPE_STATION);
-+ hw_priv->if_limits3[1].max = 1;
-+ hw_priv->if_limits3[1].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
-+ BIT(NL80211_IFTYPE_P2P_GO);
-+
-+ /* TODO:COMBO: mac80211 doesn't yet support more than 1
-+ * different channel */
-+ hw_priv->if_combs[0].num_different_channels = 1;
-+ hw_priv->if_combs[0].max_interfaces = 2;
-+ hw_priv->if_combs[0].limits = hw_priv->if_limits1;
-+ hw_priv->if_combs[0].n_limits = 2;
-+
-+ hw_priv->if_combs[1].num_different_channels = 1;
-+
-+ hw_priv->if_combs[1].max_interfaces = 2;
-+ hw_priv->if_combs[1].limits = hw_priv->if_limits2;
-+ hw_priv->if_combs[1].n_limits = 1;
-+
-+ hw_priv->if_combs[2].num_different_channels = 1;
-+ hw_priv->if_combs[2].max_interfaces = 2;
-+ hw_priv->if_combs[2].limits = hw_priv->if_limits3;
-+ hw_priv->if_combs[2].n_limits = 2;
-+
-+ hw->wiphy->iface_combinations = &hw_priv->if_combs[0];
-+ hw->wiphy->n_iface_combinations = 3;
-+}
-+
-+struct ieee80211_hw *xradio_init_common(size_t hw_priv_data_len)
-+{
-+ int i;
-+ struct ieee80211_hw *hw;
-+ struct xradio_common *hw_priv;
-+ struct ieee80211_supported_band *sband;
-+ int band;
-+
-+ /* Alloc ieee_802.11 hw and xradio_common struct. */
-+ hw = ieee80211_alloc_hw(hw_priv_data_len, &xradio_ops);
-+ if (!hw)
-+ return NULL;
-+ hw_priv = hw->priv;
-+ memset(hw_priv, 0, sizeof(*hw_priv));
-+
-+ /* Initialize members of hw_priv. */
-+ hw_priv->hw = hw;
-+ hw_priv->if_id_slot = 0;
-+ hw_priv->roc_if_id = -1;
-+ atomic_set(&hw_priv->num_vifs, 0);
-+ /* initial rates and channels TODO: fetch from FW */
-+ hw_priv->rates = xradio_rates;
-+ hw_priv->mcs_rates = xradio_n_rates;
-+#ifdef ROAM_OFFLOAD
-+ hw_priv->auto_scanning = 0;
-+ hw_priv->frame_rcvd = 0;
-+ hw_priv->num_scanchannels = 0;
-+ hw_priv->num_2g_channels = 0;
-+ hw_priv->num_5g_channels = 0;
-+#endif /*ROAM_OFFLOAD*/
-+#ifdef AP_AGGREGATE_FW_FIX
-+ /* Enable block ACK for 4 TID (BE,VI,VI,VO). */
-+ hw_priv->ba_tid_mask = 0xB1; /*due to HW limitations*/
-+#else
-+ /* Enable block ACK for every TID but voice. */
-+ hw_priv->ba_tid_mask = 0x3F;
-+#endif
-+ hw_priv->noise = -94;
-+ /* hw_priv->beacon_req_id = cpu_to_le32(0); */
-+
-+ /* Initialize members of ieee80211_hw, it works in UMAC. */
-+ hw->sta_data_size = sizeof(struct xradio_sta_priv);
-+ hw->vif_data_size = sizeof(struct xradio_vif);
-+
-+ ieee80211_hw_set(hw, SIGNAL_DBM);
-+ ieee80211_hw_set(hw, SUPPORTS_PS);
-+ ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
-+ ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
-+ ieee80211_hw_set(hw, CONNECTION_MONITOR);
-+
-+/* hw->flags = IEEE80211_HW_SIGNAL_DBM |
-+ IEEE80211_HW_SUPPORTS_PS |
-+ IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
-+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
-+ IEEE80211_HW_CONNECTION_MONITOR;*/
-+ //IEEE80211_HW_SUPPORTS_CQM_RSSI |
-+ /* Aggregation is fully controlled by firmware.
-+ * Do not need any support from the mac80211 stack */
-+ /* IEEE80211_HW_AMPDU_AGGREGATION | */
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //IEEE80211_HW_SUPPORTS_P2P_PS |
-+ //IEEE80211_HW_SUPPORTS_CQM_BEACON_MISS |
-+ // IEEE80211_HW_SUPPORTS_CQM_TX_FAIL |
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ //IEEE80211_HW_BEACON_FILTER;
-+
-+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-+ BIT(NL80211_IFTYPE_ADHOC) |
-+ BIT(NL80211_IFTYPE_AP) |
-+ BIT(NL80211_IFTYPE_MESH_POINT) |
-+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
-+ BIT(NL80211_IFTYPE_P2P_GO);
-+
-+ /* Support only for limited wowlan functionalities */
-+ /* TODO by Icenowy: RESTORE THIS */
-+/* hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT;
-+ hw->wiphy->wowlan.n_patterns = 0;*/
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ /* fix the problem that driver can not set pro-resp template frame to fw */
-+ hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
-+
-+#if defined(CONFIG_XRADIO_DISABLE_BEACON_HINTS)
-+ hw->wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
-+#endif
-+ hw->wiphy->n_addresses = XRWL_MAX_VIFS;
-+ hw->wiphy->addresses = hw_priv->addresses;
-+ hw->wiphy->max_remain_on_channel_duration = 500;
-+ hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
-+ 8 /* TKIP IV */ +
-+ 12 /* TKIP ICV and MIC */;
-+ hw->wiphy->bands[NL80211_BAND_2GHZ] = &xradio_band_2ghz;
-+ hw->queues = AC_QUEUE_NUM;
-+ hw->max_rates = MAX_RATES_STAGE;
-+ hw->max_rate_tries = MAX_RATES_RETRY;
-+ /* Channel params have to be cleared before registering wiphy again */
-+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
-+ sband = hw->wiphy->bands[band];
-+ if (!sband)
-+ continue;
-+ for (i = 0; i < sband->n_channels; i++) {
-+ sband->channels[i].flags = 0;
-+ sband->channels[i].max_antenna_gain = 0;
-+ sband->channels[i].max_power = 30;
-+ }
-+ }
-+ /* hw_priv->channel init value is the local->oper_channel init value;when transplanting,take care */
-+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
-+ sband = hw->wiphy->bands[band];
-+ if (!sband)
-+ continue;
-+ if(!hw_priv->channel){
-+ hw_priv->channel = &sband->channels[2];
-+ }
-+ }
-+ hw->wiphy->max_scan_ssids = WSM_SCAN_MAX_NUM_OF_SSIDS;
-+ hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
-+ SET_IEEE80211_PERM_ADDR(hw, hw_priv->addresses[0].addr);
-+
-+ /* Initialize locks. */
-+ spin_lock_init(&hw_priv->vif_list_lock);
-+ mutex_init(&hw_priv->wsm_cmd_mux);
-+ mutex_init(&hw_priv->conf_mutex);
-+ mutex_init(&hw_priv->wsm_oper_lock);
-+ atomic_set(&hw_priv->tx_lock, 0);
-+ sema_init(&hw_priv->tx_lock_sem, 1);
-+
-+ hw_priv->workqueue = create_singlethread_workqueue(XRADIO_WORKQUEUE);
-+ sema_init(&hw_priv->scan.lock, 1);
-+ sema_init(&hw_priv->scan.status_lock,1);
-+ INIT_WORK(&hw_priv->scan.work, xradio_scan_work);
-+#ifdef ROAM_OFFLOAD
-+ INIT_WORK(&hw_priv->scan.swork, xradio_sched_scan_work);
-+#endif /*ROAM_OFFLOAD*/
-+ INIT_DELAYED_WORK(&hw_priv->scan.probe_work, xradio_probe_work);
-+ INIT_DELAYED_WORK(&hw_priv->scan.timeout, xradio_scan_timeout);
-+ INIT_DELAYED_WORK(&hw_priv->rem_chan_timeout, xradio_rem_chan_timeout);
-+ INIT_WORK(&hw_priv->tx_policy_upload_work, tx_policy_upload_work);
-+ atomic_set(&hw_priv->upload_count, 0);
-+ memset(&hw_priv->connet_time, 0, sizeof(hw_priv->connet_time));
-+
-+ spin_lock_init(&hw_priv->event_queue_lock);
-+ INIT_LIST_HEAD(&hw_priv->event_queue);
-+ INIT_WORK(&hw_priv->event_handler, xradio_event_handler);
-+ INIT_WORK(&hw_priv->ba_work, xradio_ba_work);
-+ spin_lock_init(&hw_priv->ba_lock);
-+ timer_setup(&hw_priv->ba_timer, xradio_ba_timer, 0);
-+
-+ if (unlikely(xradio_queue_stats_init(&hw_priv->tx_queue_stats,
-+ WLAN_LINK_ID_MAX,xradio_skb_dtor, hw_priv))) {
-+ ieee80211_free_hw(hw);
-+ return NULL;
-+ }
-+ for (i = 0; i < AC_QUEUE_NUM; ++i) {
-+ if (unlikely(xradio_queue_init(&hw_priv->tx_queue[i],
-+ &hw_priv->tx_queue_stats, i, XRWL_MAX_QUEUE_SZ, xradio_ttl[i]))) {
-+ for (; i > 0; i--)
-+ xradio_queue_deinit(&hw_priv->tx_queue[i - 1]);
-+ xradio_queue_stats_deinit(&hw_priv->tx_queue_stats);
-+ ieee80211_free_hw(hw);
-+ return NULL;
-+ }
-+ }
-+
-+ init_waitqueue_head(&hw_priv->channel_switch_done);
-+ init_waitqueue_head(&hw_priv->wsm_cmd_wq);
-+ init_waitqueue_head(&hw_priv->wsm_startup_done);
-+ init_waitqueue_head(&hw_priv->offchannel_wq);
-+ hw_priv->wsm_caps.firmwareReady = 0;
-+ hw_priv->driver_ready = 0;
-+ hw_priv->offchannel_done = 0;
-+ wsm_buf_init(&hw_priv->wsm_cmd_buf);
-+ spin_lock_init(&hw_priv->wsm_cmd.lock);
-+ tx_policy_init(hw_priv);
-+ xradio_init_resv_skb(hw_priv);
-+ /* add for setting short_frame_max_tx_count(mean wdev->retry_short) to drv,init the max_rate_tries */
-+ spin_lock_bh(&hw_priv->tx_policy_cache.lock);
-+ hw_priv->long_frame_max_tx_count = hw->conf.long_frame_max_tx_count;
-+ hw_priv->short_frame_max_tx_count =
-+ (hw->conf.short_frame_max_tx_count< 0x0F) ?
-+ hw->conf.short_frame_max_tx_count : 0x0F;
-+ hw_priv->hw->max_rate_tries = hw->conf.short_frame_max_tx_count;
-+ spin_unlock_bh(&hw_priv->tx_policy_cache.lock);
-+
-+ for (i = 0; i < XRWL_MAX_VIFS; i++)
-+ hw_priv->hw_bufs_used_vif[i] = 0;
-+
-+#ifdef MCAST_FWDING
-+ for (i = 0; i < WSM_MAX_BUF; i++)
-+ wsm_init_release_buffer_request(hw_priv, i);
-+ hw_priv->buf_released = 0;
-+#endif
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+
-+ hw_priv->query_packetID = 0;
-+ atomic_set(&hw_priv->query_cnt, 0);
-+ INIT_WORK(&hw_priv->query_work, wsm_query_work);
-+
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+ atomic_set(&hw_priv->suspend_state, XRADIO_RESUME);
-+#endif
-+
-+ xradio_set_ifce_comb(hw_priv, hw_priv->hw);
-+
-+ return hw;
-+}
-+
-+void xradio_free_common(struct ieee80211_hw *dev)
-+{
-+ int i;
-+ struct xradio_common *hw_priv = dev->priv;
-+
-+ cancel_work_sync(&hw_priv->query_work);
-+ del_timer_sync(&hw_priv->ba_timer);
-+ mutex_destroy(&hw_priv->wsm_oper_lock);
-+ mutex_destroy(&hw_priv->conf_mutex);
-+ mutex_destroy(&hw_priv->wsm_cmd_mux);
-+ wsm_buf_deinit(&hw_priv->wsm_cmd_buf);
-+ flush_workqueue(hw_priv->workqueue);
-+ destroy_workqueue(hw_priv->workqueue);
-+ hw_priv->workqueue = NULL;
-+
-+ xradio_deinit_resv_skb(hw_priv);
-+ if (hw_priv->skb_cache) {
-+ dev_kfree_skb(hw_priv->skb_cache);
-+ hw_priv->skb_cache = NULL;
-+ }
-+
-+ for (i = 0; i < 4; ++i)
-+ xradio_queue_deinit(&hw_priv->tx_queue[i]);
-+ xradio_queue_stats_deinit(&hw_priv->tx_queue_stats);
-+
-+ for (i = 0; i < XRWL_MAX_VIFS; i++) {
-+ kfree(hw_priv->vif_list[i]);
-+ hw_priv->vif_list[i] = NULL;
-+ }
-+
-+//fixed memory leakage by yangfh
-+#ifdef MCAST_FWDING
-+ wsm_deinit_release_buffer(hw_priv);
-+#endif
-+ /* unsigned int i; */
-+ ieee80211_free_hw(dev);
-+}
-+
-+int xradio_register_common(struct ieee80211_hw *dev)
-+{
-+ int err = 0;
-+ struct xradio_common *hw_priv = dev->priv;
-+
-+ SET_IEEE80211_DEV(dev, hw_priv->pdev);
-+ err = ieee80211_register_hw(dev);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "Cannot register device (%d).\n", err);
-+ return err;
-+ }
-+ dev_dbg(hw_priv->pdev, "is registered as '%s'\n",
-+ wiphy_name(dev->wiphy));
-+
-+ hw_priv->driver_ready = 1;
-+ wake_up(&hw_priv->wsm_startup_done);
-+ return 0;
-+}
-+
-+void xradio_unregister_common(struct ieee80211_hw *dev)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+
-+ if (wiphy_dev(dev->wiphy)) {
-+ ieee80211_unregister_hw(dev);
-+ SET_IEEE80211_DEV(dev, NULL);
-+ }
-+ hw_priv->driver_ready = 0;
-+}
-+
-+int xradio_core_init(struct sdio_func* func)
-+{
-+ int err = -ENOMEM;
-+ u16 ctrl_reg;
-+ int if_id;
-+ struct ieee80211_hw *dev;
-+ struct xradio_common *hw_priv;
-+ unsigned char randomaddr[ETH_ALEN];
-+ const unsigned char *addr = NULL;
-+
-+ //init xradio_common
-+ dev = xradio_init_common(sizeof(struct xradio_common));
-+ if (!dev) {
-+ dev_dbg(&func->dev, "xradio_init_common failed\n");
-+ return err;
-+ }
-+ hw_priv = dev->priv;
-+ hw_priv->pdev = &func->dev;
-+ hw_priv->sdio_func = func;
-+ sdio_set_drvdata(func, hw_priv);
-+
-+ // fill in mac addresses
-+ if (hw_priv->pdev->of_node) {
-+ addr = of_get_mac_address(hw_priv->pdev->of_node);
-+ }
-+ if (!addr) {
-+ dev_warn(hw_priv->pdev, "no mac address provided, using random\n");
-+ eth_random_addr(randomaddr);
-+ addr = randomaddr;
-+ }
-+ memcpy(hw_priv->addresses[0].addr, addr, ETH_ALEN);
-+ memcpy(hw_priv->addresses[1].addr, addr, ETH_ALEN);
-+ hw_priv->addresses[1].addr[5] += 0x01;
-+
-+ /*init pm and wakelock. */
-+#ifdef CONFIG_PM
-+ err = xradio_pm_init(&hw_priv->pm_state, hw_priv);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "xradio_pm_init failed(%d).\n", err);
-+ goto err2;
-+ }
-+#endif
-+ /* Register bh thread*/
-+ err = xradio_register_bh(hw_priv);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "xradio_register_bh failed(%d).\n", err);
-+ goto err3;
-+ }
-+
-+ /* Load firmware and register Interrupt Handler */
-+ err = xradio_load_firmware(hw_priv);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "xradio_load_firmware failed(%d).\n", err);
-+ goto err4;
-+ }
-+
-+ /* Set sdio blocksize. */
-+ sdio_lock(hw_priv);
-+ WARN_ON(sdio_set_blk_size(hw_priv,
-+ SDIO_BLOCK_SIZE));
-+ sdio_unlock(hw_priv);
-+
-+ if (wait_event_interruptible_timeout(hw_priv->wsm_startup_done,
-+ hw_priv->wsm_caps.firmwareReady, 3*HZ) <= 0) {
-+
-+ /* TODO: Needs to find how to reset device */
-+ /* in QUEUE mode properly. */
-+ dev_dbg(hw_priv->pdev, "Firmware Startup Timeout!\n");
-+ err = -ETIMEDOUT;
-+ goto err5;
-+ }
-+ dev_dbg(hw_priv->pdev, "Firmware Startup Done.\n");
-+
-+ /* Keep device wake up. */
-+ WARN_ON(xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, HIF_CTRL_WUP_BIT));
-+ if (xradio_reg_read_16(hw_priv,HIF_CONTROL_REG_ID, &ctrl_reg))
-+ WARN_ON(xradio_reg_read_16(hw_priv,HIF_CONTROL_REG_ID, &ctrl_reg));
-+ WARN_ON(!(ctrl_reg & HIF_CTRL_RDY_BIT));
-+
-+ /* Set device mode parameter. */
-+ for (if_id = 0; if_id < xrwl_get_nr_hw_ifaces(hw_priv); if_id++) {
-+ /* Set low-power mode. */
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, if_id));
-+ /* Enable multi-TX confirmation */
-+ WARN_ON(wsm_use_multi_tx_conf(hw_priv, true, if_id));
-+ }
-+
-+ /* Register wireless net device. */
-+ err = xradio_register_common(dev);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "xradio_register_common failed(%d)!\n", err);
-+ goto err5;
-+ }
-+
-+ return err;
-+
-+err5:
-+ xradio_dev_deinit(hw_priv);
-+err4:
-+ xradio_unregister_bh(hw_priv);
-+err3:
-+ xradio_pm_deinit(&hw_priv->pm_state);
-+err2:
-+/* err1: MRK: unused label*/
-+ xradio_free_common(dev);
-+ return err;
-+}
-+
-+void xradio_core_deinit(struct sdio_func* func)
-+{
-+ struct xradio_common* hw_priv = sdio_get_drvdata(func);
-+ if (hw_priv) {
-+ xradio_unregister_common(hw_priv->hw);
-+ xradio_dev_deinit(hw_priv);
-+ xradio_unregister_bh(hw_priv);
-+ xradio_pm_deinit(&hw_priv->pm_state);
-+ xradio_free_common(hw_priv->hw);
-+ }
-+ return;
-+}
-diff --git a/drivers/net/wireless/xradio/main.h b/drivers/net/wireless/xradio/main.h
-new file mode 100644
-index 0000000..2238d75
---- /dev/null
-+++ b/drivers/net/wireless/xradio/main.h
-@@ -0,0 +1,7 @@
-+#ifndef __XRADIO_MAIN_H
-+#define __XRADIO_MAIN_H
-+
-+int xradio_core_init(struct sdio_func* func);
-+void xradio_core_deinit(struct sdio_func* func);
-+
-+#endif
-\ No newline at end of file
-diff --git a/drivers/net/wireless/xradio/module.c b/drivers/net/wireless/xradio/module.c
-new file mode 100644
-index 0000000..2a41c75
---- /dev/null
-+++ b/drivers/net/wireless/xradio/module.c
-@@ -0,0 +1,27 @@
-+#include
-+
-+#include "xradio.h"
-+#include "debug.h"
-+#include "sdio.h"
-+
-+MODULE_AUTHOR("XRadioTech");
-+MODULE_DESCRIPTION("XRadioTech WLAN driver core");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("xradio_core");
-+
-+/* Init Module function -> Called by insmod */
-+static int __init xradio_core_entry(void)
-+{
-+ int ret = 0;
-+ ret = xradio_sdio_register();
-+ return ret;
-+}
-+
-+/* Called at Driver Unloading */
-+static void __exit xradio_core_exit(void)
-+{
-+ xradio_sdio_unregister();
-+}
-+
-+module_init(xradio_core_entry);
-+module_exit(xradio_core_exit);
-diff --git a/drivers/net/wireless/xradio/p2p.c b/drivers/net/wireless/xradio/p2p.c
-new file mode 100644
-index 0000000..f32fb43
---- /dev/null
-+++ b/drivers/net/wireless/xradio/p2p.c
-@@ -0,0 +1,62 @@
-+#include "xradio.h"
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+///w, TES_P2P_0002 WorkAround:
-+///w, P2P GO Neg Process and P2P FIND may be collision.
-+///w, When P2P Device is waiting for GO NEG CFM in 30ms,
-+///w, P2P FIND may end with p2p listen, and then goes to p2p search.
-+///w, Then xradio scan will occupy phy on other channel in 3+ seconds.
-+///w, P2P Device will not be able to receive the GO NEG CFM.
-+///w, We extend the roc period to remaind phy to receive GO NEG CFM as WorkAround.
-+
-+s32 TES_P2P_0002_roc_dur;
-+s32 TES_P2P_0002_roc_sec;
-+s32 TES_P2P_0002_roc_usec;
-+u32 TES_P2P_0002_packet_id;
-+u32 TES_P2P_0002_state = TES_P2P_0002_STATE_IDLE;
-+
-+void xradio_frame_monitor(struct xradio_common *hw_priv, struct sk_buff *skb, bool tx) {
-+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-+
-+ u8 *action = (u8*)&mgmt->u.action.category;
-+ u8 *category_code = &(action[0]);
-+ u8 *action_code = &(action[1]);
-+ u8 *oui = &(action[2]);
-+ u8 *subtype = &(action[5]);
-+ u8 *oui_subtype = &(action[6]);
-+
-+
-+ if(ieee80211_is_action(frame->frame_control)) {
-+ if( *category_code == WLAN_CATEGORY_PUBLIC) {
-+ if (*action_code == 0x09) {
-+ if((oui[0] == 0x50) && (oui[1] == 0x6F) &&
-+ (oui[2] == 0x9A) && (*subtype == 0x09)) {
-+ if ( *oui_subtype == 0x01 ) { ///w, GO Negotiation Response
-+ if((TES_P2P_0002_state == TES_P2P_0002_STATE_IDLE) &&
-+ (tx == true)) { ///w, p2p atturbute:status,id=0
-+ u8 *go_neg_resp_res = &(action[17]);
-+ if (*go_neg_resp_res == 0x0) {
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_SEND_RESP;
-+ txrx_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_SEND_RESP]\n");
-+ }
-+ }
-+ } else if ( *oui_subtype == 0x02 ) { ///w, GO Negotiation Confirmation
-+ if( tx == false ) {
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_IDLE;
-+ txrx_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_IDLE]"
-+ "[GO Negotiation Confirmation]\n");
-+ }
-+ } else if ( *oui_subtype == 0x08 ) { ///w, Provision Discovery Response
-+ if(tx == false) {
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_IDLE;
-+ txrx_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_IDLE]"
-+ "[Provision Discovery Response]\n");
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+}
-+#endif
-\ No newline at end of file
-diff --git a/drivers/net/wireless/xradio/p2p.h b/drivers/net/wireless/xradio/p2p.h
-new file mode 100644
-index 0000000..d86686b
---- /dev/null
-+++ b/drivers/net/wireless/xradio/p2p.h
-@@ -0,0 +1,6 @@
-+#ifndef XRADIO_P2P_H
-+#define XRADIO_P2P_H
-+
-+void xradio_frame_monitor(struct xradio_common *hw_priv, struct sk_buff *skb, bool tx);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/pm.c b/drivers/net/wireless/xradio/pm.c
-new file mode 100644
-index 0000000..488c26c
---- /dev/null
-+++ b/drivers/net/wireless/xradio/pm.c
-@@ -0,0 +1,800 @@
-+/*
-+ * PM implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include "xradio.h"
-+#include "pm.h"
-+#include "sta.h"
-+#include "bh.h"
-+#include "sdio.h"
-+
-+#define XRADIO_BEACON_SKIPPING_MULTIPLIER 3
-+
-+struct xradio_udp_port_filter {
-+ struct wsm_udp_port_filter_hdr hdr;
-+ struct wsm_udp_port_filter dhcp;
-+ struct wsm_udp_port_filter upnp;
-+} __packed;
-+
-+struct xradio_ether_type_filter {
-+ struct wsm_ether_type_filter_hdr hdr;
-+ struct wsm_ether_type_filter ip;
-+ struct wsm_ether_type_filter pae;
-+ struct wsm_ether_type_filter wapi;
-+} __packed;
-+
-+static struct xradio_udp_port_filter xradio_udp_port_filter_on = {
-+ .hdr.nrFilters = 2,
-+ .dhcp = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_OUT,
-+ .portType = WSM_FILTER_PORT_TYPE_DST,
-+ .udpPort = __cpu_to_le16(67),
-+ },
-+ .upnp = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_OUT,
-+ .portType = WSM_FILTER_PORT_TYPE_DST,
-+ .udpPort = __cpu_to_le16(1900),
-+ },
-+ /* Please add other known ports to be filtered out here and
-+ * update nrFilters field in the header.
-+ * Up to 4 filters are allowed. */
-+};
-+
-+static struct wsm_udp_port_filter_hdr xradio_udp_port_filter_off = {
-+ .nrFilters = 0,
-+};
-+
-+#ifndef ETH_P_WAPI
-+#define ETH_P_WAPI 0x88B4
-+#endif
-+
-+#ifdef TES_P2P_000B_DISABLE_EAPOL_FILTER
-+/* TES_P2P_000B WorkAround:
-+ * when the link keep 10min more or less(i am not sure),
-+ * wpa_s session maybe expired, and want to update group key.
-+ * it will use eapol frame(802.1x,0x888E).
-+ * if driver suspend, and discard eapol frame, then session end.
-+ * i don't know why original code discards eapol frame in suspend.
-+ * but now make this filter disable as WorkAround. wzw */
-+static struct xradio_ether_type_filter xradio_ether_type_filter_on = {
-+ .hdr.nrFilters = 1,
-+/* .ip = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_IP),
-+ },*/
-+/* .pae = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_PAE),
-+ },*/
-+ .wapi = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_WAPI),
-+ },
-+ /* Please add other known ether types to be filtered out here and
-+ * update nrFilters field in the header.
-+ * Up to 4 filters are allowed. */
-+};
-+#else
-+static struct xradio_ether_type_filter xradio_ether_type_filter_on = {
-+ .hdr.nrFilters = 2,
-+/* .ip = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_IP),
-+ },*/
-+ .pae = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_PAE),
-+ },
-+ .wapi = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_WAPI),
-+ },
-+ /* Please add other known ether types to be filtered out here and
-+ * update nrFilters field in the header.
-+ * Up to 4 filters are allowed. */
-+};
-+#endif
-+
-+static struct wsm_ether_type_filter_hdr xradio_ether_type_filter_off = {
-+ .nrFilters = 0,
-+};
-+
-+static int xradio_suspend_late(struct device *dev);
-+static void xradio_pm_release(struct device *dev);
-+static int xradio_pm_probe(struct platform_device *pdev);
-+static int __xradio_wow_suspend(struct xradio_vif *priv,
-+ struct cfg80211_wowlan *wowlan);
-+static int __xradio_wow_resume(struct xradio_vif *priv);
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+static int xradio_poweroff_suspend(struct xradio_common *hw_priv);
-+static int xradio_poweroff_resume(struct xradio_common *hw_priv);
-+#endif
-+
-+
-+/* private */
-+struct xradio_suspend_state {
-+ unsigned long bss_loss_tmo;
-+ unsigned long connection_loss_tmo;
-+ unsigned long join_tmo;
-+ unsigned long direct_probe;
-+ unsigned long link_id_gc;
-+ bool beacon_skipping;
-+};
-+
-+static const struct dev_pm_ops xradio_pm_ops = {
-+ .suspend_noirq = xradio_suspend_late,
-+};
-+
-+static struct platform_driver xradio_power_driver = {
-+ .probe = xradio_pm_probe,
-+ .driver = {
-+ .name = XRADIO_PM_DEVICE,
-+ .pm = &xradio_pm_ops,
-+ },
-+};
-+
-+static int xradio_pm_init_common(struct xradio_pm_state *pm,
-+ struct xradio_common *hw_priv)
-+{
-+ int ret;
-+ pm_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+
-+ spin_lock_init(&pm->lock);
-+ /* Register pm driver. */
-+ ret = platform_driver_register(&xradio_power_driver);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_ERROR, "%s:platform_driver_register failed(%d)!\n",
-+ __FUNCTION__, ret);
-+ return ret;
-+ }
-+
-+ /* Add pm device. */
-+ pm->pm_dev = platform_device_alloc(XRADIO_PM_DEVICE, 0);
-+ if (!pm->pm_dev) {
-+ pm_printk(XRADIO_DBG_ERROR, "%s:platform_device_alloc failed!\n",
-+ __FUNCTION__);
-+ platform_driver_unregister(&xradio_power_driver);
-+ return -ENOMEM;
-+ }
-+ pm->pm_dev->dev.platform_data = hw_priv;
-+ ret = platform_device_add(pm->pm_dev);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_ERROR, "%s:platform_device_add failed(%d)!\n",
-+ __FUNCTION__, ret);
-+ platform_driver_unregister(&xradio_power_driver);
-+ kfree(pm->pm_dev);
-+ pm->pm_dev = NULL;
-+ }
-+
-+ return ret;
-+}
-+
-+static void xradio_pm_deinit_common(struct xradio_pm_state *pm)
-+{
-+ pm_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+ platform_driver_unregister(&xradio_power_driver);
-+ if (pm->pm_dev) {
-+ pm->pm_dev->dev.platform_data = NULL;
-+ platform_device_unregister(pm->pm_dev); /* kfree is already do */
-+ pm->pm_dev = NULL;
-+ }
-+}
-+
-+#ifdef CONFIG_WAKELOCK
-+
-+int xradio_pm_init(struct xradio_pm_state *pm,
-+ struct xradio_common *hw_priv)
-+{
-+ int ret = 0;
-+ pm_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+
-+ ret = xradio_pm_init_common(pm, hw_priv);
-+ if (!ret)
-+ wake_lock_init(&pm->wakelock, WAKE_LOCK_SUSPEND, XRADIO_WAKE_LOCK);
-+ else
-+ pm_printk(XRADIO_DBG_ERROR,"xradio_pm_init_common failed!\n");
-+ return ret;
-+}
-+
-+void xradio_pm_deinit(struct xradio_pm_state *pm)
-+{
-+ pm_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+ if (wake_lock_active(&pm->wakelock))
-+ wake_unlock(&pm->wakelock);
-+ wake_lock_destroy(&pm->wakelock);
-+ xradio_pm_deinit_common(pm);
-+}
-+
-+void xradio_pm_stay_awake(struct xradio_pm_state *pm,
-+ unsigned long tmo)
-+{
-+ long cur_tmo;
-+ pm_printk(XRADIO_DBG_MSG,"%s\n", __FUNCTION__);
-+
-+ spin_lock_bh(&pm->lock);
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
-+ cur_tmo = pm->wakelock.ws.timer.expires - jiffies;
-+#else
-+ cur_tmo = pm->wakelock.expires - jiffies;
-+#endif
-+ if (!wake_lock_active(&pm->wakelock) || cur_tmo < (long)tmo)
-+ wake_lock_timeout(&pm->wakelock, tmo);
-+ spin_unlock_bh(&pm->lock);
-+}
-+void xradio_pm_lock_awake(struct xradio_pm_state *pm)
-+{
-+
-+ spin_lock_bh(&pm->lock);
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
-+ pm->expires_save = pm->wakelock.ws.timer.expires;
-+#else
-+ pm->expires_save = pm->wakelock.expires;
-+#endif
-+ wake_lock_timeout(&pm->wakelock, LONG_MAX);
-+ spin_unlock_bh(&pm->lock);
-+}
-+void xradio_pm_unlock_awake(struct xradio_pm_state *pm)
-+{
-+
-+ spin_lock_bh(&pm->lock);
-+ pm->expires_save -= jiffies;
-+ if (pm->expires_save)
-+ wake_lock_timeout(&pm->wakelock, pm->expires_save);
-+ else
-+ wake_lock_timeout(&pm->wakelock, 1);
-+ spin_unlock_bh(&pm->lock);
-+}
-+
-+#else /* CONFIG_WAKELOCK */
-+
-+static void xradio_pm_stay_awake_tmo(struct timer_list *t)
-+{
-+ struct xradio_pm_state *pm = from_timer(pm, t, stay_awake);
-+ (void)pm;
-+}
-+
-+int xradio_pm_init(struct xradio_pm_state *pm,
-+ struct xradio_common *hw_priv)
-+{
-+ int ret = 0;
-+ pm_printk(XRADIO_DBG_MSG,"%s\n", __FUNCTION__);
-+
-+ ret = xradio_pm_init_common(pm, hw_priv);
-+ if (!ret) {
-+ timer_setup(&pm->stay_awake, xradio_pm_stay_awake_tmo, 0);
-+ } else
-+ pm_printk(XRADIO_DBG_ERROR,"xradio_pm_init_common failed!\n");
-+ return ret;
-+}
-+
-+void xradio_pm_deinit(struct xradio_pm_state *pm)
-+{
-+ del_timer_sync(&pm->stay_awake);
-+ xradio_pm_deinit_common(pm);
-+}
-+
-+void xradio_pm_stay_awake(struct xradio_pm_state *pm,
-+ unsigned long tmo)
-+{
-+ long cur_tmo;
-+
-+ spin_lock_bh(&pm->lock);
-+ cur_tmo = pm->stay_awake.expires - jiffies;
-+ if (!timer_pending(&pm->stay_awake) || cur_tmo < (long)tmo)
-+ mod_timer(&pm->stay_awake, jiffies + tmo);
-+ spin_unlock_bh(&pm->lock);
-+}
-+void xradio_pm_lock_awake(struct xradio_pm_state *pm)
-+{
-+
-+ spin_lock_bh(&pm->lock);
-+ pm->expires_save = pm->stay_awake.expires;
-+ mod_timer(&pm->stay_awake, jiffies + LONG_MAX);
-+ spin_unlock_bh(&pm->lock);
-+}
-+void xradio_pm_unlock_awake(struct xradio_pm_state *pm)
-+{
-+
-+ spin_lock_bh(&pm->lock);
-+ if (time_before(jiffies, pm->expires_save))
-+ mod_timer(&pm->stay_awake, pm->expires_save);
-+ else
-+ mod_timer(&pm->stay_awake, jiffies + 1);
-+ spin_unlock_bh(&pm->lock);
-+}
-+#endif /* CONFIG_WAKELOCK */
-+
-+static long xradio_suspend_work(struct delayed_work *work)
-+{
-+ int ret = cancel_delayed_work(work);
-+ long tmo;
-+ pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
-+
-+ if (ret > 0) {
-+ /* Timer is pending */
-+ tmo = work->timer.expires - jiffies;
-+ if (tmo < 0)
-+ tmo = 0;
-+ } else {
-+ tmo = -1;
-+ }
-+ return tmo;
-+}
-+
-+static int xradio_resume_work(struct xradio_common *hw_priv,
-+ struct delayed_work *work,
-+ unsigned long tmo)
-+{
-+ pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
-+ if ((long)tmo < 0)
-+ return 1;
-+
-+ return queue_delayed_work(hw_priv->workqueue, work, tmo);
-+}
-+
-+static int xradio_suspend_late(struct device *dev)
-+{
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+ struct xradio_common *hw_priv = dev->platform_data;
-+
-+ if (XRADIO_POWEROFF_SUSP == atomic_read(&hw_priv->suspend_state)) {
-+ return 0; /* we don't rx data when power down wifi.*/
-+ }
-+#endif
-+
-+ //if (atomic_read(&hw_priv->bh_rx)) {
-+ // pm_printk(XRADIO_DBG_WARN, "%s: Suspend interrupted.\n", __func__);
-+ // return -EAGAIN;
-+ //}
-+ return 0;
-+}
-+
-+static void xradio_pm_release(struct device *dev)
-+{
-+ pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
-+}
-+
-+static int xradio_pm_probe(struct platform_device *pdev)
-+{
-+ pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
-+ pdev->dev.release = xradio_pm_release;
-+ return 0;
-+}
-+
-+int xradio_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv;
-+ int i, ret = 0;
-+
-+
-+ if(hw_priv->bh_error) return -EBUSY;
-+ WARN_ON(!atomic_read(&hw_priv->num_vifs));
-+
-+ if (work_pending(&hw_priv->query_work))
-+ return -EBUSY;
-+
-+#ifdef ROAM_OFFLOAD
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ if((priv->vif->type == NL80211_IFTYPE_STATION)
-+ && (priv->join_status == XRADIO_JOIN_STATUS_STA)) {
-+ down(&hw_priv->scan.lock);
-+ hw_priv->scan.if_id = priv->if_id;
-+ xradio_sched_scan_work(&hw_priv->scan.swork);
-+ }
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+
-+ /* Do not suspend when datapath is not idle */
-+ if (hw_priv->tx_queue_stats.num_queued[0] +
-+ hw_priv->tx_queue_stats.num_queued[1]) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of tx_queue is not empty.\n");
-+ return -EBUSY;
-+ }
-+
-+ /* Make sure there is no configuration requests in progress. */
-+ if (!mutex_trylock(&hw_priv->conf_mutex)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of configuration requests.\n");
-+ return -EBUSY;
-+ }
-+
-+ /* Make sure there is no wsm_oper_lock in progress. */
-+ if (!mutex_trylock(&hw_priv->wsm_oper_lock)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of wsm_oper_lock.\n");
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return -EBUSY;
-+ }
-+
-+ /* Do not suspend when scanning or ROC*/
-+ if (down_trylock(&hw_priv->scan.lock)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of scan requests.\n");
-+ goto revert1;
-+ }
-+
-+ if (delayed_work_pending(&hw_priv->scan.probe_work)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of probe frames tx in progress.\n");
-+ goto revert2;
-+ }
-+
-+ /* Lock TX. */
-+ wsm_lock_tx_async(hw_priv);
-+
-+ /* Wait to avoid possible race with bh code.
-+ * But do not wait too long... */
-+ if (wait_event_timeout(hw_priv->bh_evt_wq,
-+ !hw_priv->hw_bufs_used, HZ / 10) <= 0) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of there are frames not confirm.\n");
-+ goto revert3;
-+ }
-+
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+// if (STANDBY_WITH_POWER_OFF == standby_level) {
-+ if (1) {
-+ return xradio_poweroff_suspend(hw_priv);
-+ }
-+#endif
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+
-+ ret = __xradio_wow_suspend(priv, wowlan);
-+ if (ret) {
-+ for (; i >= 0; i--) {
-+ if (!hw_priv->vif_list[i])
-+ continue;
-+ priv = (struct xradio_vif *)hw_priv->vif_list[i]->drv_priv;
-+ __xradio_wow_resume(priv);
-+ }
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of __xradio_wow_suspend failed!\n");
-+ goto revert3;
-+ }
-+ }
-+
-+ /* Stop serving thread */
-+ if (xradio_bh_suspend(hw_priv)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of xradio_bh_suspend failed!\n");
-+ xradio_wow_resume(hw);
-+ return -EBUSY;
-+ }
-+
-+ /* Enable IRQ wake */
-+ ret = sdio_pm(hw_priv, true);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend sbus pm failed\n");
-+ xradio_wow_resume(hw);
-+ return -EBUSY;
-+ }
-+
-+ /* Force resume if event is coming from the device. */
-+ //if (atomic_read(&hw_priv->bh_rx)) {
-+ // pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ // "because of recieved rx event!\n");
-+ // xradio_wow_resume(hw);
-+ // return -EAGAIN;
-+ //}
-+ return 0;
-+
-+revert3:
-+ wsm_unlock_tx(hw_priv);
-+revert2:
-+ up(&hw_priv->scan.lock);
-+revert1:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ mutex_unlock(&hw_priv->wsm_oper_lock);
-+ return -EBUSY;
-+}
-+
-+static int __xradio_wow_suspend(struct xradio_vif *priv,
-+ struct cfg80211_wowlan *wowlan)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct xradio_pm_state_vif *pm_state_vif = &priv->pm_state_vif;
-+ struct xradio_suspend_state *state;
-+ int ret;
-+#ifdef MCAST_FWDING
-+ struct wsm_forwarding_offload fwdoffload = {
-+ .fwenable = 0x1,
-+ .flags = 0x1,
-+ };
-+#endif
-+
-+
-+ /* Do not suspend when join work is scheduled */
-+ if (work_pending(&priv->join_work)) {
-+ pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
-+ "when join work is scheduled\n", __func__);
-+ goto revert1;
-+ }
-+
-+ /* Set UDP filter */
-+ wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_on.hdr,
-+ priv->if_id);
-+
-+ /* Set ethernet frame type filter */
-+ wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_on.hdr,
-+ priv->if_id);
-+
-+ /* Set IP multicast filter */
-+ wsm_set_host_sleep(hw_priv, 1, priv->if_id);
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_keepalive_filter(priv, true));
-+
-+#ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
-+ /* Set Multicast Address Filter */
-+ if (priv->multicast_filter.numOfAddresses) {
-+ priv->multicast_filter.enable = 1;
-+ wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id);
-+ }
-+
-+ /* Set Enable Broadcast Address Filter */
-+ priv->broadcast_filter.action_mode = 1;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ priv->broadcast_filter.address_mode = 3;
-+
-+ xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
-+#endif
-+
-+#ifdef MCAST_FWDING
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload,priv->if_id));
-+#endif
-+
-+ /* Allocate state */
-+ state = kzalloc(sizeof(struct xradio_suspend_state), GFP_KERNEL);
-+ if (!state) {
-+ pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
-+ "alloc xradio_suspend_state failed.\n", __func__);
-+ goto revert2;
-+ }
-+ /* Store delayed work states. */
-+ state->bss_loss_tmo = xradio_suspend_work(&priv->bss_loss_work);
-+ state->connection_loss_tmo = xradio_suspend_work(&priv->connection_loss_work);
-+ state->join_tmo = xradio_suspend_work(&priv->join_timeout);
-+ state->link_id_gc = xradio_suspend_work(&priv->link_id_gc_work);
-+
-+ /* Enable beacon skipping */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA &&
-+ priv->join_dtim_period && !priv->has_multicast_subscription) {
-+ state->beacon_skipping = true;
-+ wsm_set_beacon_wakeup_period(hw_priv, priv->join_dtim_period,
-+ XRADIO_BEACON_SKIPPING_MULTIPLIER * \
-+ priv->join_dtim_period, priv->if_id);
-+ }
-+
-+ ret = timer_pending(&priv->mcast_timeout);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
-+ "mcast timeout timer_pending failed.\n", __func__);
-+ goto revert3;
-+ }
-+
-+ /* Store suspend state */
-+ pm_state_vif->suspend_state = state;
-+
-+ return 0;
-+
-+revert3:
-+ xradio_resume_work(hw_priv, &priv->bss_loss_work, state->bss_loss_tmo);
-+ xradio_resume_work(hw_priv, &priv->connection_loss_work,
-+ state->connection_loss_tmo);
-+ xradio_resume_work(hw_priv, &priv->join_timeout, state->join_tmo);
-+ xradio_resume_work(hw_priv, &priv->link_id_gc_work, state->link_id_gc);
-+ kfree(state);
-+
-+revert2:
-+ wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_off, priv->if_id);
-+ wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_off, priv->if_id);
-+ wsm_set_host_sleep(hw_priv, 0, priv->if_id);
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_keepalive_filter(priv, false));
-+
-+#ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
-+ /* Set Multicast Address Filter */
-+ if (priv->multicast_filter.numOfAddresses) {
-+ priv->multicast_filter.enable = 0;
-+ wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id);
-+ }
-+
-+ /* Set Enable Broadcast Address Filter */
-+ priv->broadcast_filter.action_mode = 0;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ priv->broadcast_filter.address_mode = 0;
-+ xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
-+#endif
-+
-+#ifdef MCAST_FWDING
-+ fwdoffload.flags = 0x0;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload,priv->if_id));
-+#endif
-+
-+revert1:
-+ /* mutex_unlock(&hw_priv->conf_mutex); */
-+ return -EBUSY;
-+}
-+
-+int xradio_wow_resume(struct ieee80211_hw *hw)
-+{
-+
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv;
-+ int i, ret = 0;
-+
-+
-+ WARN_ON(!atomic_read(&hw_priv->num_vifs));
-+ if(hw_priv->bh_error) return 0;
-+
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+ if (XRADIO_POWEROFF_SUSP == atomic_read(&hw_priv->suspend_state)) {
-+ return xradio_poweroff_resume(hw_priv);
-+ }
-+#endif
-+
-+ /* Disable IRQ wake */
-+ sdio_pm(hw_priv, false);
-+
-+ up(&hw_priv->scan.lock);
-+
-+ /* Resume BH thread */
-+ WARN_ON(xradio_bh_resume(hw_priv));
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ ret = __xradio_wow_resume(priv);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_ERROR, "%s:__xradio_wow_resume failed!\n", __func__);
-+ break;
-+ }
-+ }
-+
-+ wsm_unlock_tx(hw_priv);
-+
-+ /* Unlock configuration mutex */
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ mutex_unlock(&hw_priv->wsm_oper_lock);
-+
-+ return ret;
-+}
-+
-+static int __xradio_wow_resume(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct xradio_pm_state_vif *pm_state_vif = &priv->pm_state_vif;
-+ struct xradio_suspend_state *state;
-+#ifdef MCAST_FWDING
-+ struct wsm_forwarding_offload fwdoffload = {
-+ .fwenable = 0x1,
-+ .flags = 0x0,
-+ };
-+#endif
-+
-+
-+ /* Restore suspend state */
-+ state = pm_state_vif->suspend_state;
-+ pm_state_vif->suspend_state = NULL;
-+
-+#ifdef ROAM_OFFLOAD
-+ if((priv->vif->type == NL80211_IFTYPE_STATION)
-+ && (priv->join_status == XRADIO_JOIN_STATUS_STA))
-+ xradio_hw_sched_scan_stop(hw_priv);
-+#endif /*ROAM_OFFLOAD*/
-+
-+ if (state->beacon_skipping) {
-+#ifdef XRADIO_USE_LONG_DTIM_PERIOD
-+ int join_dtim_period_extend;
-+ if (priv->join_dtim_period <= 3) {
-+ join_dtim_period_extend = priv->join_dtim_period * 3;
-+ } else if (priv->join_dtim_period <= 5) {
-+ join_dtim_period_extend = priv->join_dtim_period * 2;
-+ } else {
-+ join_dtim_period_extend = priv->join_dtim_period;
-+ }
-+ wsm_set_beacon_wakeup_period(hw_priv,
-+ ((priv->beacon_int * join_dtim_period_extend) > MAX_BEACON_SKIP_TIME_MS ?
-+ 1 : join_dtim_period_extend) , 0, priv->if_id);
-+#else
-+ wsm_set_beacon_wakeup_period(hw_priv, priv->beacon_int *
-+ (priv->join_dtim_period > MAX_BEACON_SKIP_TIME_MS ? 1 : priv->join_dtim_period),
-+ 0, priv->if_id);
-+#endif
-+ state->beacon_skipping = false;
-+ }
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_keepalive_filter(priv, false));
-+
-+#ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
-+ /* Set Multicast Address Filter */
-+ if (priv->multicast_filter.numOfAddresses) {
-+ priv->multicast_filter.enable = 0;
-+ wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id);
-+ }
-+ /* Set Enable Broadcast Address Filter */
-+ priv->broadcast_filter.action_mode = 0;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ priv->broadcast_filter.address_mode = 0;
-+ xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
-+#endif
-+
-+#ifdef MCAST_FWDING
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload,priv->if_id));
-+#endif
-+
-+ /* Resume delayed work */
-+ xradio_resume_work(hw_priv, &priv->bss_loss_work, state->bss_loss_tmo);
-+ xradio_resume_work(hw_priv, &priv->connection_loss_work,
-+ state->connection_loss_tmo);
-+ xradio_resume_work(hw_priv, &priv->join_timeout, state->join_tmo);
-+ xradio_resume_work(hw_priv, &priv->link_id_gc_work, state->link_id_gc);
-+
-+ /* Remove UDP port filter */
-+ wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_off, priv->if_id);
-+
-+ /* Remove ethernet frame type filter */
-+ wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_off, priv->if_id);
-+
-+ /* Remove IP multicast filter */
-+ wsm_set_host_sleep(hw_priv, 0, priv->if_id);
-+ /* Free memory */
-+ kfree(state);
-+
-+ return 0;
-+}
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+static int xradio_poweroff_suspend(struct xradio_common *hw_priv)
-+{
-+
-+ //flush all work.
-+ cancel_work_sync(&hw_priv->query_work);
-+ flush_workqueue(hw_priv->workqueue);
-+ /* Schedule hardware restart, ensure no cmds in progress.*/
-+ mutex_lock(&hw_priv->wsm_cmd_mux);
-+ atomic_set(&hw_priv->suspend_state, XRADIO_POWEROFF_SUSP);
-+ //hw_priv->hw_restart = true;
-+ mutex_unlock(&hw_priv->wsm_cmd_mux);
-+ /* Stop serving thread */
-+ if (xradio_bh_suspend(hw_priv)) {
-+ pm_printk(XRADIO_DBG_WARN, "%s, xradio_bh_suspend failed!\n", __func__);
-+ return -EBUSY;
-+ }
-+
-+ return 0;
-+}
-+
-+static int xradio_poweroff_resume(struct xradio_common *hw_priv)
-+{
-+
-+ /* Revert locks */
-+ wsm_unlock_tx(hw_priv);
-+ up(&hw_priv->scan.lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ mutex_unlock(&hw_priv->wsm_oper_lock);
-+ //if (schedule_work(&hw_priv->hw_restart_work) <= 0)
-+ // pm_printk(XRADIO_DBG_ERROR, "%s restart_work failed!\n", __func__);
-+ return 0;
-+}
-+#endif
-diff --git a/drivers/net/wireless/xradio/pm.h b/drivers/net/wireless/xradio/pm.h
-new file mode 100644
-index 0000000..6443cbc
---- /dev/null
-+++ b/drivers/net/wireless/xradio/pm.h
-@@ -0,0 +1,64 @@
-+/*
-+ * power management interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#ifndef PM_H_INCLUDED
-+#define PM_H_INCLUDED
-+
-+#ifdef CONFIG_WAKELOCK
-+#include
-+#endif
-+
-+/* ******************************************************************** */
-+/* mac80211 API */
-+
-+#ifdef CONFIG_PM
-+
-+#define XRADIO_PM_DEVICE "xradio_pm"
-+#define XRADIO_WAKE_LOCK "xradio_wlan"
-+
-+/* extern */ struct xradio_common;
-+ /* private */ struct xradio_suspend_state;
-+
-+struct xradio_pm_state {
-+#ifdef CONFIG_WAKELOCK
-+ struct wake_lock wakelock;
-+#else
-+ struct timer_list stay_awake;
-+#endif
-+ struct platform_device *pm_dev;
-+ spinlock_t lock;
-+ unsigned long expires_save;
-+};
-+
-+struct xradio_pm_state_vif {
-+ struct xradio_suspend_state *suspend_state;
-+};
-+
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+enum suspend_state {
-+ XRADIO_RESUME = 0,
-+ XRADIO_CONNECT_SUSP,
-+ XRADIO_DISCONNECT_SUSP,
-+ XRADIO_POWEROFF_SUSP
-+};
-+#endif
-+int xradio_pm_init(struct xradio_pm_state *pm, struct xradio_common *priv);
-+void xradio_pm_deinit(struct xradio_pm_state *pm);
-+void xradio_pm_stay_awake(struct xradio_pm_state *pm, unsigned long tmo);
-+void xradio_pm_lock_awake(struct xradio_pm_state *pm);
-+void xradio_pm_unlock_awake(struct xradio_pm_state *pm);
-+int xradio_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
-+int xradio_wow_resume(struct ieee80211_hw *hw);
-+
-+#endif /* CONFIG_PM */
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/queue.c b/drivers/net/wireless/xradio/queue.c
-new file mode 100644
-index 0000000..e4b00ea
---- /dev/null
-+++ b/drivers/net/wireless/xradio/queue.c
-@@ -0,0 +1,820 @@
-+/*
-+ * Queue implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include "xradio.h"
-+#include "queue.h"
-+
-+/* private */ struct xradio_queue_item
-+{
-+ struct list_head head;
-+ struct sk_buff *skb;
-+ u32 packetID;
-+ unsigned long queue_timestamp;
-+ unsigned long xmit_timestamp;
-+ struct xradio_txpriv txpriv;
-+ u8 generation;
-+ u8 pack_stk_wr;
-+};
-+
-+static inline void __xradio_queue_lock(struct xradio_queue *queue)
-+{
-+ struct xradio_queue_stats *stats = queue->stats;
-+ if (queue->tx_locked_cnt++ == 0) {
-+ txrx_printk(XRADIO_DBG_MSG, "[TX] Queue %d is locked.\n",
-+ queue->queue_id);
-+ ieee80211_stop_queue(stats->hw_priv->hw, queue->queue_id);
-+ }
-+}
-+
-+static inline void __xradio_queue_unlock(struct xradio_queue *queue)
-+{
-+ struct xradio_queue_stats *stats = queue->stats;
-+ BUG_ON(!queue->tx_locked_cnt);
-+ if (--queue->tx_locked_cnt == 0) {
-+ txrx_printk(XRADIO_DBG_MSG, "[TX] Queue %d is unlocked.\n",
-+ queue->queue_id);
-+ ieee80211_wake_queue(stats->hw_priv->hw, queue->queue_id);
-+ }
-+}
-+
-+static inline void xradio_queue_parse_id(u32 packetID, u8 *queue_generation,
-+ u8 *queue_id,
-+ u8 *item_generation,
-+ u8 *item_id,
-+ u8 *if_id,
-+ u8 *link_id)
-+{
-+ *item_id = (packetID >> 0) & 0xFF;
-+ *item_generation = (packetID >> 8) & 0xFF;
-+ *queue_id = (packetID >> 16) & 0xF;
-+ *if_id = (packetID >> 20) & 0xF;
-+ *link_id = (packetID >> 24) & 0xF;
-+ *queue_generation = (packetID >> 28) & 0xF;
-+}
-+
-+static inline u32 xradio_queue_make_packet_id(u8 queue_generation, u8 queue_id,
-+ u8 item_generation, u8 item_id,
-+ u8 if_id, u8 link_id)
-+{
-+ /*TODO:COMBO: Add interfaceID to the packetID */
-+ return ((u32)item_id << 0) |
-+ ((u32)item_generation << 8) |
-+ ((u32)queue_id << 16) |
-+ ((u32)if_id << 20) |
-+ ((u32)link_id << 24) |
-+ ((u32)queue_generation << 28);
-+}
-+
-+static void xradio_queue_post_gc(struct xradio_queue_stats *stats,
-+ struct list_head *gc_list)
-+{
-+ struct xradio_queue_item *item;
-+
-+ while (!list_empty(gc_list)) {
-+ item = list_first_entry(
-+ gc_list, struct xradio_queue_item, head);
-+ list_del(&item->head);
-+ stats->skb_dtor(stats->hw_priv, item->skb, &item->txpriv);
-+ kfree(item);
-+ }
-+}
-+
-+static void xradio_queue_register_post_gc(struct list_head *gc_list,
-+ struct xradio_queue_item *item)
-+{
-+ struct xradio_queue_item *gc_item;
-+ gc_item = kmalloc(sizeof(struct xradio_queue_item), GFP_KERNEL);
-+ BUG_ON(!gc_item);
-+ memcpy(gc_item, item, sizeof(struct xradio_queue_item));
-+ list_add_tail(&gc_item->head, gc_list);
-+}
-+
-+static void __xradio_queue_gc(struct xradio_queue *queue,
-+ struct list_head *head,
-+ bool unlock)
-+{
-+ struct xradio_queue_stats *stats = queue->stats;
-+ struct xradio_queue_item *item = NULL;
-+ //struct xradio_vif *priv;
-+ int if_id;
-+ bool wakeup_stats = false;
-+
-+ while (!list_empty(&queue->queue)) {
-+ struct xradio_txpriv *txpriv;
-+ item = list_first_entry(
-+ &queue->queue, struct xradio_queue_item, head);
-+ if (time_before(jiffies, item->queue_timestamp+queue->ttl))
-+ break;
-+
-+ txpriv = &item->txpriv;
-+ if_id = txpriv->if_id;
-+ --queue->num_queued;
-+ --queue->num_queued_vif[if_id];
-+ --queue->link_map_cache[if_id][txpriv->link_id];
-+ spin_lock_bh(&stats->lock);
-+ --stats->num_queued[if_id];
-+ if (!--stats->link_map_cache[if_id][txpriv->link_id])
-+ wakeup_stats = true;
-+ spin_unlock_bh(&stats->lock);
-+ //priv = xrwl_hwpriv_to_vifpriv(stats->hw_priv, if_id);
-+ //if (priv) {
-+ // xradio_debug_tx_ttl(priv);
-+ // spin_unlock(&priv->vif_lock);
-+ //}
-+ xradio_queue_register_post_gc(head, item);
-+ item->skb = NULL;
-+ list_move_tail(&item->head, &queue->free_pool);
-+ }
-+
-+ if (wakeup_stats)
-+ wake_up(&stats->wait_link_id_empty);
-+
-+ //modified by yangfh for test WFD
-+ if (queue->overfull) {
-+ if (queue->num_queued <= ((stats->hw_priv->vif0_throttle +
-+ stats->hw_priv->vif1_throttle+2)>>1)) {
-+ queue->overfull = false;
-+ if (unlock) {
-+ __xradio_queue_unlock(queue);
-+ }
-+ } else if (item) {
-+ unsigned long tmo = item->queue_timestamp + queue->ttl;
-+ mod_timer(&queue->gc, tmo);
-+ xradio_pm_stay_awake(&stats->hw_priv->pm_state,
-+ tmo - jiffies);
-+ }
-+ }
-+}
-+
-+static void xradio_queue_gc(struct timer_list *t)
-+{
-+ struct xradio_queue *queue = from_timer(queue, t, gc);
-+
-+ LIST_HEAD(list);
-+
-+ spin_lock_bh(&queue->lock);
-+ __xradio_queue_gc(queue, &list, true);
-+ spin_unlock_bh(&queue->lock);
-+ xradio_queue_post_gc(queue->stats, &list);
-+}
-+
-+int xradio_queue_stats_init(struct xradio_queue_stats *stats,
-+ size_t map_capacity,
-+ xradio_queue_skb_dtor_t skb_dtor,
-+ struct xradio_common *hw_priv)
-+{
-+ int i;
-+
-+ memset(stats, 0, sizeof(*stats));
-+ stats->map_capacity = map_capacity;
-+ stats->skb_dtor = skb_dtor;
-+ stats->hw_priv = hw_priv;
-+ spin_lock_init(&stats->lock);
-+ init_waitqueue_head(&stats->wait_link_id_empty);
-+ for (i = 0; i < XRWL_MAX_VIFS; i++) {
-+ stats->link_map_cache[i] = kzalloc(sizeof(int[map_capacity]), GFP_KERNEL);
-+ if (!stats->link_map_cache[i]) {
-+ for (; i >= 0; i--)
-+ kfree(stats->link_map_cache[i]);
-+ return -ENOMEM;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int xradio_queue_init(struct xradio_queue *queue,
-+ struct xradio_queue_stats *stats,
-+ u8 queue_id,
-+ size_t capacity,
-+ unsigned long ttl)
-+{
-+ int i;
-+
-+ memset(queue, 0, sizeof(*queue));
-+ queue->stats = stats;
-+ queue->capacity = capacity;
-+ queue->queue_id = queue_id;
-+ queue->ttl = ttl;
-+ INIT_LIST_HEAD(&queue->queue);
-+ INIT_LIST_HEAD(&queue->pending);
-+ INIT_LIST_HEAD(&queue->free_pool);
-+ spin_lock_init(&queue->lock);
-+ timer_setup(&queue->gc, xradio_queue_gc, 0);
-+
-+ queue->pool = kzalloc(sizeof(struct xradio_queue_item) * capacity,
-+ GFP_KERNEL);
-+ if (!queue->pool)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < XRWL_MAX_VIFS; i++) {
-+ queue->link_map_cache[i] =
-+ kzalloc(sizeof(int[stats->map_capacity]), GFP_KERNEL);
-+ if (!queue->link_map_cache[i]) {
-+ for (; i >= 0; i--)
-+ kfree(queue->link_map_cache[i]);
-+ kfree(queue->pool);
-+ queue->pool = NULL;
-+ return -ENOMEM;
-+ }
-+ }
-+
-+ for (i = 0; i < capacity; ++i)
-+ list_add_tail(&queue->pool[i].head, &queue->free_pool);
-+
-+ return 0;
-+}
-+
-+/* TODO:COMBO: Flush only a particular interface specific parts */
-+int xradio_queue_clear(struct xradio_queue *queue, int if_id)
-+{
-+ int i, cnt, iter;
-+ struct xradio_queue_stats *stats = queue->stats;
-+ LIST_HEAD(gc_list);
-+
-+ cnt = 0;
-+ spin_lock_bh(&queue->lock);
-+ queue->generation++;
-+ queue->generation &= 0xf;
-+ list_splice_tail_init(&queue->queue, &queue->pending);
-+ while (!list_empty(&queue->pending)) {
-+ struct xradio_queue_item *item = list_first_entry(
-+ &queue->pending, struct xradio_queue_item, head);
-+ WARN_ON(!item->skb);
-+ if (XRWL_ALL_IFS == if_id || item->txpriv.if_id == if_id) {
-+ xradio_queue_register_post_gc(&gc_list, item);
-+ item->skb = NULL;
-+ list_move_tail(&item->head, &queue->free_pool);
-+ cnt++;
-+ }
-+ }
-+ queue->num_queued -= cnt;
-+ queue->num_pending = 0;
-+ if (XRWL_ALL_IFS != if_id) {
-+ queue->num_queued_vif[if_id] = 0;
-+ queue->num_pending_vif[if_id] = 0;
-+ } else {
-+ for (iter = 0; iter < XRWL_MAX_VIFS; iter++) {
-+ queue->num_queued_vif[iter] = 0;
-+ queue->num_pending_vif[iter] = 0;
-+ }
-+ }
-+ spin_lock_bh(&stats->lock);
-+ if (XRWL_ALL_IFS != if_id) {
-+ for (i = 0; i < stats->map_capacity; ++i) {
-+ stats->num_queued[if_id] -=
-+ queue->link_map_cache[if_id][i];
-+ stats->link_map_cache[if_id][i] -=
-+ queue->link_map_cache[if_id][i];
-+ queue->link_map_cache[if_id][i] = 0;
-+ }
-+ } else {
-+ for (iter = 0; iter < XRWL_MAX_VIFS; iter++) {
-+ for (i = 0; i < stats->map_capacity; ++i) {
-+ stats->num_queued[iter] -=
-+ queue->link_map_cache[iter][i];
-+ stats->link_map_cache[iter][i] -=
-+ queue->link_map_cache[iter][i];
-+ queue->link_map_cache[iter][i] = 0;
-+ }
-+ }
-+ }
-+ spin_unlock_bh(&stats->lock);
-+ if (unlikely(queue->overfull)) {
-+ queue->overfull = false;
-+ __xradio_queue_unlock(queue);
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ wake_up(&stats->wait_link_id_empty);
-+ xradio_queue_post_gc(stats, &gc_list);
-+ return 0;
-+}
-+
-+void xradio_queue_stats_deinit(struct xradio_queue_stats *stats)
-+{
-+ int i;
-+
-+ for (i = 0; i < XRWL_MAX_VIFS ; i++) {
-+ kfree(stats->link_map_cache[i]);
-+ stats->link_map_cache[i] = NULL;
-+ }
-+}
-+
-+void xradio_queue_deinit(struct xradio_queue *queue)
-+{
-+ int i;
-+
-+ xradio_queue_clear(queue, XRWL_ALL_IFS);
-+ del_timer_sync(&queue->gc);
-+ INIT_LIST_HEAD(&queue->free_pool);
-+ kfree(queue->pool);
-+ for (i = 0; i < XRWL_MAX_VIFS; i++) {
-+ kfree(queue->link_map_cache[i]);
-+ queue->link_map_cache[i] = NULL;
-+ }
-+ queue->pool = NULL;
-+ queue->capacity = 0;
-+}
-+
-+size_t xradio_queue_get_num_queued(struct xradio_vif *priv,
-+ struct xradio_queue *queue,
-+ u32 link_id_map)
-+{
-+ size_t ret;
-+ int i, bit;
-+ size_t map_capacity = queue->stats->map_capacity;
-+
-+ if (!link_id_map)
-+ return 0;
-+
-+ spin_lock_bh(&queue->lock);
-+ if (likely(link_id_map == (u32) -1)) {
-+ ret = queue->num_queued_vif[priv->if_id] -
-+ queue->num_pending_vif[priv->if_id];
-+ } else {
-+ ret = 0;
-+ for (i = 0, bit = 1; i < map_capacity; ++i, bit <<= 1) {
-+ if (link_id_map & bit)
-+ ret +=
-+ queue->link_map_cache[priv->if_id][i];
-+ }
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+int xradio_queue_put(struct xradio_queue *queue, struct sk_buff *skb,
-+ struct xradio_txpriv *txpriv)
-+{
-+ int ret = 0;
-+ LIST_HEAD(gc_list);
-+ struct xradio_queue_stats *stats = queue->stats;
-+ /* TODO:COMBO: Add interface ID info to queue item */
-+
-+ if (txpriv->link_id >= queue->stats->map_capacity)
-+ return -EINVAL;
-+
-+ spin_lock_bh(&queue->lock);
-+ if (!WARN_ON(list_empty(&queue->free_pool))) {
-+ struct xradio_queue_item *item = list_first_entry(
-+ &queue->free_pool, struct xradio_queue_item, head);
-+ BUG_ON(item->skb);
-+
-+ list_move_tail(&item->head, &queue->queue);
-+ item->skb = skb;
-+ item->txpriv = *txpriv;
-+ item->generation = 1; /* avoid packet ID is 0.*/
-+ item->pack_stk_wr = 0;
-+ item->packetID = xradio_queue_make_packet_id(
-+ queue->generation, queue->queue_id,
-+ item->generation, item - queue->pool,
-+ txpriv->if_id, txpriv->raw_link_id);
-+ item->queue_timestamp = jiffies;
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ if (TES_P2P_0002_state == TES_P2P_0002_STATE_SEND_RESP) {
-+ TES_P2P_0002_packet_id = item->packetID;
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_GET_PKTID;
-+ txrx_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_GET_PKTID]\n");
-+ }
-+#endif
-+
-+ ++queue->num_queued;
-+ ++queue->num_queued_vif[txpriv->if_id];
-+ ++queue->link_map_cache[txpriv->if_id][txpriv->link_id];
-+
-+ spin_lock_bh(&stats->lock);
-+ ++stats->num_queued[txpriv->if_id];
-+ ++stats->link_map_cache[txpriv->if_id][txpriv->link_id];
-+ spin_unlock_bh(&stats->lock);
-+
-+ /*
-+ * TX may happen in parallel sometimes.
-+ * Leave extra queue slots so we don't overflow.
-+ */
-+ if (queue->overfull == false &&
-+ queue->num_queued >=
-+ ((stats->hw_priv->vif0_throttle +stats->hw_priv->vif1_throttle)
-+ - (num_present_cpus() - 1))) {
-+ queue->overfull = true;
-+ __xradio_queue_lock(queue);
-+ mod_timer(&queue->gc, jiffies);
-+ txrx_printk(XRADIO_DBG_NIY,"!lock queue\n");
-+ }
-+ } else {
-+ ret = -ENOENT;
-+ }
-+#if 0
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_put queue %d, %d, %d\n",
-+ queue->num_queued,
-+ queue->link_map_cache[txpriv->if_id][txpriv->link_id],
-+ queue->num_pending);
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_put stats %d, %d\n", stats->num_queued,
-+ stats->link_map_cache[txpriv->if_id][txpriv->link_id]);
-+#endif
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+int xradio_queue_get(struct xradio_queue *queue,
-+ int if_id,
-+ u32 link_id_map,
-+ struct wsm_tx **tx,
-+ struct ieee80211_tx_info **tx_info,
-+ struct xradio_txpriv **txpriv)
-+{
-+ int ret = -ENOENT;
-+ struct xradio_queue_item *item;
-+ struct xradio_queue_stats *stats = queue->stats;
-+ bool wakeup_stats = false;
-+
-+ spin_lock_bh(&queue->lock);
-+ list_for_each_entry(item, &queue->queue, head) {
-+ if ((item->txpriv.if_id == if_id) &&
-+ (link_id_map & BIT(item->txpriv.link_id))) {
-+ ret = 0;
-+ break;
-+ }
-+ }
-+
-+ if (!WARN_ON(ret)) {
-+ *tx = (struct wsm_tx *)item->skb->data;
-+ *tx_info = IEEE80211_SKB_CB(item->skb);
-+ *txpriv = &item->txpriv;
-+ (*tx)->packetID = __cpu_to_le32(item->packetID);
-+ list_move_tail(&item->head, &queue->pending);
-+ ++queue->num_pending;
-+ ++queue->num_pending_vif[item->txpriv.if_id];
-+ --queue->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id];
-+ item->xmit_timestamp = jiffies;
-+
-+ spin_lock_bh(&stats->lock);
-+ --stats->num_queued[item->txpriv.if_id];
-+ if (!--stats->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id])
-+ wakeup_stats = true;
-+
-+ spin_unlock_bh(&stats->lock);
-+#if 0
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_get queue %d, %d, %d\n",
-+ queue->num_queued,
-+ queue->link_map_cache[item->txpriv.if_id][item->txpriv.link_id],
-+ queue->num_pending);
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_get stats %d, %d\n", stats->num_queued,
-+ stats->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id]);
-+#endif
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ if (wakeup_stats)
-+ wake_up(&stats->wait_link_id_empty);
-+
-+ return ret;
-+}
-+
-+int xradio_queue_requeue(struct xradio_queue *queue, u32 packetID, bool check)
-+{
-+ int ret = 0;
-+ u8 queue_generation, queue_id, item_generation, item_id, if_id, link_id;
-+ struct xradio_queue_item *item;
-+ struct xradio_queue_stats *stats = queue->stats;
-+
-+ xradio_queue_parse_id(packetID, &queue_generation, &queue_id,
-+ &item_generation, &item_id, &if_id, &link_id);
-+
-+ item = &queue->pool[item_id];
-+ if (check && item->txpriv.offchannel_if_id == XRWL_GENERIC_IF_ID) {
-+ txrx_printk(XRADIO_DBG_MSG, "Requeued frame dropped for "
-+ "generic interface id.\n");
-+ xradio_queue_remove(queue, packetID);
-+ return 0;
-+ }
-+
-+ if (!check)
-+ item->txpriv.offchannel_if_id = XRWL_GENERIC_IF_ID;
-+
-+ /*if_id = item->txpriv.if_id;*/
-+
-+ spin_lock_bh(&queue->lock);
-+ BUG_ON(queue_id != queue->queue_id);
-+ if (unlikely(queue_generation != queue->generation)) {
-+ ret = -ENOENT;
-+ } else if (unlikely(item_id >= (unsigned) queue->capacity)) {
-+ WARN_ON(1);
-+ ret = -EINVAL;
-+ } else if (unlikely(item->generation != item_generation)) {
-+ WARN_ON(1);
-+ ret = -ENOENT;
-+ } else {
-+ --queue->num_pending;
-+ --queue->num_pending_vif[if_id];
-+ ++queue->link_map_cache[if_id][item->txpriv.link_id];
-+
-+ spin_lock_bh(&stats->lock);
-+ ++stats->num_queued[item->txpriv.if_id];
-+ ++stats->link_map_cache[if_id][item->txpriv.link_id];
-+ spin_unlock_bh(&stats->lock);
-+
-+ item->generation = ++item_generation;
-+ item->packetID = xradio_queue_make_packet_id(
-+ queue_generation, queue_id, item_generation, item_id,
-+ if_id, link_id);
-+ list_move(&item->head, &queue->queue);
-+#if 0
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_requeue queue %d, %d, %d\n",
-+ queue->num_queued,
-+ queue->link_map_cache[if_id][item->txpriv.link_id],
-+ queue->num_pending);
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_requeue stats %d, %d\n",
-+ stats->num_queued,
-+ stats->link_map_cache[if_id][item->txpriv.link_id]);
-+#endif
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+int xradio_queue_requeue_all(struct xradio_queue *queue)
-+{
-+ struct xradio_queue_stats *stats = queue->stats;
-+ spin_lock_bh(&queue->lock);
-+ while (!list_empty(&queue->pending)) {
-+ struct xradio_queue_item *item = list_entry(
-+ queue->pending.prev, struct xradio_queue_item, head);
-+
-+ --queue->num_pending;
-+ --queue->num_pending_vif[item->txpriv.if_id];
-+ ++queue->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id];
-+
-+ spin_lock_bh(&stats->lock);
-+ ++stats->num_queued[item->txpriv.if_id];
-+ ++stats->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id];
-+ spin_unlock_bh(&stats->lock);
-+
-+ ++item->generation;
-+ item->packetID = xradio_queue_make_packet_id(
-+ queue->generation, queue->queue_id,
-+ item->generation, item - queue->pool,
-+ item->txpriv.if_id, item->txpriv.raw_link_id);
-+ list_move(&item->head, &queue->queue);
-+ }
-+ spin_unlock_bh(&queue->lock);
-+
-+ return 0;
-+}
-+
-+int xradio_queue_remove(struct xradio_queue *queue, u32 packetID)
-+{
-+ int ret = 0;
-+ u8 queue_generation, queue_id, item_generation, item_id, if_id, link_id;
-+ struct xradio_queue_item *item;
-+ struct xradio_queue_stats *stats = queue->stats;
-+ struct sk_buff *gc_skb = NULL;
-+ struct xradio_txpriv gc_txpriv;
-+
-+ xradio_queue_parse_id(packetID, &queue_generation, &queue_id,
-+ &item_generation, &item_id, &if_id, &link_id);
-+
-+ item = &queue->pool[item_id];
-+
-+ spin_lock_bh(&queue->lock);
-+ BUG_ON(queue_id != queue->queue_id);
-+ /*TODO:COMBO:Add check for interface ID also */
-+ if (unlikely(queue_generation != queue->generation)) {
-+ ret = -ENOENT;
-+ } else if (unlikely(item_id >= (unsigned) queue->capacity)) {
-+ WARN_ON(1);
-+ ret = -EINVAL;
-+ } else if (unlikely(item->generation != item_generation)) {
-+ WARN_ON(1);
-+ ret = -ENOENT;
-+ } else {
-+ gc_txpriv = item->txpriv;
-+ gc_skb = item->skb;
-+ item->skb = NULL;
-+ --queue->num_pending;
-+ --queue->num_pending_vif[if_id];
-+ --queue->num_queued;
-+ --queue->num_queued_vif[if_id];
-+ ++queue->num_sent;
-+ ++item->generation;
-+
-+ /* Do not use list_move_tail here, but list_move:
-+ * try to utilize cache row.
-+ */
-+ list_move(&item->head, &queue->free_pool);
-+
-+ if (unlikely(queue->overfull) &&
-+ (queue->num_queued <= ((stats->hw_priv->vif0_throttle + stats->hw_priv->vif1_throttle + 2)>>1))) {
-+ queue->overfull = false;
-+ __xradio_queue_unlock(queue);
-+ }
-+ }
-+ spin_unlock_bh(&queue->lock);
-+
-+#if 0
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_drop queue %d, %d, %d\n",
-+ queue->num_queued, queue->link_map_cache[if_id][0],
-+ queue->num_pending);
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_drop stats %d, %d\n", stats->num_queued,
-+ stats->link_map_cache[if_id][0]);
-+#endif
-+ if (gc_skb)
-+ stats->skb_dtor(stats->hw_priv, gc_skb, &gc_txpriv);
-+
-+ return ret;
-+}
-+
-+int xradio_queue_get_skb(struct xradio_queue *queue, u32 packetID,
-+ struct sk_buff **skb,
-+ const struct xradio_txpriv **txpriv)
-+{
-+ int ret = 0;
-+ u8 queue_generation, queue_id, item_generation, item_id, if_id, link_id;
-+ struct xradio_queue_item *item;
-+
-+ xradio_queue_parse_id(packetID, &queue_generation, &queue_id,
-+ &item_generation, &item_id, &if_id, &link_id);
-+
-+ item = &queue->pool[item_id];
-+
-+ spin_lock_bh(&queue->lock);
-+ BUG_ON(queue_id != queue->queue_id);
-+ /* TODO:COMBO: Add check for interface ID here */
-+ if (unlikely(queue_generation != queue->generation)) {
-+ ret = -ENOENT;
-+ } else if (unlikely(item_id >= (unsigned) queue->capacity)) {
-+ WARN_ON(1);
-+ ret = -EINVAL;
-+ } else if (unlikely(item->generation != item_generation)) {
-+ WARN_ON(1);
-+ ret = -ENOENT;
-+ } else {
-+ *skb = item->skb;
-+ *txpriv = &item->txpriv;
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+void xradio_queue_lock(struct xradio_queue *queue)
-+{
-+ spin_lock_bh(&queue->lock);
-+ __xradio_queue_lock(queue);
-+ spin_unlock_bh(&queue->lock);
-+}
-+
-+void xradio_queue_unlock(struct xradio_queue *queue)
-+{
-+ spin_lock_bh(&queue->lock);
-+ __xradio_queue_unlock(queue);
-+ spin_unlock_bh(&queue->lock);
-+}
-+
-+bool xradio_queue_get_xmit_timestamp(struct xradio_queue *queue,
-+ unsigned long *timestamp, int if_id,
-+ u32 pending_frameID, u32 *Old_frame_ID)
-+{
-+ struct xradio_queue_item *item;
-+ bool ret;
-+
-+ spin_lock_bh(&queue->lock);
-+ ret = !list_empty(&queue->pending);
-+ if (ret) {
-+ list_for_each_entry(item, &queue->pending, head) {
-+ if (((if_id == XRWL_GENERIC_IF_ID) ||
-+ (if_id == XRWL_ALL_IFS) ||
-+ (item->txpriv.if_id == if_id)) &&
-+ (item->packetID != pending_frameID)) {
-+ if (time_before(item->xmit_timestamp,
-+ *timestamp)) {
-+ *timestamp = item->xmit_timestamp;
-+ *Old_frame_ID = item->packetID;
-+ }
-+ }
-+ }
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+bool xradio_queue_stats_is_empty(struct xradio_queue_stats *stats,
-+ u32 link_id_map, int if_id)
-+{
-+ bool empty = true;
-+
-+ spin_lock_bh(&stats->lock);
-+ if (link_id_map == (u32)-1)
-+ empty = stats->num_queued[if_id] == 0;
-+ else {
-+ int i, if_id;
-+ for (if_id = 0; if_id < XRWL_MAX_VIFS; if_id++) {
-+ for (i = 0; i < stats->map_capacity; ++i) {
-+ if (link_id_map & BIT(i)) {
-+ if (stats->link_map_cache[if_id][i]) {
-+ empty = false;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ spin_unlock_bh(&stats->lock);
-+
-+ return empty;
-+}
-+
-+bool xradio_query_txpkt_timeout(struct xradio_common *hw_priv, int if_id,
-+ u32 pending_pkt_id, long *timeout)
-+{
-+ int i;
-+ bool pending = false;
-+ unsigned long timestamp = jiffies;
-+ struct xradio_queue *queue = NULL;
-+ struct xradio_queue_item *item = NULL;
-+ struct xradio_queue *old_queue = NULL;
-+ struct xradio_queue_item *old_item = NULL;
-+ u8 pack_stk_wr = 0;
-+
-+ /* Get oldest frame.*/
-+ for (i = 0; i < AC_QUEUE_NUM; ++i) {
-+ queue = &hw_priv->tx_queue[i];
-+ spin_lock_bh(&queue->lock);
-+ if (!list_empty(&queue->pending)) {
-+ list_for_each_entry(item, &queue->pending, head) {
-+ if (((if_id == XRWL_GENERIC_IF_ID) ||
-+ (if_id == XRWL_ALL_IFS) ||
-+ (item->txpriv.if_id == if_id)) &&
-+ (item->packetID != pending_pkt_id)) {
-+ if (time_before(item->xmit_timestamp, timestamp)) {
-+ timestamp = item->xmit_timestamp;
-+ pack_stk_wr = item->pack_stk_wr;
-+ old_queue = queue;
-+ old_item = item;
-+ }
-+ }
-+ }
-+ pending = true;
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ }
-+ if (!pending)
-+ return false;
-+
-+ /* Check if frame transmission is timed out.
-+ * add (WSM_CMD_LAST_CHANCE_TIMEOUT>>1) for stuck workaround.*/
-+ *timeout = timestamp + WSM_CMD_LAST_CHANCE_TIMEOUT - jiffies;
-+ if (unlikely(*timeout < 0) && !pack_stk_wr) {
-+ struct ieee80211_hdr *frame = NULL;
-+ const struct xradio_txpriv *txpriv = NULL;
-+ u16 fctl = 0x0;
-+ u32 len = 0x0;
-+ u8 if_id = 0, link_id = 0, tid = 0;
-+
-+ /* query the timeout frame. */
-+ spin_lock_bh(&old_queue->lock);
-+ if (likely(old_item->skb && !hw_priv->query_packetID)) {
-+ hw_priv->query_packetID = old_item->packetID;
-+ old_item->pack_stk_wr = 1;
-+ atomic_add(1, &hw_priv->query_cnt);
-+
-+ /* Info of stuck frames for debug.*/
-+ txpriv = &old_item->txpriv;
-+ frame = (struct ieee80211_hdr *)(&old_item->skb->data[txpriv->offset]);
-+ fctl = frame->frame_control;
-+ len = old_item->skb->len;
-+ if_id = txpriv->if_id;
-+ link_id = txpriv->link_id;
-+ tid = txpriv->tid;
-+ }
-+ spin_unlock_bh(&old_queue->lock);
-+ /* Dump Info of stuck frames. */
-+ if (frame) {
-+ txrx_printk(XRADIO_DBG_ERROR, "TX confirm timeout(%ds).\n",
-+ WSM_CMD_LAST_CHANCE_TIMEOUT/HZ);
-+ txrx_printk(XRADIO_DBG_ERROR, "if=%d, linkid=%d, tid=%d, " \
-+ "old_packetID=0x%08x, fctl=0x%04x, len=%d, wr=%d\n",
-+ if_id, link_id, tid, hw_priv->query_packetID, fctl, len,
-+ pack_stk_wr);
-+ }
-+ /* Return half of timeout for query packet. */
-+ *timeout = (WSM_CMD_LAST_CHANCE_TIMEOUT>>1);
-+ } else if (unlikely(pack_stk_wr)){
-+ *timeout = *timeout + (WSM_CMD_LAST_CHANCE_TIMEOUT>>1);
-+ txrx_printk(XRADIO_DBG_MSG,"%s, wr and timeout=%ld\n", __func__, *timeout);
-+ }
-+ return pending;
-+}
-diff --git a/drivers/net/wireless/xradio/queue.h b/drivers/net/wireless/xradio/queue.h
-new file mode 100644
-index 0000000..d6b64ce
---- /dev/null
-+++ b/drivers/net/wireless/xradio/queue.h
-@@ -0,0 +1,139 @@
-+/*
-+ * queue operations for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#ifndef XRADIO_QUEUE_H_INCLUDED
-+#define XRADIO_QUEUE_H_INCLUDED
-+
-+/* private */ struct xradio_queue_item;
-+
-+/* extern */ struct sk_buff;
-+/* extern */ struct wsm_tx;
-+/* extern */ struct xradio_common;
-+/* extern */ struct xradio_vif;
-+/* extern */ struct ieee80211_tx_queue_stats;
-+/* extern */ struct xradio_txpriv;
-+
-+/* forward */ struct xradio_queue_stats;
-+
-+typedef void (*xradio_queue_skb_dtor_t)(struct xradio_common *priv,
-+ struct sk_buff *skb,
-+ const struct xradio_txpriv *txpriv);
-+
-+struct xradio_queue {
-+ struct xradio_queue_stats *stats;
-+ size_t capacity;
-+ size_t num_queued;
-+ size_t num_queued_vif[XRWL_MAX_VIFS];
-+ size_t num_pending;
-+ size_t num_pending_vif[XRWL_MAX_VIFS];
-+ size_t num_sent;
-+ struct xradio_queue_item *pool;
-+ struct list_head queue;
-+ struct list_head free_pool;
-+ struct list_head pending;
-+ int tx_locked_cnt;
-+ int *link_map_cache[XRWL_MAX_VIFS];
-+ bool overfull;
-+ spinlock_t lock;
-+ u8 queue_id;
-+ u8 generation;
-+ struct timer_list gc;
-+ unsigned long ttl;
-+};
-+
-+struct xradio_queue_stats {
-+ spinlock_t lock;
-+ int *link_map_cache[XRWL_MAX_VIFS];
-+ int num_queued[XRWL_MAX_VIFS];
-+ size_t map_capacity;
-+ wait_queue_head_t wait_link_id_empty;
-+ xradio_queue_skb_dtor_t skb_dtor;
-+ struct xradio_common *hw_priv;
-+};
-+
-+struct xradio_txpriv {
-+ u8 link_id;
-+ u8 raw_link_id;
-+ u8 tid;
-+ u8 rate_id;
-+ u8 offset;
-+ u8 if_id;
-+ u8 offchannel_if_id;
-+ u8 use_bg_rate;
-+};
-+
-+int xradio_queue_stats_init(struct xradio_queue_stats *stats,
-+ size_t map_capacity,
-+ xradio_queue_skb_dtor_t skb_dtor,
-+ struct xradio_common *priv);
-+int xradio_queue_init(struct xradio_queue *queue,
-+ struct xradio_queue_stats *stats,
-+ u8 queue_id,
-+ size_t capacity,
-+ unsigned long ttl);
-+int xradio_queue_clear(struct xradio_queue *queue, int if_id);
-+void xradio_queue_stats_deinit(struct xradio_queue_stats *stats);
-+void xradio_queue_deinit(struct xradio_queue *queue);
-+
-+size_t xradio_queue_get_num_queued(struct xradio_vif *priv,
-+ struct xradio_queue *queue,
-+ u32 link_id_map);
-+int xradio_queue_put(struct xradio_queue *queue,
-+ struct sk_buff *skb, struct xradio_txpriv *txpriv);
-+int xradio_queue_get(struct xradio_queue *queue,
-+ int if_id, u32 link_id_map,
-+ struct wsm_tx **tx,
-+ struct ieee80211_tx_info **tx_info,
-+ struct xradio_txpriv **txpriv);
-+
-+int xradio_queue_requeue(struct xradio_queue *queue, u32 packetID, bool check);
-+
-+int xradio_queue_requeue_all(struct xradio_queue *queue);
-+int xradio_queue_remove(struct xradio_queue *queue,
-+ u32 packetID);
-+
-+int xradio_queue_get_skb(struct xradio_queue *queue, u32 packetID,
-+ struct sk_buff **skb,
-+ const struct xradio_txpriv **txpriv);
-+void xradio_queue_lock(struct xradio_queue *queue);
-+void xradio_queue_unlock(struct xradio_queue *queue);
-+bool xradio_queue_get_xmit_timestamp(struct xradio_queue *queue,
-+ unsigned long *timestamp, int if_id,
-+ u32 pending_frameID, u32 *Old_frame_ID);
-+bool xradio_query_txpkt_timeout(struct xradio_common *hw_priv, int if_id,
-+ u32 pending_pkt_id, long *timeout);
-+
-+
-+bool xradio_queue_stats_is_empty(struct xradio_queue_stats *stats,
-+ u32 link_id_map, int if_id);
-+
-+static inline u8 xradio_queue_get_queue_id(u32 packetID)
-+{
-+ return (packetID >> 16) & 0xF;
-+}
-+
-+static inline u8 xradio_queue_get_if_id(u32 packetID)
-+{
-+ return (packetID >> 20) & 0xF;
-+}
-+
-+static inline u8 xradio_queue_get_link_id(u32 packetID)
-+{
-+ return (packetID >> 24) & 0xF;
-+}
-+
-+static inline u8 xradio_queue_get_generation(u32 packetID)
-+{
-+ return (packetID >> 8) & 0xFF;
-+}
-+
-+#endif /* XRADIO_QUEUE_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/rx.c b/drivers/net/wireless/xradio/rx.c
-new file mode 100644
-index 0000000..5a1ce60
---- /dev/null
-+++ b/drivers/net/wireless/xradio/rx.c
-@@ -0,0 +1,414 @@
-+#include
-+
-+#include "xradio.h"
-+#include "rx.h"
-+#include "ht.h"
-+#include "p2p.h"
-+#include "sta.h"
-+#include "bh.h"
-+#include "ap.h"
-+
-+ // MRK: added copy of this tx.c function here for testing, renamed _rx
-+
-+static void xradio_check_go_neg_conf_success_rx(struct xradio_common *hw_priv,
-+ u8 *action)
-+{
-+ if (action[2] == 0x50 && action[3] == 0x6F && action[4] == 0x9A &&
-+ action[5] == 0x09 && action[6] == 0x02) {
-+ if(action[17] == 0) {
-+ hw_priv->is_go_thru_go_neg = true;
-+ }
-+ else {
-+ hw_priv->is_go_thru_go_neg = false;
-+ }
-+ }
-+}
-+
-+
-+static int xradio_handle_pspoll(struct xradio_vif *priv,
-+ struct sk_buff *skb)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct ieee80211_sta *sta;
-+ struct ieee80211_pspoll *pspoll =
-+ (struct ieee80211_pspoll *) skb->data;
-+ int link_id = 0;
-+ u32 pspoll_mask = 0;
-+ int drop = 1;
-+ int i;
-+
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP)
-+ goto done;
-+ if (memcmp(priv->vif->addr, pspoll->bssid, ETH_ALEN))
-+ goto done;
-+
-+ rcu_read_lock();
-+ sta = ieee80211_find_sta(priv->vif, pspoll->ta);
-+ if (sta) {
-+ struct xradio_sta_priv *sta_priv;
-+ sta_priv = (struct xradio_sta_priv *)&sta->drv_priv;
-+ link_id = sta_priv->link_id;
-+ pspoll_mask = BIT(sta_priv->link_id);
-+ }
-+ rcu_read_unlock();
-+ if (!link_id)
-+ goto done;
-+
-+ priv->pspoll_mask |= pspoll_mask;
-+ drop = 0;
-+
-+ /* Do not report pspols if data for given link id is
-+ * queued already. */
-+ for (i = 0; i < 4; ++i) {
-+ if (xradio_queue_get_num_queued(priv,
-+ &hw_priv->tx_queue[i],
-+ pspoll_mask)) {
-+ xradio_bh_wakeup(hw_priv);
-+ drop = 1;
-+ break;
-+ }
-+ }
-+ txrx_printk(XRADIO_DBG_NIY, "[RX] PSPOLL: %s\n", drop ? "local" : "fwd");
-+done:
-+ return drop;
-+}
-+
-+
-+static void
-+xradio_rx_h_ba_stat(struct xradio_vif *priv,
-+ size_t hdrlen, size_t skb_len )
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_STA)
-+ return;
-+ if (!xradio_is_ht(&hw_priv->ht_oper))
-+ return;
-+ if (!priv->setbssparams_done)
-+ return;
-+
-+ spin_lock_bh(&hw_priv->ba_lock);
-+ hw_priv->ba_acc_rx += skb_len - hdrlen;
-+ if (!(hw_priv->ba_cnt_rx || hw_priv->ba_cnt)) {
-+ mod_timer(&hw_priv->ba_timer,
-+ jiffies + XRADIO_BLOCK_ACK_INTERVAL);
-+ }
-+ hw_priv->ba_cnt_rx++;
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+}
-+
-+void xradio_rx_cb(struct xradio_vif *priv,
-+ struct wsm_rx *arg,
-+ struct sk_buff **skb_p)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct sk_buff *skb = *skb_p;
-+ struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-+#endif
-+ struct xradio_link_entry *entry = NULL;
-+ unsigned long grace_period;
-+ bool early_data = false;
-+ size_t hdrlen = 0;
-+ u8 parse_iv_len = 0;
-+
-+ dev_dbg(hw_priv->pdev, "vif %d: rx, status %u flags 0x%.8x",
-+ priv->if_id, arg->status, arg->flags);
-+ if(ieee80211_is_deauth(frame->frame_control))
-+ dev_dbg(hw_priv->pdev, "vif %d: deauth\n", priv->if_id);
-+
-+ hdr->flag = 0;
-+
-+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
-+ /* STA is stopped. */
-+ goto drop;
-+ }
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ xradio_frame_monitor(hw_priv,skb,false);
-+#endif
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ if ((ieee80211_is_action(frame->frame_control))
-+ && (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) {
-+ u8 *action = (u8*)&mgmt->u.action.category;
-+ xradio_check_go_neg_conf_success_rx(hw_priv, action);
-+ }
-+#endif
-+
-+ if (arg->link_id && (arg->link_id != XRADIO_LINK_ID_UNMAPPED)
-+ && (arg->link_id <= XRADIO_MAX_STA_IN_AP_MODE)) {
-+ entry = &priv->link_id_db[arg->link_id - 1];
-+ if (entry->status == XRADIO_LINK_SOFT &&
-+ ieee80211_is_data(frame->frame_control))
-+ early_data = true;
-+ entry->timestamp = jiffies;
-+ }
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ else if ((arg->link_id == XRADIO_LINK_ID_UNMAPPED)
-+ && (priv->vif->p2p == WSM_START_MODE_P2P_GO)
-+ && ieee80211_is_action(frame->frame_control)
-+ && (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) {
-+ txrx_printk(XRADIO_DBG_NIY, "[RX] Going to MAP&RESET link ID\n");
-+
-+ if (work_pending(&priv->linkid_reset_work))
-+ WARN_ON(1);
-+
-+ memcpy(&priv->action_frame_sa[0],
-+ ieee80211_get_SA(frame), ETH_ALEN);
-+ priv->action_linkid = 0;
-+ schedule_work(&priv->linkid_reset_work);
-+ }
-+
-+ if (arg->link_id && (arg->link_id != XRADIO_LINK_ID_UNMAPPED)
-+ && (priv->vif->p2p == WSM_START_MODE_P2P_GO)
-+ && ieee80211_is_action(frame->frame_control)
-+ && (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) {
-+ /* Link ID already exists for the ACTION frame.
-+ * Reset and Remap */
-+ if (work_pending(&priv->linkid_reset_work))
-+ WARN_ON(1);
-+ memcpy(&priv->action_frame_sa[0],
-+ ieee80211_get_SA(frame), ETH_ALEN);
-+ priv->action_linkid = arg->link_id;
-+ schedule_work(&priv->linkid_reset_work);
-+ }
-+#endif
-+ if (unlikely(arg->status)) {
-+ if (arg->status == WSM_STATUS_MICFAILURE) {
-+ dev_err(priv->hw_priv->pdev, "[RX] IF=%d, MIC failure.\n",
-+ priv->if_id);
-+ hdr->flag |= RX_FLAG_MMIC_ERROR;
-+ } else if (arg->status == WSM_STATUS_NO_KEY_FOUND) {
-+ dev_warn(priv->hw_priv->pdev, "received frame has no key status\n");
-+ goto drop;
-+ } else {
-+ dev_err(priv->hw_priv->pdev, "[RX] IF=%d, Receive failure: %d.\n",
-+ priv->if_id, arg->status);
-+ goto drop;
-+ }
-+ }
-+
-+ if (skb->len < sizeof(struct ieee80211_pspoll)) {
-+ dev_err(priv->hw_priv->pdev, "Malformed SDU rx'ed. "
-+ "Size is lesser than IEEE header.\n");
-+ goto drop;
-+ }
-+
-+ if (unlikely(ieee80211_is_pspoll(frame->frame_control)))
-+ if (xradio_handle_pspoll(priv, skb))
-+ goto drop;
-+
-+ hdr->mactime = 0; /* Not supported by WSM */
-+ hdr->band = (arg->channelNumber > 14) ?
-+ NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
-+ hdr->freq = ieee80211_channel_to_frequency(
-+ arg->channelNumber,
-+ hdr->band);
-+
-+#ifdef AP_HT_COMPAT_FIX
-+ if (!priv->ht_compat_det && priv->htcap &&
-+ ieee80211_is_data_qos(frame->frame_control)) {
-+ if(xradio_apcompat_detect(priv, arg->rxedRate))
-+ goto drop;
-+ }
-+#endif
-+
-+ if (arg->rxedRate >= 14) {
-+ hdr->encoding = RX_ENC_HT;
-+ hdr->rate_idx = arg->rxedRate - 14;
-+ } else if (arg->rxedRate >= 4) {
-+ if (hdr->band == NL80211_BAND_5GHZ)
-+ hdr->rate_idx = arg->rxedRate - 6;
-+ else
-+ hdr->rate_idx = arg->rxedRate - 2;
-+ } else {
-+ hdr->rate_idx = arg->rxedRate;
-+ }
-+
-+ hdr->signal = (s8)arg->rcpiRssi;
-+ hdr->antenna = 0;
-+
-+ hdrlen = ieee80211_hdrlen(frame->frame_control);
-+
-+ if (WSM_RX_STATUS_ENCRYPTION(arg->flags)) {
-+ size_t iv_len = 0, icv_len = 0;
-+
-+ hdr->flag |= RX_FLAG_DECRYPTED;
-+
-+ /* Oops... There is no fast way to ask mac80211 about
-+ * IV/ICV lengths. Even defines are not exposed.*/
-+ switch (WSM_RX_STATUS_ENCRYPTION(arg->flags)) {
-+ case WSM_RX_STATUS_WEP:
-+ iv_len = 4 /* WEP_IV_LEN */;
-+ icv_len = 4 /* WEP_ICV_LEN */;
-+ break;
-+ case WSM_RX_STATUS_TKIP:
-+ iv_len = 8 /* TKIP_IV_LEN */;
-+ icv_len = 4 /* TKIP_ICV_LEN */
-+ + 8 /*MICHAEL_MIC_LEN*/;
-+ break;
-+ case WSM_RX_STATUS_AES:
-+ iv_len = 8 /* CCMP_HDR_LEN */;
-+ icv_len = 8 /* CCMP_MIC_LEN */;
-+ break;
-+ case WSM_RX_STATUS_WAPI:
-+ iv_len = 18 /* WAPI_HDR_LEN */;
-+ icv_len = 16 /* WAPI_MIC_LEN */;
-+ hdr->flag |= RX_FLAG_IV_STRIPPED;
-+ break;
-+ default:
-+ WARN_ON("Unknown encryption type");
-+ goto drop;
-+ }
-+
-+ /* Firmware strips ICV in case of MIC failure. */
-+ if (arg->status == WSM_STATUS_MICFAILURE) {
-+ icv_len = 0;
-+ hdr->flag |= RX_FLAG_IV_STRIPPED;
-+ }
-+
-+ if (skb->len < hdrlen + iv_len + icv_len) {
-+ dev_err(priv->hw_priv->pdev, "Mailformed SDU rx'ed. "
-+ "Size is lesser than crypto headers.\n");
-+ goto drop;
-+ }
-+
-+ if (WSM_RX_STATUS_ENCRYPTION(arg->flags) ==
-+ WSM_RX_STATUS_TKIP) {
-+ /* Remove TKIP MIC 8 bytes*/
-+ memmove(skb->data + skb->len-icv_len,
-+ skb->data + skb->len-icv_len+8, 4);
-+ skb_trim(skb, skb->len - 8);
-+ hdr->flag |= RX_FLAG_MMIC_STRIPPED;
-+ } else if (unlikely(WSM_RX_STATUS_ENCRYPTION(arg->flags) ==
-+ WSM_RX_STATUS_WAPI)) {
-+ /* Protocols not defined in mac80211 should be
-+ stripped/crypted in driver/firmware */
-+ /* Remove IV, ICV and MIC */
-+ skb_trim(skb, skb->len - icv_len);
-+ memmove(skb->data + iv_len, skb->data, hdrlen);
-+ skb_pull(skb, iv_len);
-+ }
-+ parse_iv_len = iv_len;
-+ }
-+
-+ if (ieee80211_is_beacon(frame->frame_control) &&
-+ !arg->status &&
-+ !memcmp(ieee80211_get_SA(frame), priv->join_bssid,ETH_ALEN)) {
-+ const u8 *tim_ie;
-+ u8 *ies;
-+ size_t ies_len;
-+ priv->disable_beacon_filter = false;
-+ queue_work(hw_priv->workqueue, &priv->update_filtering_work);
-+ ies = ((struct ieee80211_mgmt *)
-+ (skb->data))->u.beacon.variable;
-+ ies_len = skb->len - (ies - (u8 *)(skb->data));
-+
-+ tim_ie = xradio_get_ie(ies, ies_len, WLAN_EID_TIM);
-+ if (tim_ie) {
-+ struct ieee80211_tim_ie *tim =
-+ (struct ieee80211_tim_ie *)&tim_ie[2];
-+
-+ if (priv->join_dtim_period != tim->dtim_period) {
-+ priv->join_dtim_period = tim->dtim_period;
-+ queue_work(hw_priv->workqueue,
-+ &priv->set_beacon_wakeup_period_work);
-+ }
-+ }
-+ if (unlikely(priv->disable_beacon_filter)) {
-+ priv->disable_beacon_filter = false;
-+ queue_work(hw_priv->workqueue,
-+ &priv->update_filtering_work);
-+ }
-+ }
-+#ifdef AP_HT_CAP_UPDATE
-+ if (priv->mode == NL80211_IFTYPE_AP &&
-+ ieee80211_is_beacon(frame->frame_control) &&
-+ ((priv->ht_oper&HT_INFO_MASK) != 0x0011) &&
-+ !arg->status){
-+ u8 *ies;
-+ size_t ies_len;
-+ const u8 *ht_cap;
-+ ies = ((struct ieee80211_mgmt *)(skb->data))->u.beacon.variable;
-+ ies_len = skb->len - (ies - (u8 *)(skb->data));
-+ ht_cap = xradio_get_ie(ies, ies_len, WLAN_EID_HT_CAPABILITY);
-+ if(!ht_cap) {
-+ priv->ht_oper |= 0x0011;
-+ queue_work(hw_priv->workqueue, &priv->ht_oper_update_work);
-+ }
-+ }
-+#endif
-+
-+#ifdef AP_HT_COMPAT_FIX
-+ if (ieee80211_is_mgmt(frame->frame_control) &&
-+ priv->if_id == 0 && !(priv->ht_compat_det & 0x10)) {
-+ xradio_remove_ht_ie(priv, skb);
-+ }
-+#endif
-+
-+#ifdef ROAM_OFFLOAD
-+ if ((ieee80211_is_beacon(frame->frame_control)||ieee80211_is_probe_resp(frame->frame_control)) &&
-+ !arg->status ) {
-+ if (hw_priv->auto_scanning && !atomic_read(&hw_priv->scan.in_progress))
-+ hw_priv->frame_rcvd = 1;
-+
-+ if (!memcmp(ieee80211_get_SA(frame), priv->join_bssid, ETH_ALEN)) {
-+ if (hw_priv->beacon)
-+ dev_kfree_skb(hw_priv->beacon);
-+ hw_priv->beacon = skb_copy(skb, GFP_ATOMIC);
-+ if (!hw_priv->beacon)
-+ txrx_printk(XRADIO_DBG_ERROR, "sched_scan: own beacon storing failed\n");
-+ }
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+
-+ //don't delay scan before next connect, yangfh.
-+ if (ieee80211_is_deauth(frame->frame_control) ||
-+ ieee80211_is_disassoc(frame->frame_control))
-+ hw_priv->connet_time[priv->if_id] = 0;
-+
-+ /* Stay awake for 1sec. after frame is received to give
-+ * userspace chance to react and acquire appropriate
-+ * wakelock. */
-+ if (ieee80211_is_auth(frame->frame_control))
-+ grace_period = 5 * HZ;
-+ else if (ieee80211_is_deauth(frame->frame_control))
-+ grace_period = 5 * HZ;
-+ else
-+ grace_period = HZ;
-+
-+ if (ieee80211_is_data(frame->frame_control))
-+ xradio_rx_h_ba_stat(priv, hdrlen, skb->len);
-+
-+ xradio_pm_stay_awake(&hw_priv->pm_state, grace_period);
-+
-+ if(xradio_realloc_resv_skb(hw_priv, *skb_p)) {
-+ *skb_p = NULL;
-+ return;
-+ }
-+ /* Try to a packet for the case dev_alloc_skb failed in bh.*/
-+ if (unlikely(early_data)) {
-+ spin_lock_bh(&priv->ps_state_lock);
-+ /* Double-check status with lock held */
-+ if (entry->status == XRADIO_LINK_SOFT) {
-+ skb_queue_tail(&entry->rx_queue, skb);
-+ dev_warn(priv->hw_priv->pdev, "***skb_queue_tail\n");
-+ } else
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ } else {
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+ *skb_p = NULL;
-+
-+ return;
-+
-+drop:
-+ dev_warn(priv->hw_priv->pdev, "dropped received frame\n");
-+ return;
-+}
-diff --git a/drivers/net/wireless/xradio/rx.h b/drivers/net/wireless/xradio/rx.h
-new file mode 100644
-index 0000000..0c02b23
---- /dev/null
-+++ b/drivers/net/wireless/xradio/rx.h
-@@ -0,0 +1,8 @@
-+#ifndef XRADIO_RX_H
-+#define XRADIO_RX_H
-+
-+void xradio_rx_cb(struct xradio_vif *priv,
-+ struct wsm_rx *arg,
-+ struct sk_buff **skb_p);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/scan.c b/drivers/net/wireless/xradio/scan.c
-new file mode 100644
-index 0000000..a8829c0
---- /dev/null
-+++ b/drivers/net/wireless/xradio/scan.c
-@@ -0,0 +1,897 @@
-+/*
-+ * Scan implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include "xradio.h"
-+#include "scan.h"
-+#include "sta.h"
-+#include "pm.h"
-+
-+static void xradio_scan_restart_delayed(struct xradio_vif *priv);
-+
-+static void xradio_remove_wps_p2p_ie(struct wsm_template_frame *frame)
-+{
-+ u8 *ies;
-+ u32 ies_len;
-+ u32 ie_len;
-+ u32 p2p_ie_len = 0;
-+ u32 wps_ie_len = 0;
-+
-+
-+ ies = &frame->skb->data[sizeof(struct ieee80211_hdr_3addr)];
-+ ies_len = frame->skb->len - sizeof(struct ieee80211_hdr_3addr);
-+ while (ies_len >= 6) {
-+ ie_len = ies[1] + 2;
-+ ies_len -= ie_len;
-+ if ((ies[0] == WLAN_EID_VENDOR_SPECIFIC) &&
-+ (ies[2] == 0x00 && ies[3] == 0x50 &&
-+ ies[4] == 0xf2 && ies[5] == 0x04)) {
-+ wps_ie_len = ie_len;
-+ memmove(ies, ies + ie_len, ies_len);
-+ } else if ((ies[0] == WLAN_EID_VENDOR_SPECIFIC) &&
-+ (ies[2] == 0x50 && ies[3] == 0x6f &&
-+ ies[4] == 0x9a && ies[5] == 0x09)) {
-+ p2p_ie_len = ie_len;
-+ memmove(ies, ies + ie_len, ies_len);
-+ } else {
-+ ies += ie_len;
-+ }
-+ }
-+
-+ if (p2p_ie_len || wps_ie_len) {
-+ skb_trim(frame->skb, frame->skb->len - (p2p_ie_len + wps_ie_len));
-+ }
-+}
-+
-+static int xradio_scan_start(struct xradio_vif *priv, struct wsm_scan *scan)
-+{
-+ int ret, i;
-+#ifdef FPGA_SETUP
-+ int tmo = 5000;
-+#else
-+ int tmo = 5000;
-+#endif
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+
-+ for (i = 0; i < scan->numOfChannels; ++i)
-+ tmo += scan->ch[i].maxChannelTime + 10;
-+
-+ atomic_set(&hw_priv->scan.in_progress, 1);
-+ atomic_set(&hw_priv->recent_scan, 1);
-+ xradio_pm_stay_awake(&hw_priv->pm_state, tmo * HZ / 1000);
-+ ret = wsm_scan(hw_priv, scan, priv->if_id);
-+ if (unlikely(ret)) {
-+ scan_printk(XRADIO_DBG_WARN, "%s,wsm_scan failed!\n", __func__);
-+ atomic_set(&hw_priv->scan.in_progress, 0);
-+ xradio_scan_restart_delayed(priv);
-+ } else {
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.timeout,
-+ tmo * HZ / 1000);
-+ }
-+ return ret;
-+}
-+
-+#ifdef ROAM_OFFLOAD
-+static int xradio_sched_scan_start(struct xradio_vif *priv, struct wsm_scan *scan)
-+{
-+ int ret;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+
-+ ret = wsm_scan(hw_priv, scan, priv->if_id);
-+ if (unlikely(ret)) {
-+ atomic_set(&hw_priv->scan.in_progress, 0);
-+ scan_printk(XRADIO_DBG_WARN,"%s,wsm_scan failed!\n", __func__);
-+ }
-+ return ret;
-+}
-+#endif /*ROAM_OFFLOAD*/
-+
-+int xradio_hw_scan(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_scan_request *hw_req)
-+{
-+ struct cfg80211_scan_request *req = &hw_req->req;
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
-+ };
-+ int i;
-+
-+ /* Scan when P2P_GO corrupt firmware MiniAP mode */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ scan_printk(XRADIO_DBG_WARN,"%s, can't scan in AP mode!\n", __func__);
-+ return -EOPNOTSUPP;
-+ }
-+
-+ if (hw_priv->bh_error) {
-+ scan_printk(XRADIO_DBG_NIY, "Ignoring scan bh error occur!\n");
-+ return -EBUSY;
-+ }
-+
-+ if (work_pending(&priv->offchannel_work) ||
-+ (hw_priv->roc_if_id != -1)) {
-+ scan_printk(XRADIO_DBG_WARN, "Offchannel work pending, "
-+ "ignoring scan work %d\n", hw_priv->roc_if_id);
-+ return -EBUSY;
-+ }
-+
-+ if (req->n_ssids == 1 && !req->ssids[0].ssid_len)
-+ req->n_ssids = 0;
-+
-+ scan_printk(XRADIO_DBG_NIY, "vif%d Scan request(%s-%dchs) for %d SSIDs.\n",
-+ priv->if_id, (req->channels[0]->band==NL80211_BAND_2GHZ)?"2.4G":"5G",
-+ req->n_channels, req->n_ssids);
-+
-+ /*delay multiple ssids scan of vif0 for 3s when connnetting to a node*/
-+ if(hw_priv->connet_time[0] > 0 && req->n_ssids == 0 && priv->if_id == 0) {
-+ long timeleft0 = hw_priv->connet_time[0] + SCAN_MAX_DELAY - jiffies;
-+ if(jiffies >= hw_priv->connet_time[0] && timeleft0 > 0) {
-+ scan_printk(XRADIO_DBG_NIY, "vif0 connetting, scan delay %ldms\n",
-+ timeleft0*1000/HZ);
-+ return -EBUSY;
-+ }
-+ hw_priv->connet_time[0] = 0;
-+ }
-+
-+ if (req->n_ssids > hw->wiphy->max_scan_ssids){
-+ scan_printk(XRADIO_DBG_ERROR, "%s: ssids is too much(%d)\n",
-+ __func__, req->n_ssids);
-+ return -EINVAL;
-+ }
-+
-+ /* TODO by Icenowy: so strange function call */
-+ frame.skb = ieee80211_probereq_get(hw, vif->addr, NULL, 0, 0);
-+ if (!frame.skb) {
-+ scan_printk(XRADIO_DBG_ERROR, "%s: ieee80211_probereq_get failed!\n",
-+ __func__);
-+ return -ENOMEM;
-+ }
-+
-+#ifdef ROAM_OFFLOAD
-+ if (priv->join_status != XRADIO_JOIN_STATUS_STA) {
-+ if (req->channels[0]->band == NL80211_BAND_2GHZ)
-+ hw_priv->num_scanchannels = 0;
-+ else
-+ hw_priv->num_scanchannels = hw_priv->num_2g_channels;
-+
-+ for (i=0; i < req->n_channels; i++) {
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].number = \
-+ req->channels[i]->hw_value;
-+ if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) {
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].minChannelTime = 50;
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].maxChannelTime = 110;
-+ }
-+ else {
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].minChannelTime = 10;
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].maxChannelTime = 40;
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].number |= \
-+ XRADIO_SCAN_TYPE_ACTIVE;
-+ }
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].txPowerLevel = \
-+ req->channels[i]->max_power;
-+ if (req->channels[0]->band == NL80211_BAND_5GHZ)
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].number |= \
-+ XRADIO_SCAN_BAND_5G;
-+ }
-+ if (req->channels[0]->band == NL80211_BAND_2GHZ)
-+ hw_priv->num_2g_channels = req->n_channels;
-+ else
-+ hw_priv->num_5g_channels = req->n_channels;
-+ }
-+ hw_priv->num_scanchannels = hw_priv->num_2g_channels + hw_priv->num_5g_channels;
-+#endif /*ROAM_OFFLOAD*/
-+
-+ /* will be unlocked in xradio_scan_work() */
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ if (frame.skb) {
-+ int ret = 0;
-+ if (priv->if_id == 0)
-+ xradio_remove_wps_p2p_ie(&frame);
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ if (ret) {
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+ dev_kfree_skb(frame.skb);
-+ scan_printk(XRADIO_DBG_ERROR, "%s: wsm_set_template_frame failed: %d.\n",
-+ __func__, ret);
-+ return ret;
-+ }
-+ }
-+
-+ wsm_vif_lock_tx(priv);
-+
-+ BUG_ON(hw_priv->scan.req);
-+ hw_priv->scan.req = req;
-+ hw_priv->scan.n_ssids = 0;
-+ hw_priv->scan.status = 0;
-+ hw_priv->scan.begin = &req->channels[0];
-+ hw_priv->scan.curr = hw_priv->scan.begin;
-+ hw_priv->scan.end = &req->channels[req->n_channels];
-+ hw_priv->scan.output_power = hw_priv->output_power;
-+ hw_priv->scan.if_id = priv->if_id;
-+ /* TODO:COMBO: Populate BIT4 in scanflags to decide on which MAC
-+ * address the SCAN request will be sent */
-+
-+ for (i = 0; i < req->n_ssids; ++i) {
-+ struct wsm_ssid *dst = &hw_priv->scan.ssids[hw_priv->scan.n_ssids];
-+ BUG_ON(req->ssids[i].ssid_len > sizeof(dst->ssid));
-+ memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid));
-+ dst->length = req->ssids[i].ssid_len;
-+ ++hw_priv->scan.n_ssids;
-+ }
-+
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ if (frame.skb)
-+ dev_kfree_skb(frame.skb);
-+ queue_work(hw_priv->workqueue, &hw_priv->scan.work);
-+
-+ return 0;
-+}
-+
-+#ifdef ROAM_OFFLOAD
-+int xradio_hw_sched_scan_start(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct cfg80211_sched_scan_request *req,
-+ struct ieee80211_sched_scan_ies *ies)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
-+ };
-+ int i;
-+
-+
-+ scan_printk(XRADIO_DBG_WARN, "Scheduled scan request-->.\n");
-+ if (!priv->vif)
-+ return -EINVAL;
-+
-+ /* Scan when P2P_GO corrupt firmware MiniAP mode */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ scan_printk(XRADIO_DBG_WARN,"%s, can't scan in AP mode!\n", __func__);
-+ return -EOPNOTSUPP;
-+ }
-+
-+ scan_printk(XRADIO_DBG_WARN, "Scheduled scan: n_ssids %d, ssid[0].len = %d\n",
-+ req->n_ssids, req->ssids[0].ssid_len);
-+ if (req->n_ssids == 1 && !req->ssids[0].ssid_len)
-+ req->n_ssids = 0;
-+
-+ scan_printk(XRADIO_DBG_NIY, "[SCAN] Scan request for %d SSIDs.\n",
-+ req->n_ssids);
-+
-+ if (req->n_ssids > hw->wiphy->max_scan_ssids) [
-+ scan_printk(XRADIO_DBG_ERROR, "%s: ssids is too much(%d)\n",
-+ __func__, req->n_ssids);
-+ return -EINVAL;
-+ }
-+
-+ frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0,
-+ ies->ie[0], ies->len[0]);
-+ if (!frame.skb) {
-+ scan_printk(XRADIO_DBG_ERROR, "%s: ieee80211_probereq_get failed!\n",
-+ __func__);
-+ return -ENOMEM;
-+ }
-+
-+ /* will be unlocked in xradio_scan_work() */
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (frame.skb) {
-+ int ret;
-+ if (priv->if_id == 0)
-+ xradio_remove_wps_p2p_ie(&frame);
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ if (0 == ret) {
-+ /* Host want to be the probe responder. */
-+ ret = wsm_set_probe_responder(priv, true);
-+ }
-+ if (ret) {
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+ dev_kfree_skb(frame.skb);
-+ scan_printk(XRADIO_DBG_ERROR, "%s: wsm_set_probe_responder failed: %d.\n",
-+ __func__, ret);
-+ return ret;
-+ }
-+ }
-+
-+ wsm_lock_tx(hw_priv);
-+ BUG_ON(hw_priv->scan.req);
-+ hw_priv->scan.sched_req = req;
-+ hw_priv->scan.n_ssids = 0;
-+ hw_priv->scan.status = 0;
-+ hw_priv->scan.begin = &req->channels[0];
-+ hw_priv->scan.curr = hw_priv->scan.begin;
-+ hw_priv->scan.end = &req->channels[req->n_channels];
-+ hw_priv->scan.output_power = hw_priv->output_power;
-+
-+ for (i = 0; i < req->n_ssids; ++i) {
-+ u8 j;
-+ struct wsm_ssid *dst = &hw_priv->scan.ssids[hw_priv->scan.n_ssids];
-+ BUG_ON(req->ssids[i].ssid_len > sizeof(dst->ssid));
-+ memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid));
-+ dst->length = req->ssids[i].ssid_len;
-+ ++hw_priv->scan.n_ssids;
-+ scan_printk(XRADIO_DBG_NIY, "SSID %d\n",i);
-+ for(j=0; jssids[i].ssid_len; j++)
-+ scan_printk(XRADIO_DBG_NIY, "0x%x\n", req->ssids[i].ssid[j]);
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ if (frame.skb)
-+ dev_kfree_skb(frame.skb);
-+ queue_work(hw_priv->workqueue, &hw_priv->scan.swork);
-+ scan_printk(XRADIO_DBG_NIY, "<-- Scheduled scan request.\n");
-+ return 0;
-+}
-+#endif /*ROAM_OFFLOAD*/
-+
-+void xradio_scan_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv = container_of(work,
-+ struct xradio_common,
-+ scan.work);
-+ struct xradio_vif *priv;
-+ struct ieee80211_channel **it;
-+ struct wsm_scan scan = {
-+ .scanType = WSM_SCAN_TYPE_FOREGROUND,
-+ .scanFlags = 0, /* TODO:COMBO */
-+ //.scanFlags = WSM_SCAN_FLAG_SPLIT_METHOD, /* TODO:COMBO */
-+ };
-+ bool first_run;
-+ int i;
-+ const u32 ProbeRequestTime = 2;
-+ const u32 ChannelRemainTime = 15;
-+ u32 maxChannelTime;
-+ struct cfg80211_scan_info scan_info;
-+
-+
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
-+
-+ /*TODO: COMBO: introduce locking so vif is not removed in meanwhile */
-+ if (!priv) {
-+ scan_printk(XRADIO_DBG_WARN, "interface removed, "
-+ "ignoring scan work\n");
-+ return;
-+ }
-+
-+ if (priv->if_id)
-+ scan.scanFlags |= WSM_FLAG_MAC_INSTANCE_1;
-+ else
-+ scan.scanFlags &= ~WSM_FLAG_MAC_INSTANCE_1;
-+
-+ /* No need to set WSM_SCAN_FLAG_FORCE_BACKGROUND in BSS_LOSS work.
-+ * yangfh 2015-11-11 18:45:02 */
-+ //xradio_for_each_vif(hw_priv, vif, i) {
-+ // if (!vif)
-+ // continue;
-+ // if (vif->bss_loss_status > XRADIO_BSS_LOSS_NONE)
-+ // scan.scanFlags |= WSM_SCAN_FLAG_FORCE_BACKGROUND;
-+ //}
-+
-+ first_run = (hw_priv->scan.begin == hw_priv->scan.curr &&
-+ hw_priv->scan.begin != hw_priv->scan.end);
-+ if (first_run) {
-+ /* Firmware gets crazy if scan request is sent
-+ * when STA is joined but not yet associated.
-+ * Force unjoin in this case. */
-+ if (cancel_delayed_work_sync(&priv->join_timeout) > 0)
-+ xradio_join_timeout(&priv->join_timeout.work);
-+ }
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (first_run) {
-+#if 0
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA &&
-+ !(priv->powersave_mode.pmMode & WSM_PSM_PS)) {
-+ struct wsm_set_pm pm = priv->powersave_mode;
-+ pm.pmMode = WSM_PSM_PS;
-+ xradio_set_pm(priv, &pm);
-+ } else
-+#endif
-+ if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR) {
-+ /* FW bug: driver has to restart p2p-dev mode
-+ * after scan */
-+ xradio_disable_listening(priv);
-+ }
-+ }
-+
-+ if (!hw_priv->scan.req || (hw_priv->scan.curr == hw_priv->scan.end)) {
-+ if (hw_priv->scan.output_power != hw_priv->output_power) {
-+ /* TODO:COMBO: Change when mac80211 implementation
-+ * is available for output power also */
-+ WARN_ON(wsm_set_output_power(hw_priv, hw_priv->output_power * 10,
-+ priv->if_id));
-+ }
-+
-+#if 0
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA &&
-+ !(priv->powersave_mode.pmMode & WSM_PSM_PS))
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+#endif
-+
-+ if (hw_priv->scan.status < 0)
-+ scan_printk(XRADIO_DBG_ERROR, "Scan failed (%d).\n", hw_priv->scan.status);
-+ else if (hw_priv->scan.req)
-+ scan_printk(XRADIO_DBG_NIY, "Scan completed.\n");
-+ else
-+ scan_printk(XRADIO_DBG_NIY, "Scan canceled.\n");
-+
-+ hw_priv->scan.req = NULL;
-+ xradio_scan_restart_delayed(priv);
-+ wsm_unlock_tx(hw_priv);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ memset(&scan_info, 0, sizeof(scan_info));
-+ scan_info.aborted = hw_priv->scan.status ? 1 : 0;
-+ ieee80211_scan_completed(hw_priv->hw, &scan_info);
-+ up(&hw_priv->scan.lock);
-+ return;
-+
-+ } else {
-+ struct ieee80211_channel *first = *hw_priv->scan.curr;
-+ for (it = hw_priv->scan.curr + 1, i = 1;
-+ it != hw_priv->scan.end && i < WSM_SCAN_MAX_NUM_OF_CHANNELS;
-+ ++it, ++i) {
-+ if ((*it)->band != first->band)
-+ break;
-+ if (((*it)->flags ^ first->flags) & IEEE80211_CHAN_NO_IR)
-+ break;
-+ if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
-+ (*it)->max_power != first->max_power)
-+ break;
-+ }
-+ scan.band = first->band;
-+
-+ if (hw_priv->scan.req->no_cck)
-+ scan.maxTransmitRate = WSM_TRANSMIT_RATE_6;
-+ else
-+ scan.maxTransmitRate = WSM_TRANSMIT_RATE_1;
-+
-+ /* TODO: Is it optimal? */
-+ scan.numOfProbeRequests = (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2;
-+
-+ scan.numOfSSIDs = hw_priv->scan.n_ssids;
-+ scan.ssids = &hw_priv->scan.ssids[0];
-+ scan.numOfChannels = it - hw_priv->scan.curr;
-+ /* TODO: Is it optimal? */
-+ scan.probeDelay = 100;
-+ /* It is not stated in WSM specification, however
-+ * FW team says that driver may not use FG scan
-+ * when joined. */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ scan.scanType = WSM_SCAN_TYPE_BACKGROUND;
-+ scan.scanFlags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
-+ }
-+ scan.ch = kzalloc(sizeof(struct wsm_scan_ch[it - hw_priv->scan.curr]), GFP_KERNEL);
-+ if (!scan.ch) {
-+ hw_priv->scan.status = -ENOMEM;
-+ scan_printk(XRADIO_DBG_ERROR, "xr_kzalloc wsm_scan_ch failed.\n");
-+ goto fail;
-+ }
-+ maxChannelTime = (scan.numOfSSIDs * scan.numOfProbeRequests *ProbeRequestTime) +
-+ ChannelRemainTime;
-+ maxChannelTime = (maxChannelTime < 35) ? 35 : maxChannelTime;
-+ for (i = 0; i < scan.numOfChannels; ++i) {
-+ scan.ch[i].number = hw_priv->scan.curr[i]->hw_value;
-+
-+
-+ if (hw_priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) {
-+ scan.ch[i].minChannelTime = 50;
-+ scan.ch[i].maxChannelTime = 110;
-+ } else {
-+ scan.ch[i].minChannelTime = 15;
-+ scan.ch[i].maxChannelTime = maxChannelTime;
-+ }
-+
-+
-+ }
-+
-+ if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
-+ hw_priv->scan.output_power != first->max_power) {
-+ hw_priv->scan.output_power = first->max_power;
-+ /* TODO:COMBO: Change after mac80211 implementation
-+ * complete */
-+ WARN_ON(wsm_set_output_power(hw_priv, hw_priv->scan.output_power * 10,
-+ priv->if_id));
-+ }
-+
-+ down(&hw_priv->scan.status_lock);
-+ hw_priv->scan.status = xradio_scan_start(priv, &scan);
-+
-+ kfree(scan.ch);
-+ if (WARN_ON(hw_priv->scan.status)) {
-+ scan_printk(XRADIO_DBG_ERROR, "scan failed, status=%d.\n",
-+ hw_priv->scan.status);
-+ up(&hw_priv->scan.status_lock);
-+ goto fail;
-+ }
-+ up(&hw_priv->scan.status_lock);
-+ hw_priv->scan.curr = it;
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return;
-+
-+fail:
-+ hw_priv->scan.curr = hw_priv->scan.end;
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ queue_work(hw_priv->workqueue, &hw_priv->scan.work);
-+ return;
-+}
-+
-+#ifdef ROAM_OFFLOAD
-+void xradio_sched_scan_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv = container_of(work, struct xradio_common,
-+ scan.swork);
-+ struct wsm_scan scan;
-+ struct wsm_ssid scan_ssid;
-+ int i;
-+ struct xradio_vif *priv = NULL;
-+
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
-+ if (unlikely(!priv)) {
-+ WARN_ON(1);
-+ return;
-+ }
-+
-+ spin_unlock(&priv->vif_lock);
-+ /* Firmware gets crazy if scan request is sent
-+ * when STA is joined but not yet associated.
-+ * Force unjoin in this case. */
-+ if (cancel_delayed_work_sync(&priv->join_timeout) > 0) {
-+ xradio_join_timeout(&priv->join_timeout.work);
-+ }
-+ mutex_lock(&hw_priv->conf_mutex);
-+ hw_priv->auto_scanning = 1;
-+ scan.band = 0;
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA)
-+ scan.scanType = 3; /* auto background */
-+ else
-+ scan.scanType = 2; /* auto foreground */
-+
-+ scan.scanFlags = 0x01; /* bit 0 set => forced background scan */
-+ scan.maxTransmitRate = WSM_TRANSMIT_RATE_6;
-+ scan.autoScanInterval = (0xba << 24)|(30 * 1024); /* 30 seconds, -70 rssi */
-+ scan.numOfProbeRequests = 1;
-+ //scan.numOfChannels = 11;
-+ scan.numOfChannels = hw_priv->num_scanchannels;
-+ scan.numOfSSIDs = 1;
-+ scan.probeDelay = 100;
-+ scan_ssid.length = priv->ssid_length;
-+ memcpy(scan_ssid.ssid, priv->ssid, priv->ssid_length);
-+ scan.ssids = &scan_ssid;
-+
-+ scan.ch = xr_kzalloc(sizeof(struct wsm_scan_ch[scan.numOfChannels]), false);
-+ if (!scan.ch) {
-+ scan_printk(XRADIO_DBG_ERROR, "xr_kzalloc wsm_scan_ch failed.\n");
-+ hw_priv->scan.status = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ for (i = 0; i < scan.numOfChannels; i++) {
-+ scan.ch[i].number = hw_priv->scan_channels[i].number;
-+ scan.ch[i].minChannelTime = hw_priv->scan_channels[i].minChannelTime;
-+ scan.ch[i].maxChannelTime = hw_priv->scan_channels[i].maxChannelTime;
-+ scan.ch[i].txPowerLevel = hw_priv->scan_channels[i].txPowerLevel;
-+ }
-+
-+#if 0
-+ for (i = 1; i <= scan.numOfChannels; i++) {
-+ scan.ch[i-1].number = i;
-+ scan.ch[i-1].minChannelTime = 10;
-+ scan.ch[i-1].maxChannelTime = 40;
-+ }
-+#endif
-+
-+ hw_priv->scan.status = xradio_sched_scan_start(priv, &scan);
-+ kfree(scan.ch);
-+ if (hw_priv->scan.status) {
-+ scan_printk(XRADIO_DBG_ERROR, "scan failed, status=%d.\n",
-+ hw_priv->scan.status);
-+ goto fail;
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return;
-+
-+fail:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ queue_work(hw_priv->workqueue, &hw_priv->scan.swork);
-+ return;
-+}
-+
-+void xradio_hw_sched_scan_stop(struct xradio_common *hw_priv)
-+{
-+ struct xradio_vif *priv = NULL;
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv,hw_priv->scan.if_id);
-+ if (unlikely(!priv))
-+ return;
-+
-+ spin_unlock(&priv->vif_lock);
-+ wsm_stop_scan(hw_priv, priv->if_id);
-+
-+ return;
-+}
-+#endif /*ROAM_OFFLOAD*/
-+
-+
-+static void xradio_scan_restart_delayed(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+
-+ if (priv->delayed_link_loss) {
-+ int tmo = hw_priv->scan.direct_probe ? 0 : priv->cqm_beacon_loss_count;
-+
-+ priv->delayed_link_loss = 0;
-+ /* Restart beacon loss timer and requeue
-+ BSS loss work. */
-+ scan_printk(XRADIO_DBG_WARN, "[CQM] Requeue BSS loss in %d "
-+ "beacons.\n", tmo);
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ queue_delayed_work(hw_priv->workqueue, &priv->bss_loss_work,
-+ tmo * HZ / 10);
-+
-+ }
-+
-+ /* FW bug: driver has to restart p2p-dev mode after scan. */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR) {
-+ /*xradio_enable_listening(priv);*/
-+ WARN_ON(1);
-+ xradio_update_filtering(priv);
-+ scan_printk(XRADIO_DBG_WARN, "driver has to restart "
-+ "p2p-dev mode after scan");
-+ }
-+
-+ if (atomic_xchg(&priv->delayed_unjoin, 0)) {
-+ if (queue_work(hw_priv->workqueue, &priv->unjoin_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+}
-+
-+static void xradio_scan_complete(struct xradio_common *hw_priv, int if_id)
-+{
-+ struct xradio_vif *priv;
-+ atomic_xchg(&hw_priv->recent_scan, 0);
-+
-+
-+ if (hw_priv->scan.direct_probe) {
-+ mutex_lock(&hw_priv->conf_mutex);
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, if_id);
-+ if (priv) {
-+ scan_printk(XRADIO_DBG_MSG, "Direct probe complete.\n");
-+ xradio_scan_restart_delayed(priv);
-+ } else {
-+ scan_printk(XRADIO_DBG_MSG, "Direct probe complete without interface!\n");
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ hw_priv->scan.direct_probe = 0;
-+ up(&hw_priv->scan.lock);
-+ wsm_unlock_tx(hw_priv);
-+ } else {
-+ xradio_scan_work(&hw_priv->scan.work);
-+ }
-+}
-+
-+void xradio_scan_complete_cb(struct xradio_common *hw_priv,
-+ struct wsm_scan_complete *arg)
-+{
-+ struct xradio_vif *priv = xrwl_hwpriv_to_vifpriv(hw_priv,
-+ hw_priv->scan.if_id);
-+
-+
-+ if (unlikely(!priv))
-+ return;
-+
-+#ifdef ROAM_OFFLOAD
-+ if (hw_priv->auto_scanning)
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.timeout, 0);
-+#endif /*ROAM_OFFLOAD*/
-+
-+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
-+ /* STA is stopped. */
-+ spin_unlock(&priv->vif_lock);
-+ scan_printk(XRADIO_DBG_WARN, "%s: priv->mode UNSPECIFIED.\n", __func__);
-+ return;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+
-+ /*
-+ if(hw_priv->scan.status == -ETIMEDOUT)
-+ scan_printk(XRADIO_DBG_WARN, "Scan timeout already occured. "
-+ "Don't cancel work");
-+ if ((hw_priv->scan.status != -ETIMEDOUT) &&
-+ (cancel_delayed_work_sync(&hw_priv->scan.timeout) > 0)) {
-+ hw_priv->scan.status = 1;
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.timeout, 0);
-+ }
-+ */ // should not involve status as a condition
-+
-+ if (cancel_delayed_work_sync(&hw_priv->scan.timeout) > 0) {
-+ down(&hw_priv->scan.status_lock);
-+ hw_priv->scan.status = 1;
-+ up(&hw_priv->scan.status_lock);
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.timeout, 0);
-+ }
-+}
-+
-+void xradio_scan_timeout(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, scan.timeout.work);
-+
-+
-+ if (likely(atomic_xchg(&hw_priv->scan.in_progress, 0))) {
-+ if (hw_priv->scan.status > 0)
-+ hw_priv->scan.status = 0;
-+ else if (!hw_priv->scan.status) {
-+ scan_printk(XRADIO_DBG_WARN, "Timeout waiting for scan "
-+ "complete notification.\n");
-+ hw_priv->scan.status = -ETIMEDOUT;
-+ hw_priv->scan.curr = hw_priv->scan.end;
-+ WARN_ON(wsm_stop_scan(hw_priv, hw_priv->scan.if_id ? 1 : 0));
-+ }
-+ xradio_scan_complete(hw_priv, hw_priv->scan.if_id);
-+#ifdef ROAM_OFFLOAD
-+ } else if (hw_priv->auto_scanning) {
-+ hw_priv->auto_scanning = 0;
-+ ieee80211_sched_scan_results(hw_priv->hw);
-+#endif /*ROAM_OFFLOAD*/
-+ }
-+}
-+
-+void xradio_probe_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, scan.probe_work.work);
-+ struct xradio_vif *priv;
-+ u8 queueId = xradio_queue_get_queue_id(hw_priv->pending_frame_id);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queueId];
-+ const struct xradio_txpriv *txpriv;
-+ struct wsm_tx *wsm;
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
-+ };
-+ struct wsm_ssid ssids[1] = {{
-+ .length = 0,
-+ } };
-+ struct wsm_scan_ch ch[1] = {{
-+ .minChannelTime = 0,
-+ .maxChannelTime = 10,
-+ } };
-+ struct wsm_scan scan = {
-+ .scanType = WSM_SCAN_TYPE_FOREGROUND,
-+ .numOfProbeRequests = 1,
-+ .probeDelay = 0,
-+ .numOfChannels = 1,
-+ .ssids = ssids,
-+ .ch = ch,
-+ };
-+ u8 *ies;
-+ size_t ies_len;
-+ int ret = 1;
-+ scan_printk(XRADIO_DBG_MSG, "%s:Direct probe.\n", __func__);
-+
-+ BUG_ON(queueId >= 4);
-+ BUG_ON(!hw_priv->channel);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (unlikely(down_trylock(&hw_priv->scan.lock))) {
-+ /* Scan is already in progress. Requeue self. */
-+ schedule();
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.probe_work,
-+ HZ / 10);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return;
-+ }
-+
-+ if (xradio_queue_get_skb(queue, hw_priv->pending_frame_id, &frame.skb, &txpriv)) {
-+ up(&hw_priv->scan.lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ wsm_unlock_tx(hw_priv);
-+ scan_printk(XRADIO_DBG_ERROR, "%s:xradio_queue_get_skb error!\n", __func__);
-+ return;
-+ }
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, txpriv->if_id);
-+ if (!priv) {
-+ up(&hw_priv->scan.lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ scan_printk(XRADIO_DBG_ERROR, "%s:priv error!\n", __func__);
-+ return;
-+ }
-+ wsm = (struct wsm_tx *)frame.skb->data;
-+ scan.maxTransmitRate = wsm->maxTxRate;
-+ scan.band = (hw_priv->channel->band == NL80211_BAND_5GHZ) ?
-+ WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ scan.scanType = WSM_SCAN_TYPE_BACKGROUND;
-+ scan.scanFlags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
-+ if (priv->if_id)
-+ scan.scanFlags |= WSM_FLAG_MAC_INSTANCE_1;
-+ else
-+ scan.scanFlags &= ~WSM_FLAG_MAC_INSTANCE_1;
-+ }
-+
-+ /* No need to set WSM_SCAN_FLAG_FORCE_BACKGROUND in BSS_LOSS work.
-+ * yangfh 2015-11-11 18:45:02 */
-+ //xradio_for_each_vif(hw_priv, vif, i) {
-+ // if (!vif)
-+ // continue;
-+ // if (vif->bss_loss_status > XRADIO_BSS_LOSS_NONE)
-+ // scan.scanFlags |= WSM_SCAN_FLAG_FORCE_BACKGROUND;
-+ //}
-+
-+ ch[0].number = hw_priv->channel->hw_value;
-+ skb_pull(frame.skb, txpriv->offset);
-+ ies = &frame.skb->data[sizeof(struct ieee80211_hdr_3addr)];
-+ ies_len = frame.skb->len - sizeof(struct ieee80211_hdr_3addr);
-+
-+ if (ies_len) {
-+ u8 *ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
-+ if (ssidie && ssidie[1] && ssidie[1] <= sizeof(ssids[0].ssid)) {
-+ u8 *nextie = &ssidie[2 + ssidie[1]];
-+ /* Remove SSID from the IE list. It has to be provided
-+ * as a separate argument in xradio_scan_start call */
-+
-+ /* Store SSID localy */
-+ ssids[0].length = ssidie[1];
-+ memcpy(ssids[0].ssid, &ssidie[2], ssids[0].length);
-+ scan.numOfSSIDs = 1;
-+
-+ /* Remove SSID from IE list */
-+ ssidie[1] = 0;
-+ memmove(&ssidie[2], nextie, &ies[ies_len] - nextie);
-+ skb_trim(frame.skb, frame.skb->len - ssids[0].length);
-+ }
-+ }
-+
-+ if (priv->if_id == 0)
-+ xradio_remove_wps_p2p_ie(&frame);
-+
-+ /* FW bug: driver has to restart p2p-dev mode after scan */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR) {
-+ WARN_ON(1);
-+ /*xradio_disable_listening(priv);*/
-+ }
-+ ret = WARN_ON(wsm_set_template_frame(hw_priv, &frame,
-+ priv->if_id));
-+
-+ hw_priv->scan.direct_probe = 1;
-+ hw_priv->scan.if_id = priv->if_id;
-+ if (!ret) {
-+ wsm_flush_tx(hw_priv);
-+ ret = WARN_ON(xradio_scan_start(priv, &scan));
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ skb_push(frame.skb, txpriv->offset);
-+ if (!ret)
-+ IEEE80211_SKB_CB(frame.skb)->flags |= IEEE80211_TX_STAT_ACK;
-+
-+ BUG_ON(xradio_queue_remove(queue, hw_priv->pending_frame_id));
-+
-+ if (ret) {
-+ hw_priv->scan.direct_probe = 0;
-+ up(&hw_priv->scan.lock);
-+ wsm_unlock_tx(hw_priv);
-+ }
-+
-+ return;
-+}
-diff --git a/drivers/net/wireless/xradio/scan.h b/drivers/net/wireless/xradio/scan.h
-new file mode 100644
-index 0000000..5c520ed
---- /dev/null
-+++ b/drivers/net/wireless/xradio/scan.h
-@@ -0,0 +1,71 @@
-+/*
-+ * Scan interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#ifndef SCAN_H_INCLUDED
-+#define SCAN_H_INCLUDED
-+
-+#include
-+#include "wsm.h"
-+
-+/* external */ struct sk_buff;
-+/* external */ struct cfg80211_scan_request;
-+/* external */ struct ieee80211_channel;
-+/* external */ struct ieee80211_hw;
-+/* external */ struct work_struct;
-+
-+#define SCAN_MAX_DELAY (3*HZ) //3s, add by yangfh for connect
-+
-+struct xradio_scan {
-+ struct semaphore lock;
-+ struct work_struct work;
-+#ifdef ROAM_OFFLOAD
-+ struct work_struct swork; /* scheduled scan work */
-+ struct cfg80211_sched_scan_request *sched_req;
-+#endif /*ROAM_OFFLOAD*/
-+ struct delayed_work timeout;
-+ struct cfg80211_scan_request *req;
-+ struct ieee80211_channel **begin;
-+ struct ieee80211_channel **curr;
-+ struct ieee80211_channel **end;
-+ struct wsm_ssid ssids[WSM_SCAN_MAX_NUM_OF_SSIDS];
-+ int output_power;
-+ int n_ssids;
-+ //add by liwei, for h64 ping WS550 BUG
-+ struct semaphore status_lock;
-+ int status;
-+ atomic_t in_progress;
-+ /* Direct probe requests workaround */
-+ struct delayed_work probe_work;
-+ int direct_probe;
-+ u8 if_id;
-+};
-+
-+int xradio_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_scan_request *req);
-+#ifdef ROAM_OFFLOAD
-+int xradio_hw_sched_scan_start(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct cfg80211_sched_scan_request *req,
-+ struct ieee80211_sched_scan_ies *ies);
-+void xradio_hw_sched_scan_stop(struct xradio_common *priv);
-+void xradio_sched_scan_work(struct work_struct *work);
-+#endif /*ROAM_OFFLOAD*/
-+void xradio_scan_work(struct work_struct *work);
-+void xradio_scan_timeout(struct work_struct *work);
-+void xradio_scan_complete_cb(struct xradio_common *priv,
-+ struct wsm_scan_complete *arg);
-+
-+/* ******************************************************************** */
-+/* Raw probe requests TX workaround */
-+void xradio_probe_work(struct work_struct *work);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/sdio.c b/drivers/net/wireless/xradio/sdio.c
-new file mode 100644
-index 0000000..13d4eb5
---- /dev/null
-+++ b/drivers/net/wireless/xradio/sdio.c
-@@ -0,0 +1,246 @@
-+/*
-+ * SDIO driver for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "sdio.h"
-+#include "main.h"
-+
-+/* sdio vendor id and device id*/
-+#define SDIO_VENDOR_ID_XRADIO 0x0020
-+#define SDIO_DEVICE_ID_XRADIO 0x2281
-+static const struct sdio_device_id xradio_sdio_ids[] = {
-+ { SDIO_DEVICE(SDIO_VENDOR_ID_XRADIO, SDIO_DEVICE_ID_XRADIO) },
-+ //{ SDIO_DEVICE(SDIO_ANY_ID, SDIO_ANY_ID) },
-+ { /* end: all zeroes */ },
-+};
-+
-+/* sbus_ops implemetation */
-+int sdio_data_read(struct xradio_common* self, unsigned int addr,
-+ void *dst, int count)
-+{
-+ int ret = sdio_memcpy_fromio(self->sdio_func, dst, addr, count);
-+// printk("sdio_memcpy_fromio 0x%x:%d ret %d\n", addr, count, ret);
-+// print_hex_dump_bytes("sdio read ", 0, dst, min(count,32));
-+ return ret;
-+}
-+
-+int sdio_data_write(struct xradio_common* self, unsigned int addr,
-+ const void *src, int count)
-+{
-+ int ret = sdio_memcpy_toio(self->sdio_func, addr, (void *)src, count);
-+// printk("sdio_memcpy_toio 0x%x:%d ret %d\n", addr, count, ret);
-+// print_hex_dump_bytes("sdio write", 0, src, min(count,32));
-+ return ret;
-+}
-+
-+void sdio_lock(struct xradio_common* self)
-+{
-+ sdio_claim_host(self->sdio_func);
-+}
-+
-+void sdio_unlock(struct xradio_common *self)
-+{
-+ sdio_release_host(self->sdio_func);
-+}
-+
-+size_t sdio_align_len(struct xradio_common *self, size_t size)
-+{
-+ return sdio_align_size(self->sdio_func, size);
-+}
-+
-+int sdio_set_blk_size(struct xradio_common *self, size_t size)
-+{
-+ return sdio_set_block_size(self->sdio_func, size);
-+}
-+
-+extern void xradio_irq_handler(struct xradio_common*);
-+
-+static irqreturn_t sdio_irq_handler(int irq, void *dev_id)
-+{
-+ struct sdio_func *func = (struct sdio_func*) dev_id;
-+ struct xradio_common *self = sdio_get_drvdata(func);
-+ if (self != NULL)
-+ xradio_irq_handler(self);
-+ return IRQ_HANDLED;
-+}
-+
-+static int sdio_enableint(struct sdio_func* func)
-+{
-+ int ret = 0;
-+ u8 cccr;
-+ int func_num;
-+
-+ sdio_claim_host(func);
-+
-+ /* Hack to access Fuction-0 */
-+ func_num = func->num;
-+ func->num = 0;
-+ cccr = sdio_readb(func, SDIO_CCCR_IENx, &ret);
-+ cccr |= BIT(0); /* Master interrupt enable ... */
-+ cccr |= BIT(func_num); /* ... for our function */
-+ sdio_writeb(func, cccr, SDIO_CCCR_IENx, &ret);
-+
-+ /* Restore the WLAN function number */
-+ func->num = func_num;
-+
-+ sdio_release_host(func);
-+
-+ return ret;
-+}
-+
-+int sdio_pm(struct xradio_common *self, bool suspend)
-+{
-+ int ret = 0;
-+ if (suspend) {
-+ /* Notify SDIO that XRADIO will remain powered during suspend */
-+ ret = sdio_set_host_pm_flags(self->sdio_func, MMC_PM_KEEP_POWER);
-+ if (ret)
-+ dev_dbg(&self->sdio_func->dev, "Error setting SDIO pm flags: %i\n", ret);
-+ }
-+
-+ return ret;
-+}
-+
-+static const struct of_device_id xradio_sdio_of_match_table[] = {
-+ { .compatible = "xradio,xr819" },
-+ { }
-+};
-+
-+static int xradio_probe_of(struct sdio_func *func)
-+{
-+ struct device *dev = &func->dev;
-+ struct device_node *np = dev->of_node;
-+ const struct of_device_id *of_id;
-+ int irq;
-+ int ret;
-+
-+ of_id = of_match_node(xradio_sdio_of_match_table, np);
-+ if (!of_id)
-+ return -ENODEV;
-+
-+ //pdev_data->family = of_id->data;
-+
-+ irq = irq_of_parse_and_map(np, 0);
-+ if (!irq) {
-+ dev_err(dev, "No irq in platform data\n");
-+ return -EINVAL;
-+ }
-+
-+ ret = devm_request_irq(dev, irq, sdio_irq_handler, 0, "xradio", func);
-+ if (ret) {
-+ dev_err(dev, "Failed to request irq_wakeup.\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Probe Function to be called by SDIO stack when device is discovered */
-+static int sdio_probe(struct sdio_func *func,
-+ const struct sdio_device_id *id)
-+{
-+ dev_dbg(&func->dev, "XRadio Device:sdio clk=%d\n",
-+ func->card->host->ios.clock);
-+ dev_dbg(&func->dev, "sdio func->class=%x\n", func->class);
-+ dev_dbg(&func->dev, "sdio_vendor: 0x%04x\n", func->vendor);
-+ dev_dbg(&func->dev, "sdio_device: 0x%04x\n", func->device);
-+ dev_dbg(&func->dev, "Function#: 0x%04x\n", func->num);
-+
-+#if 0 //for odly and sdly debug.
-+{
-+ u32 sdio_param = 0;
-+ sdio_param = readl(__io_address(0x01c20088));
-+ sdio_param &= ~(0xf<<8);
-+ sdio_param |= 3<<8;
-+ sdio_param &= ~(0xf<<20);
-+ sdio_param |= s_dly<<20;
-+ writel(sdio_param, __io_address(0x01c20088));
-+ sbus_printk(XRADIO_DBG_ALWY, "%s: 0x01c20088=0x%08x\n", __func__, sdio_param);
-+}
-+#endif
-+
-+ xradio_probe_of(func);
-+
-+ func->card->quirks |= MMC_QUIRK_BROKEN_BYTE_MODE_512;
-+ sdio_claim_host(func);
-+ sdio_enable_func(func);
-+ sdio_release_host(func);
-+
-+ sdio_enableint(func);
-+
-+ xradio_core_init(func);
-+
-+ try_module_get(func->dev.driver->owner);
-+ return 0;
-+}
-+/* Disconnect Function to be called by SDIO stack when
-+ * device is disconnected */
-+static void sdio_remove(struct sdio_func *func)
-+{
-+ sdio_claim_host(func);
-+ sdio_disable_func(func);
-+ sdio_release_host(func);
-+ module_put(func->dev.driver->owner);
-+}
-+
-+static int sdio_suspend(struct device *dev)
-+{
-+ int ret = 0;
-+ /*
-+ struct sdio_func *func = dev_to_sdio_func(dev);
-+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
-+ if (ret)
-+ sbus_printk(XRADIO_DBG_ERROR, "set MMC_PM_KEEP_POWER error\n");
-+ */
-+ return ret;
-+}
-+
-+static int sdio_resume(struct device *dev)
-+{
-+ return 0;
-+}
-+
-+static const struct dev_pm_ops sdio_pm_ops = {
-+ .suspend = sdio_suspend,
-+ .resume = sdio_resume,
-+};
-+
-+static struct sdio_driver sdio_driver = {
-+ .name = "xradio_wlan",
-+ .id_table = xradio_sdio_ids,
-+ .probe = sdio_probe,
-+ .remove = sdio_remove,
-+ .drv = {
-+ .owner = THIS_MODULE,
-+ .pm = &sdio_pm_ops,
-+ }
-+};
-+
-+
-+int xradio_sdio_register(){
-+ return sdio_register_driver(&sdio_driver);
-+}
-+
-+void xradio_sdio_unregister(){
-+ sdio_unregister_driver(&sdio_driver);
-+}
-+
-+MODULE_DEVICE_TABLE(sdio, xradio_sdio_ids);
-diff --git a/drivers/net/wireless/xradio/sdio.h b/drivers/net/wireless/xradio/sdio.h
-new file mode 100644
-index 0000000..ea3c45a
---- /dev/null
-+++ b/drivers/net/wireless/xradio/sdio.h
-@@ -0,0 +1,17 @@
-+#ifndef __XRADIO_SDIO_H
-+#define __XRADIO_SDIO_H
-+
-+size_t sdio_align_len(struct xradio_common *self, size_t size);
-+void sdio_lock(struct xradio_common *self);
-+void sdio_unlock(struct xradio_common *self);
-+int sdio_set_blk_size(struct xradio_common *self, size_t size);
-+int sdio_data_read(struct xradio_common *self, unsigned int addr, void *dst,
-+ int count);
-+int sdio_data_write(struct xradio_common *self, unsigned int addr, const void *src,
-+ int count);
-+int sdio_pm(struct xradio_common *self, bool suspend);
-+
-+int xradio_sdio_register(void);
-+void xradio_sdio_unregister(void);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/sta.c b/drivers/net/wireless/xradio/sta.c
-new file mode 100644
-index 0000000..5e9d8a2
---- /dev/null
-+++ b/drivers/net/wireless/xradio/sta.c
-@@ -0,0 +1,2199 @@
-+/*
-+ * STA APIs for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "sta.h"
-+#include "ap.h"
-+#include "keys.h"
-+#include "fwio.h"
-+#include "bh.h"
-+#include "wsm.h"
-+#ifdef ROAM_OFFLOAD
-+#include
-+#endif /*ROAM_OFFLOAD*/
-+
-+#include "net/mac80211.h"
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+#include
-+#endif
-+
-+#define WEP_ENCRYPT_HDR_SIZE 4
-+#define WEP_ENCRYPT_TAIL_SIZE 4
-+#define WPA_ENCRYPT_HDR_SIZE 8
-+#define WPA_ENCRYPT_TAIL_SIZE 12
-+#define WPA2_ENCRYPT_HDR_SIZE 8
-+#define WPA2_ENCRYPT_TAIL_SIZE 8
-+#define WAPI_ENCRYPT_HDR_SIZE 18
-+#define WAPI_ENCRYPT_TAIL_SIZE 16
-+#define MAX_ARP_REPLY_TEMPLATE_SIZE 120
-+
-+static inline void __xradio_free_event_queue(struct list_head *list)
-+{
-+ while (!list_empty(list)) {
-+ struct xradio_wsm_event *event =
-+ list_first_entry(list, struct xradio_wsm_event,link);
-+ list_del(&event->link);
-+ kfree(event);
-+ }
-+}
-+
-+static inline void __xradio_bf_configure(struct xradio_vif *priv)
-+{
-+ priv->bf_table.numOfIEs = __cpu_to_le32(3);
-+ priv->bf_table.entry[0].ieId = WLAN_EID_VENDOR_SPECIFIC;
-+ priv->bf_table.entry[0].actionFlags =
-+ WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED;
-+
-+ priv->bf_table.entry[0].oui[0] = 0x50;
-+ priv->bf_table.entry[0].oui[1] = 0x6F;
-+ priv->bf_table.entry[0].oui[2] = 0x9A;
-+
-+ priv->bf_table.entry[1].ieId = WLAN_EID_ERP_INFO;
-+ priv->bf_table.entry[1].actionFlags =
-+ WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED;
-+
-+ priv->bf_table.entry[2].ieId = WLAN_EID_HT_OPERATION;
-+ priv->bf_table.entry[2].actionFlags =
-+ WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED;
-+
-+ priv->bf_control.enabled = WSM_BEACON_FILTER_ENABLE;
-+}
-+
-+/* ******************************************************************** */
-+/* STA API */
-+
-+int xradio_start(struct ieee80211_hw *dev)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ int ret = 0;
-+
-+
-+ if (wait_event_interruptible_timeout(hw_priv->wsm_startup_done,
-+ hw_priv->driver_ready, 3*HZ) <= 0) {
-+ wiphy_err(dev->wiphy, "driver is not ready!\n");
-+ return -ETIMEDOUT;
-+ }
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ memcpy(hw_priv->mac_addr, dev->wiphy->perm_addr, ETH_ALEN);
-+ hw_priv->softled_state = 0;
-+
-+ ret = xradio_setup_mac(hw_priv);
-+ if (WARN_ON(ret)) {
-+ wiphy_err(dev->wiphy, "xradio_setup_mac failed(%d)\n", ret);
-+ goto out;
-+ }
-+
-+out:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return ret;
-+}
-+
-+void xradio_stop(struct ieee80211_hw *dev)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = NULL;
-+ LIST_HEAD(list);
-+ int i;
-+
-+ wsm_lock_tx(hw_priv);
-+ while (down_trylock(&hw_priv->scan.lock)) {
-+ /* Scan is in progress. Force it to stop. */
-+ hw_priv->scan.req = NULL;
-+ schedule();
-+ }
-+ up(&hw_priv->scan.lock);
-+
-+ cancel_delayed_work_sync(&hw_priv->scan.probe_work);
-+ cancel_delayed_work_sync(&hw_priv->scan.timeout);
-+ flush_workqueue(hw_priv->workqueue);
-+ del_timer_sync(&hw_priv->ba_timer);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ hw_priv->softled_state = 0;
-+ /* xradio_set_leds(hw_priv); */
-+
-+ spin_lock(&hw_priv->event_queue_lock);
-+ list_splice_init(&hw_priv->event_queue, &list);
-+ spin_unlock(&hw_priv->event_queue_lock);
-+ __xradio_free_event_queue(&list);
-+
-+ for (i = 0; i < 4; i++)
-+ xradio_queue_clear(&hw_priv->tx_queue[i], XRWL_ALL_IFS);
-+
-+ /* HACK! */
-+ if (atomic_xchg(&hw_priv->tx_lock, 1) != 1)
-+ wiphy_debug(dev->wiphy, "TX is force-unlocked due to stop request.\n");
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
-+ priv->listening = false;
-+ priv->delayed_link_loss = 0;
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ cancel_delayed_work_sync(&priv->link_id_gc_work);
-+ del_timer_sync(&priv->mcast_timeout);
-+ }
-+
-+ wsm_unlock_tx(hw_priv);
-+
-+ mutex_unlock(&hw_priv->conf_mutex);
-+}
-+
-+int xradio_add_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif)
-+{
-+ int ret;
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv;
-+ struct xradio_vif **drv_priv = (void *)vif->drv_priv;
-+ int i;
-+ if (atomic_read(&hw_priv->num_vifs) >= XRWL_MAX_VIFS)
-+ return -EOPNOTSUPP;
-+
-+ if (wait_event_interruptible_timeout(hw_priv->wsm_startup_done,
-+ hw_priv->driver_ready, 3*HZ) <= 0) {
-+ wiphy_err(dev->wiphy, "driver is not ready!\n");
-+ return -ETIMEDOUT;
-+ }
-+
-+ /* fix the problem that when connected,then deauth */
-+ vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
-+ vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
-+
-+ priv = xrwl_get_vif_from_ieee80211(vif);
-+ atomic_set(&priv->enabled, 0);
-+
-+ *drv_priv = priv;
-+ /* __le32 auto_calibration_mode = __cpu_to_le32(1); */
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ priv->mode = vif->type;
-+
-+ spin_lock(&hw_priv->vif_list_lock);
-+ if (atomic_read(&hw_priv->num_vifs) < XRWL_MAX_VIFS) {
-+ for (i = 0; i < XRWL_MAX_VIFS; i++)
-+ if (!memcmp(vif->addr, hw_priv->addresses[i].addr, ETH_ALEN))
-+ break;
-+ if (i == XRWL_MAX_VIFS) {
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return -EINVAL;
-+ }
-+ priv->if_id = i;
-+
-+ hw_priv->if_id_slot |= BIT(priv->if_id);
-+ priv->hw_priv = hw_priv;
-+ priv->hw = dev;
-+ priv->vif = vif;
-+ hw_priv->vif_list[priv->if_id] = vif;
-+ atomic_inc(&hw_priv->num_vifs);
-+ } else {
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return -EOPNOTSUPP;
-+ }
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ /* TODO:COMBO :Check if MAC address matches the one expected by FW */
-+ memcpy(hw_priv->mac_addr, vif->addr, ETH_ALEN);
-+
-+ /* Enable auto-calibration */
-+ /* Exception in subsequent channel switch; disabled.
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_SET_AUTO_CALIBRATION_MODE,
-+ &auto_calibration_mode, sizeof(auto_calibration_mode)));
-+ */
-+ wiphy_debug(dev->wiphy, "Interface ID:%d of type:%d added\n", priv->if_id, priv->mode);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ xradio_vif_setup(priv);
-+
-+ ret = WARN_ON(xradio_setup_mac_pvif(priv));
-+
-+ return ret;
-+}
-+
-+void xradio_remove_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct wsm_reset reset = {
-+ .reset_statistics = true,
-+ };
-+ int i;
-+ bool is_htcapie = false;
-+ struct xradio_vif *tmp_priv;
-+
-+ wiphy_warn(dev->wiphy, "!!! vif_id=%d\n", priv->if_id);
-+ atomic_set(&priv->enabled, 0);
-+ down(&hw_priv->scan.lock);
-+ if(priv->join_status == XRADIO_JOIN_STATUS_STA){
-+ if (atomic_xchg(&priv->delayed_unjoin, 0)) {
-+ wsm_unlock_tx(hw_priv);
-+ wiphy_err(dev->wiphy, "delayed_unjoin exist!\n");
-+ }
-+ cancel_work_sync(&priv->unjoin_work);
-+ wsm_lock_tx(hw_priv);
-+ xradio_unjoin_work(&priv->unjoin_work);
-+ }
-+ mutex_lock(&hw_priv->conf_mutex);
-+ xradio_tx_queues_lock(hw_priv);
-+ wsm_lock_tx(hw_priv);
-+ switch (priv->join_status) {
-+ case XRADIO_JOIN_STATUS_AP:
-+ for (i = 0; priv->link_id_map; ++i) {
-+ if (priv->link_id_map & BIT(i)) {
-+ xrwl_unmap_link(priv, i);
-+ priv->link_id_map &= ~BIT(i);
-+ }
-+ }
-+ memset(priv->link_id_db, 0,
-+ sizeof(priv->link_id_db));
-+ priv->sta_asleep_mask = 0;
-+ priv->enable_beacon = false;
-+ priv->tx_multicast = false;
-+ priv->aid0_bit_set = false;
-+ priv->buffered_multicasts = false;
-+ priv->pspoll_mask = 0;
-+ reset.link_id = 0;
-+ wsm_reset(hw_priv, &reset, priv->if_id);
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ xradio_for_each_vif(hw_priv, tmp_priv, i) {
-+ if (!tmp_priv)
-+ continue;
-+ if ((tmp_priv->join_status == XRADIO_JOIN_STATUS_STA) && tmp_priv->htcap)
-+ is_htcapie = true;
-+ }
-+
-+ if (is_htcapie) {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11N_THROTTLE;
-+ sta_printk(XRADIO_DBG_NIY, "AP REMOVE HTCAP 11N %d\n",hw_priv->vif0_throttle);
-+ } else {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ sta_printk(XRADIO_DBG_NIY, "AP REMOVE 11BG %d\n",hw_priv->vif0_throttle);
-+ }
-+ break;
-+ case XRADIO_JOIN_STATUS_MONITOR:
-+ xradio_disable_listening(priv);
-+ break;
-+ default:
-+ break;
-+ }
-+ /* TODO:COMBO: Change Queue Module */
-+ __xradio_flush(hw_priv, false, priv->if_id);
-+
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ cancel_delayed_work_sync(&priv->link_id_gc_work);
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+ cancel_delayed_work_sync(&priv->set_cts_work);
-+ cancel_delayed_work_sync(&priv->pending_offchanneltx_work);
-+
-+ del_timer_sync(&priv->mcast_timeout);
-+ /* TODO:COMBO: May be reset of these variables "delayed_link_loss and
-+ * join_status to default can be removed as dev_priv will be freed by
-+ * mac80211 */
-+ priv->delayed_link_loss = 0;
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+ wsm_unlock_tx(hw_priv);
-+
-+ if ((priv->if_id ==1) && (priv->mode == NL80211_IFTYPE_AP
-+ || priv->mode == NL80211_IFTYPE_P2P_GO)) {
-+ hw_priv->is_go_thru_go_neg = false;
-+ }
-+ spin_lock(&hw_priv->vif_list_lock);
-+ spin_lock(&priv->vif_lock);
-+ hw_priv->vif_list[priv->if_id] = NULL;
-+ hw_priv->if_id_slot &= (~BIT(priv->if_id));
-+ atomic_dec(&hw_priv->num_vifs);
-+ if (atomic_read(&hw_priv->num_vifs) == 0) {
-+ xradio_free_keys(hw_priv);
-+ memset(hw_priv->mac_addr, 0, ETH_ALEN);
-+ }
-+ spin_unlock(&priv->vif_lock);
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ priv->listening = false;
-+
-+ xradio_tx_queues_unlock(hw_priv);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ if (atomic_read(&hw_priv->num_vifs) == 0)
-+ flush_workqueue(hw_priv->workqueue);
-+ memset(priv, 0, sizeof(struct xradio_vif));
-+ up(&hw_priv->scan.lock);
-+}
-+
-+int xradio_change_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ enum nl80211_iftype new_type,
-+ bool p2p)
-+{
-+ int ret = 0;
-+ wiphy_debug(dev->wiphy, "changing interface type; new type=%d(%d), p2p=%d(%d)\n",
-+ new_type, vif->type, p2p, vif->p2p);
-+ if (new_type != vif->type || vif->p2p != p2p) {
-+ xradio_remove_interface(dev, vif);
-+ vif->type = new_type;
-+ vif->p2p = p2p;
-+ ret = xradio_add_interface(dev, vif);
-+ }
-+
-+ return ret;
-+}
-+
-+int xradio_config(struct ieee80211_hw *dev, u32 changed)
-+{
-+ int ret = 0;
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct ieee80211_conf *conf = &dev->conf;
-+ /* TODO:COMBO: adjust to multi vif interface
-+ * IEEE80211_CONF_CHANGE_IDLE is still handled per xradio_vif*/
-+ int if_id = 0;
-+ struct xradio_vif *priv;
-+
-+
-+ if (changed &
-+ (IEEE80211_CONF_CHANGE_MONITOR|IEEE80211_CONF_CHANGE_IDLE)) {
-+ /* TBD: It looks like it's transparent
-+ * there's a monitor interface present -- use this
-+ * to determine for example whether to calculate
-+ * timestamps for packets or not, do not use instead
-+ * of filter flags! */
-+ wiphy_debug(dev->wiphy, "ignore IEEE80211_CONF_CHANGE_MONITOR (%d)"
-+ "IEEE80211_CONF_CHANGE_IDLE (%d)\n",
-+ (changed & IEEE80211_CONF_CHANGE_MONITOR) ? 1 : 0,
-+ (changed & IEEE80211_CONF_CHANGE_IDLE) ? 1 : 0);
-+ return ret;
-+ }
-+
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
-+ /* TODO: IEEE80211_CONF_CHANGE_QOS */
-+ /* TODO:COMBO:Change when support is available mac80211*/
-+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
-+ /*hw_priv->output_power = conf->power_level;*/
-+ hw_priv->output_power = 20;
-+ wiphy_debug(dev->wiphy, "Config Tx power=%d, but real=%d\n",
-+ conf->power_level, hw_priv->output_power);
-+ WARN_ON(wsm_set_output_power(hw_priv, hw_priv->output_power * 10, if_id));
-+ }
-+
-+ if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) &&
-+ (hw_priv->channel != conf->chandef.chan)) {
-+ /* Switch Channel commented for CC Mode */
-+ struct ieee80211_channel *ch = conf->chandef.chan;
-+ wiphy_debug(dev->wiphy, "Freq %d (wsm ch: %d).\n",
-+ ch->center_freq, ch->hw_value);
-+ /* Earlier there was a call to __xradio_flush().
-+ Removed as deemed unnecessary */
-+ hw_priv->channel = ch;
-+ hw_priv->channel_changed = 1;
-+ }
-+
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+ return ret;
-+}
-+
-+void xradio_update_filtering(struct xradio_vif *priv)
-+{
-+ int ret;
-+ bool bssid_filtering = !priv->rx_filter.bssid;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ static struct wsm_beacon_filter_control bf_disabled = {
-+ .enabled = 0,
-+ .bcn_count = 1,
-+ };
-+ bool ap_mode = 0;
-+ static struct wsm_beacon_filter_table bf_table_auto = {
-+ .numOfIEs = __cpu_to_le32(2),
-+ .entry[0].ieId = WLAN_EID_VENDOR_SPECIFIC,
-+ .entry[0].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED,
-+ .entry[0].oui[0] = 0x50,
-+ .entry[0].oui[1] = 0x6F,
-+ .entry[0].oui[2] = 0x9A,
-+
-+ .entry[1].ieId = WLAN_EID_HT_OPERATION,
-+ .entry[1].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED,
-+ };
-+ static struct wsm_beacon_filter_control bf_auto = {
-+ .enabled = WSM_BEACON_FILTER_ENABLE |
-+ WSM_BEACON_FILTER_AUTO_ERP,
-+ .bcn_count = 1,
-+ };
-+
-+
-+ bf_auto.bcn_count = priv->bf_control.bcn_count;
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_PASSIVE)
-+ return;
-+ else if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR)
-+ bssid_filtering = false;
-+
-+ if (priv->vif && (priv->vif->type == NL80211_IFTYPE_AP))
-+ ap_mode = true;
-+ /*
-+ * When acting as p2p client being connected to p2p GO, in order to
-+ * receive frames from a different p2p device, turn off bssid filter.
-+ *
-+ * WARNING: FW dependency!
-+ * This can only be used with FW WSM371 and its successors.
-+ * In that FW version even with bssid filter turned off,
-+ * device will block most of the unwanted frames.
-+ */
-+ if (priv->vif && priv->vif->p2p)
-+ bssid_filtering = false;
-+
-+ ret = wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
-+ if (!ret && !ap_mode) {
-+ if (priv->vif) {
-+ if (priv->vif->p2p || NL80211_IFTYPE_STATION != priv->vif->type)
-+ ret = wsm_set_beacon_filter_table(hw_priv, &priv->bf_table, priv->if_id);
-+ else
-+ ret = wsm_set_beacon_filter_table(hw_priv, &bf_table_auto, priv->if_id);
-+ } else
-+ WARN_ON(1);
-+ }
-+ if (!ret && !ap_mode) {
-+ if (priv->disable_beacon_filter)
-+ ret = wsm_beacon_filter_control(hw_priv, &bf_disabled, priv->if_id);
-+ else {
-+ if (priv->vif) {
-+ if (priv->vif->p2p || NL80211_IFTYPE_STATION != priv->vif->type)
-+ ret = wsm_beacon_filter_control(hw_priv, &priv->bf_control,
-+ priv->if_id);
-+ else
-+ ret = wsm_beacon_filter_control(hw_priv, &bf_auto, priv->if_id);
-+ } else
-+ WARN_ON(1);
-+ }
-+ }
-+
-+ if (!ret)
-+ ret = wsm_set_bssid_filtering(hw_priv, bssid_filtering, priv->if_id);
-+#if 0
-+ if (!ret) {
-+ ret = wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id);
-+ }
-+#endif
-+ if (ret)
-+ wiphy_debug(priv->hw_priv->hw->wiphy, "Update filtering failed: %d.\n", ret);
-+ return;
-+}
-+
-+void xradio_update_filtering_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif,
-+ update_filtering_work);
-+
-+ xradio_update_filtering(priv);
-+}
-+
-+void xradio_set_beacon_wakeup_period_work(struct work_struct *work)
-+{
-+
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, set_beacon_wakeup_period_work);
-+
-+
-+#ifdef XRADIO_USE_LONG_DTIM_PERIOD
-+{
-+ int join_dtim_period_extend;
-+ if (priv->join_dtim_period <= 3) {
-+ join_dtim_period_extend = priv->join_dtim_period * 3;
-+ } else if (priv->join_dtim_period <= 5) {
-+ join_dtim_period_extend = priv->join_dtim_period * 2;
-+ } else {
-+ join_dtim_period_extend = priv->join_dtim_period;
-+ }
-+ WARN_ON(wsm_set_beacon_wakeup_period(priv->hw_priv,
-+ priv->beacon_int * join_dtim_period_extend >
-+ MAX_BEACON_SKIP_TIME_MS ? 1 : join_dtim_period_extend,
-+ 0, priv->if_id));
-+}
-+#else
-+ WARN_ON(wsm_set_beacon_wakeup_period(priv->hw_priv,
-+ priv->beacon_int * priv->join_dtim_period >
-+ MAX_BEACON_SKIP_TIME_MS ? 1 :priv->join_dtim_period,
-+ 0, priv->if_id));
-+#endif
-+}
-+
-+u64 xradio_prepare_multicast(struct ieee80211_hw *hw,
-+ struct netdev_hw_addr_list *mc_list)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = NULL;
-+ static u8 broadcast_ipv6[ETH_ALEN] = {
-+ 0x33, 0x33, 0x00, 0x00, 0x00, 0x01
-+ };
-+ static u8 broadcast_ipv4[ETH_ALEN] = {
-+ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01
-+ };
-+
-+ int i= 0;
-+ xradio_for_each_vif(hw_priv,priv,i) {
-+ struct netdev_hw_addr *ha = NULL;
-+ int count = 0;
-+ if ((!priv))
-+ continue;
-+
-+ /* Disable multicast filtering */
-+ priv->has_multicast_subscription = false;
-+ memset(&priv->multicast_filter, 0x00, sizeof(priv->multicast_filter));
-+ if (netdev_hw_addr_list_count(mc_list) > WSM_MAX_GRP_ADDRTABLE_ENTRIES)
-+ return 0;
-+
-+ /* Enable if requested */
-+ netdev_hw_addr_list_for_each(ha, mc_list) {
-+ sta_printk(XRADIO_DBG_MSG, "multicast: %pM\n", ha->addr);
-+ memcpy(&priv->multicast_filter.macAddress[count], ha->addr, ETH_ALEN);
-+ if (memcmp(ha->addr, broadcast_ipv4, ETH_ALEN) &&
-+ memcmp(ha->addr, broadcast_ipv6, ETH_ALEN))
-+ priv->has_multicast_subscription = true;
-+ count++;
-+ }
-+ if (count) {
-+ priv->multicast_filter.enable = __cpu_to_le32(1);
-+ priv->multicast_filter.numOfAddresses = __cpu_to_le32(count);
-+ }
-+ }
-+ return netdev_hw_addr_list_count(mc_list);
-+}
-+
-+void xradio_configure_filter(struct ieee80211_hw *hw,
-+ unsigned int changed_flags,
-+ unsigned int *total_flags,
-+ u64 multicast)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = NULL;
-+ int i = 0;
-+
-+ /* delete umac warning */
-+ if (hw_priv->vif_list[0] == NULL && hw_priv->vif_list[1] == NULL)
-+
-+ *total_flags &= ~(1<<31);
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if(NULL == priv)
-+ continue;
-+
-+#if 0
-+ bool listening = !!(*total_flags &
-+ (FIF_PROMISC_IN_BSS |
-+ FIF_OTHER_BSS |
-+ FIF_BCN_PRBRESP_PROMISC |
-+ FIF_PROBE_REQ));
-+#endif
-+
-+ *total_flags &= FIF_OTHER_BSS |
-+ FIF_FCSFAIL |
-+ FIF_BCN_PRBRESP_PROMISC |
-+ FIF_PROBE_REQ;
-+
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ priv->rx_filter.promiscuous = 0;
-+ priv->rx_filter.bssid = (*total_flags &
-+ (FIF_OTHER_BSS | FIF_PROBE_REQ)) ? 1 : 0;
-+ priv->rx_filter.fcs = (*total_flags & FIF_FCSFAIL) ? 1 : 0;
-+ priv->bf_control.bcn_count = (*total_flags &
-+ (FIF_BCN_PRBRESP_PROMISC |
-+ FIF_PROBE_REQ)) ? 1 : 0;
-+
-+ /*add for handle ap FIF_PROBE_REQ message,*/
-+ priv->rx_filter.promiscuous = 0;
-+ priv->rx_filter.fcs = 0;
-+ if(NL80211_IFTYPE_AP == priv->vif->type){
-+ priv->bf_control.bcn_count = 1;
-+ priv->rx_filter.bssid = 1;
-+ }else{
-+ priv->bf_control.bcn_count = 0;
-+ priv->rx_filter.bssid = 0;
-+ }
-+#if 0
-+ if (priv->listening ^ listening) {
-+ priv->listening = listening;
-+ wsm_lock_tx(hw_priv);
-+ xradio_update_listening(priv, listening);
-+ wsm_unlock_tx(hw_priv);
-+ }
-+#endif
-+ xradio_update_filtering(priv);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+ }
-+}
-+
-+int xradio_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
-+ u16 queue, const struct ieee80211_tx_queue_params *params)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ int ret = 0;
-+ /* To prevent re-applying PM request OID again and again*/
-+ bool old_uapsdFlags;
-+
-+ wiphy_debug(dev->wiphy, "vif %d, configuring tx\n", priv->if_id);
-+
-+ if (WARN_ON(!priv))
-+ return -EOPNOTSUPP;
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ if (queue < dev->queues) {
-+ old_uapsdFlags = priv->uapsd_info.uapsdFlags;
-+
-+ WSM_TX_QUEUE_SET(&priv->tx_queue_params, queue, 0, 0, 0);
-+ ret = wsm_set_tx_queue_params(hw_priv,
-+ &priv->tx_queue_params.params[queue],
-+ queue, priv->if_id);
-+ if (ret) {
-+ wiphy_err(dev->wiphy, "wsm_set_tx_queue_params failed!\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ WSM_EDCA_SET(&priv->edca, queue, params->aifs,
-+ params->cw_min, params->cw_max,
-+ params->txop, 0xc8, params->uapsd);
-+ /* sta role is not support the uapsd */
-+ if (priv->mode == NL80211_IFTYPE_STATION ||
-+ priv->mode == NL80211_IFTYPE_P2P_CLIENT)
-+ priv->edca.params[queue].uapsdEnable = 0;
-+
-+ ret = wsm_set_edca_params(hw_priv, &priv->edca, priv->if_id);
-+ if (ret) {
-+ wiphy_err(dev->wiphy, "wsm_set_edca_params failed!\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (priv->mode == NL80211_IFTYPE_STATION) {
-+ ret = xradio_set_uapsd_param(priv, &priv->edca);
-+ if (!ret && priv->setbssparams_done &&
-+ (priv->join_status == XRADIO_JOIN_STATUS_STA) &&
-+ (old_uapsdFlags != priv->uapsd_info.uapsdFlags))
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+ }
-+ } else {
-+ wiphy_err(dev->wiphy, "queue is to large!\n");
-+ ret = -EINVAL;
-+ }
-+
-+out:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return ret;
-+}
-+
-+int xradio_get_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_low_level_stats *stats)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+
-+ memcpy(stats, &hw_priv->stats, sizeof(*stats));
-+ return 0;
-+}
-+
-+/*
-+int xradio_get_tx_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_tx_queue_stats *stats)
-+{
-+ int i;
-+ struct xradio_common *priv = dev->priv;
-+
-+ for (i = 0; i < dev->queues; ++i)
-+ xradio_queue_get_stats(&priv->tx_queue[i], &stats[i]);
-+
-+ return 0;
-+}
-+*/
-+
-+int xradio_set_pm(struct xradio_vif *priv, const struct wsm_set_pm *arg)
-+{
-+ struct wsm_set_pm pm = *arg;
-+
-+ if (priv->uapsd_info.uapsdFlags != 0)
-+ pm.pmMode &= ~WSM_PSM_FAST_PS_FLAG;
-+
-+ if (memcmp(&pm, &priv->firmware_ps_mode, sizeof(struct wsm_set_pm))) {
-+ priv->firmware_ps_mode = pm;
-+ return wsm_set_pm(priv->hw_priv, &pm, priv->if_id);
-+ } else {
-+ return 0;
-+ }
-+}
-+
-+void xradio_wep_key_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv = container_of(work, struct xradio_vif , wep_key_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u8 queueId = xradio_queue_get_queue_id(hw_priv->pending_frame_id);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queueId];
-+ __le32 wep_default_key_id = __cpu_to_le32(priv->wep_default_key_id);
-+
-+
-+ BUG_ON(queueId >= 4);
-+
-+ sta_printk(XRADIO_DBG_MSG, "Setting default WEP key: %d\n",
-+ priv->wep_default_key_id);
-+
-+ wsm_flush_tx(hw_priv);
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID,
-+ &wep_default_key_id, sizeof(wep_default_key_id),
-+ priv->if_id));
-+
-+ xradio_queue_requeue(queue, hw_priv->pending_frame_id, true);
-+
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+int xradio_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ int ret = 0;
-+ __le32 val32;
-+ struct xradio_vif *priv = NULL;
-+ int i =0;
-+ int if_id;
-+
-+
-+ xradio_for_each_vif(hw_priv,priv,i) {
-+ if (!priv)
-+ continue;
-+ if_id = priv->if_id;
-+
-+ if (value != (u32) -1)
-+ val32 = __cpu_to_le32(value);
-+ else
-+ val32 = 0; /* disabled */
-+
-+ /* mutex_lock(&priv->conf_mutex); */
-+ ret = WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_RTS_THRESHOLD,
-+ &val32, sizeof(val32), if_id));
-+ /* mutex_unlock(&priv->conf_mutex); */
-+ }
-+ return ret;
-+}
-+
-+/* TODO: COMBO: Flush only a particular interface specific parts */
-+int __xradio_flush(struct xradio_common *hw_priv, bool drop, int if_id)
-+{
-+ int i, ret;
-+ struct xradio_vif *priv =
-+ __xrwl_hwpriv_to_vifpriv(hw_priv, if_id);
-+
-+
-+ for (;;) {
-+ /* TODO: correct flush handling is required when dev_stop.
-+ * Temporary workaround: 2s
-+ */
-+ if (drop) {
-+ for (i = 0; i < 4; ++i)
-+ xradio_queue_clear(&hw_priv->tx_queue[i],if_id);
-+ } else if(!hw_priv->bh_error){
-+ ret = wait_event_timeout(
-+ hw_priv->tx_queue_stats.wait_link_id_empty,
-+ xradio_queue_stats_is_empty(&hw_priv->tx_queue_stats, -1, if_id),
-+ 2 * HZ);
-+ } else { //add by yangfh, don't wait when bh error
-+ sta_printk(XRADIO_DBG_ERROR, " %s:bh_error occur.\n", __func__);
-+ ret = -1;
-+ break;
-+ }
-+
-+ if (!drop && unlikely(ret <= 0)) {
-+ sta_printk(XRADIO_DBG_ERROR, " %s: timeout...\n", __func__);
-+ ret = -ETIMEDOUT;
-+ break;
-+ } else {
-+ ret = 0;
-+ }
-+
-+ wsm_vif_lock_tx(priv);
-+ if (unlikely(!xradio_queue_stats_is_empty(&hw_priv->tx_queue_stats,
-+ -1, if_id))) {
-+ /* Highly unlekely: WSM requeued frames. */
-+ wsm_unlock_tx(hw_priv);
-+ continue;
-+ }
-+ wsm_unlock_tx(hw_priv);
-+ break;
-+ }
-+ return ret;
-+}
-+
-+void xradio_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop)
-+{
-+ //struct xradio_vif *priv = NULL;
-+ struct xradio_common *hw_priv = hw->priv;
-+ int i = 0;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+
-+ /*TODO:COMBO: reenable this part of code when flush callback
-+ * is implemented per vif */
-+ /*switch (hw_priv->mode) {
-+ case NL80211_IFTYPE_MONITOR:
-+ drop = true;
-+ break;
-+ case NL80211_IFTYPE_AP:
-+ if (!hw_priv->enable_beacon)
-+ drop = true;
-+ break;
-+ }*/
-+
-+ //if (!(hw_priv->if_id_slot & BIT(priv->if_id)))
-+ // return;
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if(NULL == priv)
-+ continue;
-+ if ((hw_priv->if_id_slot & BIT(priv->if_id)))
-+ __xradio_flush(hw_priv, drop, priv->if_id);
-+ }
-+ return;
-+}
-+
-+int xradio_remain_on_channel(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_channel *chan,
-+ int duration, enum ieee80211_roc_type type)
-+{
-+ int ret = 0;
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = NULL;
-+ int i = 0;
-+ int if_id;
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ struct timeval TES_P2P_0002_tmval;
-+#endif
-+
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ do_gettimeofday(&TES_P2P_0002_tmval);
-+ TES_P2P_0002_roc_dur = (s32)duration;
-+ TES_P2P_0002_roc_sec = (s32)TES_P2P_0002_tmval.tv_sec;
-+ TES_P2P_0002_roc_usec = (s32)TES_P2P_0002_tmval.tv_usec;
-+#endif
-+
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if(NULL == priv)
-+ continue;
-+ if_id = priv->if_id;
-+
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "ROC IN %d ch %d\n",
-+ priv->if_id, chan->hw_value);
-+#endif
-+ /* default only p2p interface if_id can remain on */
-+ if((priv->if_id == 0) || (priv->if_id == 1))
-+ continue;
-+ hw_priv->roc_if_id = priv->if_id;
-+ ret = WARN_ON(__xradio_flush(hw_priv, false, if_id));
-+ xradio_enable_listening(priv, chan);
-+
-+ if (!ret) {
-+ atomic_set(&hw_priv->remain_on_channel, 1);
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->rem_chan_timeout,
-+ duration * HZ / 1000);
-+ priv->join_status = XRADIO_JOIN_STATUS_MONITOR;
-+ ieee80211_ready_on_channel(hw);
-+ } else {
-+ hw_priv->roc_if_id = -1;
-+ up(&hw_priv->scan.lock);
-+ }
-+
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "ROC OUT %d\n", priv->if_id);
-+#endif
-+ }
-+ /* set the channel to supplied ieee80211_channel pointer, if it
-+ is not set. This is to remove the crash while sending a probe res
-+ in listen state. Later channel will updated on
-+ IEEE80211_CONF_CHANGE_CHANNEL event*/
-+ if(!hw_priv->channel) {
-+ hw_priv->channel = chan;
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return ret;
-+}
-+
-+int xradio_cancel_remain_on_channel(struct ieee80211_hw *hw)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+
-+
-+ sta_printk(XRADIO_DBG_NIY, "Cancel remain on channel\n");
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ if (TES_P2P_0002_state == TES_P2P_0002_STATE_GET_PKTID) {
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_IDLE;
-+ sta_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_IDLE][Cancel ROC]\n");
-+ }
-+#endif
-+
-+ if (atomic_read(&hw_priv->remain_on_channel))
-+ cancel_delayed_work_sync(&hw_priv->rem_chan_timeout);
-+
-+ if (atomic_read(&hw_priv->remain_on_channel))
-+ xradio_rem_chan_timeout(&hw_priv->rem_chan_timeout.work);
-+
-+ return 0;
-+}
-+
-+/* ******************************************************************** */
-+/* WSM callbacks */
-+
-+void xradio_channel_switch_cb(struct xradio_common *hw_priv)
-+{
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_free_event_queue(struct xradio_common *hw_priv)
-+{
-+ LIST_HEAD(list);
-+
-+
-+ spin_lock(&hw_priv->event_queue_lock);
-+ list_splice_init(&hw_priv->event_queue, &list);
-+ spin_unlock(&hw_priv->event_queue_lock);
-+
-+ __xradio_free_event_queue(&list);
-+}
-+
-+void xradio_event_handler(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, event_handler);
-+ struct xradio_vif *priv;
-+ struct xradio_wsm_event *event;
-+ LIST_HEAD(list);
-+
-+
-+ spin_lock(&hw_priv->event_queue_lock);
-+ list_splice_init(&hw_priv->event_queue, &list);
-+ spin_unlock(&hw_priv->event_queue_lock);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ list_for_each_entry(event, &list, link) {
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, event->if_id);
-+ if (!priv) {
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] Event for non existing "
-+ "interface, ignoring.\n");
-+ continue;
-+ }
-+ switch (event->evt.eventId) {
-+ case WSM_EVENT_ERROR:
-+ /* I even don't know what is it about.. */
-+ //STUB();
-+ break;
-+ case WSM_EVENT_BSS_LOST:
-+ {
-+ spin_lock(&priv->bss_loss_lock);
-+ if (priv->bss_loss_status > XRADIO_BSS_LOSS_NONE) {
-+ spin_unlock(&priv->bss_loss_lock);
-+ break;
-+ }
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_CHECKING;
-+ spin_unlock(&priv->bss_loss_lock);
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] BSS lost, Beacon miss=%d, event=%x.\n",
-+ (event->evt.eventData>>8)&0xff, event->evt.eventData&0xff);
-+
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ if (!down_trylock(&hw_priv->scan.lock)) {
-+ up(&hw_priv->scan.lock);
-+ priv->delayed_link_loss = 0;
-+ queue_delayed_work(hw_priv->workqueue,
-+ &priv->bss_loss_work, HZ/10); //100ms
-+ } else {
-+ /* Scan is in progress. Delay reporting. */
-+ /* Scan complete will trigger bss_loss_work */
-+ priv->delayed_link_loss = 1;
-+ /* Also we're starting watchdog. */
-+ queue_delayed_work(hw_priv->workqueue,
-+ &priv->bss_loss_work, 10 * HZ);
-+ }
-+ break;
-+ }
-+ case WSM_EVENT_BSS_REGAINED:
-+ {
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] BSS regained.\n");
-+ priv->delayed_link_loss = 0;
-+ spin_lock(&priv->bss_loss_lock);
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_NONE;
-+ spin_unlock(&priv->bss_loss_lock);
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ break;
-+ }
-+ case WSM_EVENT_RADAR_DETECTED:
-+ //STUB();
-+ break;
-+ case WSM_EVENT_RCPI_RSSI:
-+ {
-+ /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
-+ * RSSI = RCPI / 2 - 110 */
-+ int rcpiRssi = (int)(event->evt.eventData & 0xFF);
-+ int cqm_evt;
-+ if (priv->cqm_use_rssi)
-+ rcpiRssi = (s8)rcpiRssi;
-+ else
-+ rcpiRssi = rcpiRssi / 2 - 110;
-+
-+ cqm_evt = (rcpiRssi <= priv->cqm_rssi_thold) ?
-+ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW :
-+ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
-+ sta_printk(XRADIO_DBG_NIY, "[CQM] RSSI event: %d", rcpiRssi);
-+ ieee80211_cqm_rssi_notify(priv->vif,
-+ cqm_evt,
-+ 0,
-+ GFP_KERNEL);
-+ break;
-+ }
-+ case WSM_EVENT_BT_INACTIVE:
-+ //STUB();
-+ break;
-+ case WSM_EVENT_BT_ACTIVE:
-+ //STUB();
-+ break;
-+ case WSM_EVENT_INACTIVITY:
-+ {
-+ int link_id = ffs((u32)(event->evt.eventData)) - 1;
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *deauth;
-+ struct xradio_link_entry *entry = NULL;
-+
-+ sta_printk(XRADIO_DBG_WARN, "Inactivity Event Recieved for "
-+ "link_id %d\n", link_id);
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ break;
-+ skb_reserve(skb, 64);
-+ xrwl_unmap_link(priv, link_id);
-+ deauth = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ WARN_ON(!deauth);
-+ entry = &priv->link_id_db[link_id - 1];
-+ deauth->duration = 0;
-+ memcpy(deauth->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(deauth->sa, entry->mac/*priv->link_id_db[i].mac*/, ETH_ALEN);
-+ memcpy(deauth->bssid, priv->vif->addr, ETH_ALEN);
-+ deauth->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-+ IEEE80211_STYPE_DEAUTH |
-+ IEEE80211_FCTL_TODS);
-+ deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
-+ deauth->seq_ctrl = 0;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ sta_printk(XRADIO_DBG_WARN, " Inactivity Deauth Frame sent for MAC SA %pM \t and DA %pM\n", deauth->sa, deauth->da);
-+ queue_work(priv->hw_priv->workqueue, &priv->set_tim_work);
-+ break;
-+ }
-+ case WSM_EVENT_PS_MODE_ERROR:
-+ {
-+ if (!priv->uapsd_info.uapsdFlags &&
-+ (priv->user_pm_mode != WSM_PSM_PS))
-+ {
-+ struct wsm_set_pm pm = priv->powersave_mode;
-+ int ret = 0;
-+
-+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
-+ ret = xradio_set_pm (priv, &priv->powersave_mode);
-+ if(ret)
-+ priv->powersave_mode = pm;
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ __xradio_free_event_queue(&list);
-+}
-+
-+void xradio_bss_loss_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, bss_loss_work.work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int timeout; /* in beacons */
-+
-+
-+ timeout = priv->cqm_link_loss_count - priv->cqm_beacon_loss_count;
-+ /* Skip the confimration procedure in P2P case */
-+ if (priv->vif->p2p)
-+ goto report;
-+
-+ spin_lock(&priv->bss_loss_lock);
-+ if (priv->bss_loss_status == XRADIO_BSS_LOSS_CONFIRMING) {
-+ //do loss report next time.
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_CONFIRMED;
-+ spin_unlock(&priv->bss_loss_lock);
-+ //wait for more 1s to loss confirm.
-+ queue_delayed_work(hw_priv->workqueue, &priv->bss_loss_work, 1 * HZ);
-+ return;
-+ } else if (priv->bss_loss_status == XRADIO_BSS_LOSS_NONE) {
-+ spin_unlock(&priv->bss_loss_lock);
-+ //link is alive.
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ return;
-+ } else if (priv->bss_loss_status == XRADIO_BSS_LOSS_CHECKING) {
-+ /* it mean no confirming packets, just report loss. */
-+ }
-+ spin_unlock(&priv->bss_loss_lock);
-+
-+report:
-+ if (priv->cqm_beacon_loss_count) {
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] Beacon loss.\n");
-+ if (timeout <= 0)
-+ timeout = 0;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //ieee80211_cqm_beacon_miss_notify(priv->vif, GFP_KERNEL);
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ } else {
-+ timeout = 0;
-+ }
-+
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ queue_delayed_work(hw_priv->workqueue, &priv->connection_loss_work,
-+ timeout * HZ / 10);
-+
-+ spin_lock(&priv->bss_loss_lock);
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_NONE;
-+ spin_unlock(&priv->bss_loss_lock);
-+}
-+
-+void xradio_connection_loss_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, connection_loss_work.work);
-+ sta_printk(XRADIO_DBG_ERROR, "[CQM] if%d Reporting connection loss.\n",
-+ priv->if_id);
-+ ieee80211_connection_loss(priv->vif);
-+}
-+
-+void xradio_tx_failure_work(struct work_struct *work)
-+{
-+ //struct xradio_vif *priv =
-+ // container_of(work, struct xradio_vif, tx_failure_work);
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] Reporting TX failure.\n");
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //ieee80211_cqm_tx_fail_notify(priv->vif, GFP_KERNEL);
-+#else /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ //(void)priv;
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+}
-+
-+/* Internal API */
-+int xradio_setup_mac(struct xradio_common *hw_priv)
-+{
-+ int ret = 0, if_id;
-+
-+
-+ if (hw_priv->sdd) {
-+ struct wsm_configuration cfg = {
-+ .dot11StationId = &hw_priv->mac_addr[0],
-+ .dpdData = hw_priv->sdd->data,
-+ .dpdData_size = hw_priv->sdd->size,
-+ };
-+ for (if_id = 0; if_id < xrwl_get_nr_hw_ifaces(hw_priv);
-+ if_id++) {
-+ /* Set low-power mode. */
-+ ret |= WARN_ON(wsm_configuration(hw_priv, &cfg,
-+ if_id));
-+ }
-+ /* wsm_configuration only once, so release it */
-+ release_firmware(hw_priv->sdd);
-+ hw_priv->sdd = NULL;
-+ }
-+
-+ /* BUG:TX output power is not set untill config_xradio is called.
-+ * This would lead to 0 power set in fw and would effect scan & p2p-find
-+ * Setting to default value here from sdd which would be overwritten when
-+ * we make connection to AP.This value is used only during scan & p2p-ops
-+ * untill AP connection is made */
-+ /*BUG:TX output power: Hardcoding to 20dbm if CCX is not enabled*/
-+ /*TODO: This might change*/
-+ if (!hw_priv->output_power)
-+ hw_priv->output_power=20;
-+ sta_printk(XRADIO_DBG_MSG, "%s output power %d\n",__func__,hw_priv->output_power);
-+
-+ return ret;
-+}
-+
-+void xradio_pending_offchanneltx_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, pending_offchanneltx_work.work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "OFFCHAN PEND IN\n");
-+#endif
-+ xradio_disable_listening(priv);
-+ hw_priv->roc_if_id = -1;
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "OFFCHAN PEND OUT\n");
-+#endif
-+ up(&hw_priv->scan.lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+}
-+
-+void xradio_offchannel_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, offchannel_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u8 queueId = xradio_queue_get_queue_id(hw_priv->pending_frame_id);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queueId];
-+
-+
-+ BUG_ON(queueId >= 4);
-+ BUG_ON(!hw_priv->channel);
-+
-+ if (unlikely(down_trylock(&hw_priv->scan.lock))) {
-+ int ret;
-+ sta_printk(XRADIO_DBG_ERROR, "xradio_offchannel_work***** drop frame\n");
-+ ret = xradio_queue_remove(queue, hw_priv->pending_frame_id);
-+ if (ret)
-+ sta_printk(XRADIO_DBG_ERROR, "xradio_offchannel_work: "
-+ "queue_remove failed %d\n", ret);
-+ wsm_unlock_tx(hw_priv);
-+ //workaround by yangfh
-+ up(&hw_priv->scan.lock);
-+ ieee80211_connection_loss(priv->vif);
-+ sta_printk(XRADIO_DBG_ERROR,"lock %d\n", hw_priv->scan.lock.count);
-+
-+ return;
-+ }
-+ mutex_lock(&hw_priv->conf_mutex);
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "OFFCHAN WORK IN %d\n", priv->if_id);
-+#endif
-+ hw_priv->roc_if_id = priv->if_id;
-+ if (likely(!priv->join_status)) {
-+ wsm_vif_flush_tx(priv);
-+ xradio_enable_listening(priv, hw_priv->channel);
-+ /* xradio_update_filtering(priv); */
-+ }
-+ if (unlikely(!priv->join_status))
-+ xradio_queue_remove(queue, hw_priv->pending_frame_id);
-+ else
-+ xradio_queue_requeue(queue, hw_priv->pending_frame_id, false);
-+
-+ queue_delayed_work(hw_priv->workqueue,
-+ &priv->pending_offchanneltx_work, 204 * HZ/1000);
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "OFFCHAN WORK OUT %d\n", priv->if_id);
-+#endif
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_join_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, join_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u8 queueId = xradio_queue_get_queue_id(hw_priv->pending_frame_id);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queueId];
-+ const struct xradio_txpriv *txpriv = NULL;
-+ struct sk_buff *skb = NULL;
-+ const struct wsm_tx *wsm;
-+ const struct ieee80211_hdr *frame;
-+ const u8 *bssid;
-+ struct cfg80211_bss *bss;
-+ const u8 *ssidie;
-+ const u8 *dtimie;
-+ const struct ieee80211_tim_ie *tim = NULL;
-+ struct wsm_protected_mgmt_policy mgmt_policy;
-+ //struct wsm_reset reset = {
-+ // .reset_statistics = true,
-+ //};
-+
-+
-+
-+ BUG_ON(queueId >= 4);
-+ if (xradio_queue_get_skb(queue, hw_priv->pending_frame_id,
-+ &skb, &txpriv)) {
-+ wsm_unlock_tx(hw_priv);
-+ return;
-+ }
-+ wsm = (struct wsm_tx *)&skb->data[0];
-+ frame = (struct ieee80211_hdr *)&skb->data[txpriv->offset];
-+ bssid = &frame->addr1[0]; /* AP SSID in a 802.11 frame */
-+
-+ BUG_ON(!wsm);
-+ BUG_ON(!hw_priv->channel);
-+
-+ if (unlikely(priv->join_status)) {
-+ sta_printk(XRADIO_DBG_WARN, "%s, pre join_status=%d.\n",
-+ __func__, priv->join_status);
-+ wsm_lock_tx(hw_priv);
-+ xradio_unjoin_work(&priv->unjoin_work);
-+ }
-+
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+
-+ bss = cfg80211_get_bss(hw_priv->hw->wiphy, hw_priv->channel,
-+ bssid, NULL, 0, 0, 0);
-+ if (!bss) {
-+ xradio_queue_remove(queue, hw_priv->pending_frame_id);
-+ wsm_unlock_tx(hw_priv);
-+ return;
-+ }
-+ ssidie = cfg80211_find_ie(WLAN_EID_SSID,
-+ bss->ies->data,
-+ bss->ies->len);
-+ dtimie = cfg80211_find_ie(WLAN_EID_TIM,
-+ bss->ies->data,
-+ bss->ies->len);
-+ if (dtimie)
-+ tim = (struct ieee80211_tim_ie *)&dtimie[2];
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ {
-+ struct wsm_join join = {
-+ .mode = (bss->capability & WLAN_CAPABILITY_IBSS) ?
-+ WSM_JOIN_MODE_IBSS : WSM_JOIN_MODE_BSS,
-+ /* default changed to LONG, by HuangLu, fix 2/5.5/11m tx fail*/
-+ .preambleType = WSM_JOIN_PREAMBLE_LONG,
-+ .probeForJoin = 1,
-+ /* dtimPeriod will be updated after association */
-+ .dtimPeriod = 1,
-+ .beaconInterval = bss->beacon_interval,
-+ };
-+
-+ if (priv->if_id)
-+ join.flags |= WSM_FLAG_MAC_INSTANCE_1;
-+ else
-+ join.flags &= ~WSM_FLAG_MAC_INSTANCE_1;
-+
-+ /* BT Coex related changes */
-+ if (hw_priv->is_BT_Present) {
-+ if (((hw_priv->conf_listen_interval * 100) %
-+ bss->beacon_interval) == 0)
-+ priv->listen_interval =
-+ ((hw_priv->conf_listen_interval * 100) /
-+ bss->beacon_interval);
-+ else
-+ priv->listen_interval =
-+ ((hw_priv->conf_listen_interval * 100) /
-+ bss->beacon_interval + 1);
-+ }
-+
-+ if (tim && tim->dtim_period > 1) {
-+ join.dtimPeriod = tim->dtim_period;
-+ priv->join_dtim_period = tim->dtim_period;
-+ }
-+ priv->beacon_int = bss->beacon_interval;
-+ sta_printk(XRADIO_DBG_NIY, "Join DTIM: %d, interval: %d\n",
-+ join.dtimPeriod, priv->beacon_int);
-+
-+ hw_priv->is_go_thru_go_neg = false;
-+ join.channelNumber = hw_priv->channel->hw_value;
-+
-+ /* basicRateSet will be updated after association.
-+ Currently these values are hardcoded */
-+ if (hw_priv->channel->band == NL80211_BAND_5GHZ) {
-+ join.band = WSM_PHY_BAND_5G;
-+ join.basicRateSet = 64; /*6 mbps*/
-+ }else{
-+ join.band = WSM_PHY_BAND_2_4G;
-+ join.basicRateSet = 7; /*1, 2, 5.5 mbps*/
-+ }
-+ memcpy(&join.bssid[0], bssid, sizeof(join.bssid));
-+ memcpy(&priv->join_bssid[0], bssid, sizeof(priv->join_bssid));
-+
-+ if (ssidie) {
-+ join.ssidLength = ssidie[1];
-+ if (WARN_ON(join.ssidLength > sizeof(join.ssid)))
-+ join.ssidLength = sizeof(join.ssid);
-+ memcpy(&join.ssid[0], &ssidie[2], join.ssidLength);
-+ if(strstr(&join.ssid[0],"5.1.4"))
-+ msleep(200);
-+#ifdef ROAM_OFFLOAD
-+ if((priv->vif->type == NL80211_IFTYPE_STATION)) {
-+ priv->ssid_length = join.ssidLength;
-+ memcpy(priv->ssid, &join.ssid[0], priv->ssid_length);
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+ }
-+
-+ if (priv->vif->p2p) {
-+ join.flags |= WSM_JOIN_FLAGS_P2P_GO;
-+ join.basicRateSet =
-+ xradio_rate_mask_to_wsm(hw_priv, 0xFF0);
-+ }
-+
-+ wsm_flush_tx(hw_priv);
-+
-+ /* Queue unjoin if not associated in 3 sec. */
-+ queue_delayed_work(hw_priv->workqueue,
-+ &priv->join_timeout, 3 * HZ);
-+ /*Stay Awake for Join Timeout*/
-+ xradio_pm_stay_awake(&hw_priv->pm_state, 3 * HZ);
-+
-+ xradio_disable_listening(priv);
-+
-+ //WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ 0, hw_priv->ba_tid_mask, priv->if_id));
-+ spin_lock_bh(&hw_priv->ba_lock);
-+ hw_priv->ba_ena = false;
-+ hw_priv->ba_cnt = 0;
-+ hw_priv->ba_acc = 0;
-+ hw_priv->ba_hist = 0;
-+ hw_priv->ba_cnt_rx = 0;
-+ hw_priv->ba_acc_rx = 0;
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+
-+ mgmt_policy.protectedMgmtEnable = 0;
-+ mgmt_policy.unprotectedMgmtFramesAllowed = 1;
-+ mgmt_policy.encryptionForAuthFrame = 1;
-+ wsm_set_protected_mgmt_policy(hw_priv, &mgmt_policy, priv->if_id);
-+
-+ if (wsm_join(hw_priv, &join, priv->if_id)) {
-+ memset(&priv->join_bssid[0],
-+ 0, sizeof(priv->join_bssid));
-+ xradio_queue_remove(queue, hw_priv->pending_frame_id);
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+ } else {
-+ /* Upload keys */
-+ xradio_queue_requeue(queue, hw_priv->pending_frame_id,
-+ true);
-+ priv->join_status = XRADIO_JOIN_STATUS_STA;
-+
-+ /* Due to beacon filtering it is possible that the
-+ * AP's beacon is not known for the mac80211 stack.
-+ * Disable filtering temporary to make sure the stack
-+ * receives at least one */
-+ priv->disable_beacon_filter = true;
-+
-+ }
-+ xradio_update_filtering(priv);
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ cfg80211_put_bss(hw_priv->hw->wiphy,bss);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_join_timeout(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, join_timeout.work);
-+ sta_printk(XRADIO_DBG_WARN, "[WSM] Issue unjoin command (TMO).\n");
-+ wsm_lock_tx(priv->hw_priv);
-+ xradio_unjoin_work(&priv->unjoin_work);
-+}
-+
-+void xradio_unjoin_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, unjoin_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ struct wsm_reset reset = {
-+ .reset_statistics = true,
-+ };
-+ bool is_htcapie = false;
-+ int i;
-+ struct xradio_vif *tmp_priv;
-+
-+ //add by yangfh.
-+ hw_priv->connet_time[priv->if_id] = 0;
-+#ifdef AP_HT_COMPAT_FIX
-+ priv->ht_compat_det &= ~1;
-+ priv->ht_compat_cnt = 0;
-+#endif
-+
-+ del_timer_sync(&hw_priv->ba_timer);
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (unlikely(atomic_read(&hw_priv->scan.in_progress))) {
-+ if (atomic_xchg(&priv->delayed_unjoin, 1)) {
-+ sta_printk(XRADIO_DBG_NIY,
-+ "%s: Delayed unjoin "
-+ "is already scheduled.\n",
-+ __func__);
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return;
-+ }
-+
-+ if (priv->join_status &&
-+ priv->join_status > XRADIO_JOIN_STATUS_STA) {
-+ sta_printk(XRADIO_DBG_ERROR,
-+ "%s: Unexpected: join status: %d\n",
-+ __func__, priv->join_status);
-+ BUG_ON(1);
-+ }
-+ if (priv->join_status) {
-+ cancel_work_sync(&priv->update_filtering_work);
-+ cancel_work_sync(&priv->set_beacon_wakeup_period_work);
-+ memset(&priv->join_bssid[0], 0, sizeof(priv->join_bssid));
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+
-+ /* Unjoin is a reset. */
-+ wsm_flush_tx(hw_priv);
-+ WARN_ON(wsm_keep_alive_period(hw_priv, 0, priv->if_id));
-+ WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ WARN_ON(wsm_set_output_power(hw_priv,
-+ hw_priv->output_power * 10, priv->if_id));
-+ priv->join_dtim_period = 0;
-+ priv->cipherType = 0;
-+ WARN_ON(xradio_setup_mac_pvif(priv));
-+ xradio_free_event_queue(hw_priv);
-+ cancel_work_sync(&hw_priv->event_handler);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ 0, hw_priv->ba_tid_mask, priv->if_id));
-+ priv->disable_beacon_filter = false;
-+ xradio_update_filtering(priv);
-+ priv->setbssparams_done = false;
-+ memset(&priv->association_mode, 0,
-+ sizeof(priv->association_mode));
-+ memset(&priv->bss_params, 0, sizeof(priv->bss_params));
-+ memset(&priv->firmware_ps_mode, 0,
-+ sizeof(priv->firmware_ps_mode));
-+ priv->htcap = false;
-+ xradio_for_each_vif(hw_priv, tmp_priv, i) {
-+ if (!tmp_priv)
-+ continue;
-+ if ((tmp_priv->join_status == XRADIO_JOIN_STATUS_STA) && tmp_priv->htcap)
-+ is_htcapie = true;
-+ }
-+
-+ if (is_htcapie) {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11N_THROTTLE;
-+ sta_printk(XRADIO_DBG_NIY, "UNJOIN HTCAP 11N %d\n",hw_priv->vif0_throttle);
-+ } else {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ sta_printk(XRADIO_DBG_NIY, "UNJOIN 11BG %d\n",hw_priv->vif0_throttle);
-+ }
-+ sta_printk(XRADIO_DBG_NIY, "Unjoin.\n");
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+int xradio_enable_listening(struct xradio_vif *priv,
-+ struct ieee80211_channel *chan)
-+{
-+ /* TODO:COMBO: Channel is common to HW currently in mac80211.
-+ Change the code below once channel is made per VIF */
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_start start = {
-+ .mode = WSM_START_MODE_P2P_DEV | (priv->if_id << 4),
-+ .band = (chan->band == NL80211_BAND_5GHZ) ?
-+ WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G,
-+ .channelNumber = chan->hw_value,
-+ .beaconInterval = 100,
-+ .DTIMPeriod = 1,
-+ .probeDelay = 0,
-+ .basicRateSet = 0x0F,
-+ };
-+
-+
-+ if(priv->if_id != 2) {
-+ WARN_ON(priv->join_status > XRADIO_JOIN_STATUS_MONITOR);
-+ return 0;
-+ }
-+ if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR)
-+ return 0;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_PASSIVE)
-+ priv->join_status = XRADIO_JOIN_STATUS_MONITOR;
-+
-+ WARN_ON(priv->join_status > XRADIO_JOIN_STATUS_MONITOR);
-+
-+ return wsm_start(hw_priv, &start, XRWL_GENERIC_IF_ID);
-+}
-+
-+int xradio_disable_listening(struct xradio_vif *priv)
-+{
-+ int ret;
-+ struct wsm_reset reset = {
-+ .reset_statistics = true,
-+ };
-+
-+
-+ if(priv->if_id != 2) {
-+ WARN_ON(priv->join_status > XRADIO_JOIN_STATUS_MONITOR);
-+ return 0;
-+ }
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+
-+ WARN_ON(priv->join_status > XRADIO_JOIN_STATUS_MONITOR);
-+
-+ if (priv->hw_priv->roc_if_id == -1)
-+ return 0;
-+
-+ ret = wsm_reset(priv->hw_priv, &reset, XRWL_GENERIC_IF_ID);
-+ return ret;
-+}
-+
-+/* TODO:COMBO:UAPSD will be supported only on one interface */
-+int xradio_set_uapsd_param(struct xradio_vif *priv,
-+ const struct wsm_edca_params *arg)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int ret;
-+ u16 uapsdFlags = 0;
-+
-+
-+ /* Here's the mapping AC [queue, bit]
-+ VO [0,3], VI [1, 2], BE [2, 1], BK [3, 0]*/
-+
-+ if (arg->params[0].uapsdEnable)
-+ uapsdFlags |= 1 << 3;
-+
-+ if (arg->params[1].uapsdEnable)
-+ uapsdFlags |= 1 << 2;
-+
-+ if (arg->params[2].uapsdEnable)
-+ uapsdFlags |= 1 << 1;
-+
-+ if (arg->params[3].uapsdEnable)
-+ uapsdFlags |= 1;
-+
-+ /* Currently pseudo U-APSD operation is not supported, so setting
-+ * MinAutoTriggerInterval, MaxAutoTriggerInterval and
-+ * AutoTriggerStep to 0 */
-+
-+ priv->uapsd_info.uapsdFlags = cpu_to_le16(uapsdFlags);
-+ priv->uapsd_info.minAutoTriggerInterval = 0;
-+ priv->uapsd_info.maxAutoTriggerInterval = 0;
-+ priv->uapsd_info.autoTriggerStep = 0;
-+
-+ ret = wsm_set_uapsd_info(hw_priv, &priv->uapsd_info,
-+ priv->if_id);
-+ return ret;
-+}
-+
-+void xradio_ba_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, ba_work);
-+ u8 tx_ba_tid_mask;
-+
-+
-+ /* TODO:COMBO: reenable this part of code */
-+/* if (priv->join_status != XRADIO_JOIN_STATUS_STA)
-+ return;
-+ if (!priv->setbssparams_done)
-+ return;*/
-+
-+ sta_printk(XRADIO_DBG_WARN, "BA work****\n");
-+ spin_lock_bh(&hw_priv->ba_lock);
-+// tx_ba_tid_mask = hw_priv->ba_ena ? hw_priv->ba_tid_mask : 0;
-+ tx_ba_tid_mask = hw_priv->ba_tid_mask;
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+
-+ wsm_lock_tx(hw_priv);
-+
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ tx_ba_tid_mask, hw_priv->ba_tid_mask, -1)); /*TODO:COMBO*/
-+
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_ba_timer(struct timer_list *t)
-+{
-+ struct xradio_common *hw_priv = from_timer(hw_priv, t, ba_timer);
-+ bool ba_ena;
-+
-+
-+ spin_lock_bh(&hw_priv->ba_lock);
-+
-+ if (atomic_read(&hw_priv->scan.in_progress)) {
-+ hw_priv->ba_cnt = 0;
-+ hw_priv->ba_acc = 0;
-+ hw_priv->ba_cnt_rx = 0;
-+ hw_priv->ba_acc_rx = 0;
-+ goto skip_statistic_update;
-+ }
-+
-+ if (hw_priv->ba_cnt >= XRADIO_BLOCK_ACK_CNT &&
-+ (hw_priv->ba_acc / hw_priv->ba_cnt >= XRADIO_BLOCK_ACK_THLD ||
-+ (hw_priv->ba_cnt_rx >= XRADIO_BLOCK_ACK_CNT &&
-+ hw_priv->ba_acc_rx / hw_priv->ba_cnt_rx >=
-+ XRADIO_BLOCK_ACK_THLD)))
-+ ba_ena = true;
-+ else
-+ ba_ena = false;
-+
-+ hw_priv->ba_cnt = 0;
-+ hw_priv->ba_acc = 0;
-+ hw_priv->ba_cnt_rx = 0;
-+ hw_priv->ba_acc_rx = 0;
-+
-+ if (ba_ena != hw_priv->ba_ena) {
-+ if (ba_ena || ++hw_priv->ba_hist >= XRADIO_BLOCK_ACK_HIST) {
-+ hw_priv->ba_ena = ba_ena;
-+ hw_priv->ba_hist = 0;
-+#if 0
-+ sta_printk(XRADIO_DBG_NIY, "%s block ACK:\n",
-+ ba_ena ? "enable" : "disable");
-+ queue_work(hw_priv->workqueue, &hw_priv->ba_work);
-+#endif
-+ }
-+ } else if (hw_priv->ba_hist)
-+ --hw_priv->ba_hist;
-+
-+skip_statistic_update:
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+}
-+
-+int xradio_vif_setup(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+ int ret = 0;
-+
-+
-+ //reset channel change flag, yangfh 2015-5-15 17:12:14
-+ hw_priv->channel_changed = 0;
-+ /* Setup per vif workitems and locks */
-+ spin_lock_init(&priv->vif_lock);
-+ INIT_WORK(&priv->join_work, xradio_join_work);
-+ INIT_DELAYED_WORK(&priv->join_timeout, xradio_join_timeout);
-+ INIT_WORK(&priv->unjoin_work, xradio_unjoin_work);
-+ INIT_WORK(&priv->wep_key_work, xradio_wep_key_work);
-+ INIT_WORK(&priv->offchannel_work, xradio_offchannel_work);
-+ INIT_DELAYED_WORK(&priv->bss_loss_work, xradio_bss_loss_work);
-+ INIT_DELAYED_WORK(&priv->connection_loss_work, xradio_connection_loss_work);
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_NONE;
-+ spin_lock_init(&priv->bss_loss_lock);
-+ INIT_WORK(&priv->tx_failure_work, xradio_tx_failure_work);
-+ spin_lock_init(&priv->ps_state_lock);
-+ INIT_DELAYED_WORK(&priv->set_cts_work, xradio_set_cts_work);
-+ INIT_WORK(&priv->set_tim_work, xradio_set_tim_work);
-+ INIT_WORK(&priv->multicast_start_work, xradio_multicast_start_work);
-+ INIT_WORK(&priv->multicast_stop_work, xradio_multicast_stop_work);
-+ INIT_WORK(&priv->link_id_work, xradio_link_id_work);
-+ INIT_DELAYED_WORK(&priv->link_id_gc_work, xradio_link_id_gc_work);
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ INIT_WORK(&priv->linkid_reset_work, xradio_link_id_reset);
-+#endif
-+ INIT_WORK(&priv->update_filtering_work, xradio_update_filtering_work);
-+ INIT_DELAYED_WORK(&priv->pending_offchanneltx_work,
-+ xradio_pending_offchanneltx_work);
-+ INIT_WORK(&priv->set_beacon_wakeup_period_work,
-+ xradio_set_beacon_wakeup_period_work);
-+#ifdef AP_HT_CAP_UPDATE
-+ INIT_WORK(&priv->ht_oper_update_work, xradio_ht_oper_update_work);
-+#endif
-+ timer_setup(&priv->mcast_timeout, xradio_mcast_timeout, 0);
-+ priv->setbssparams_done = false;
-+ priv->power_set_true = 0;
-+ priv->user_power_set_true = 0;
-+ priv->user_pm_mode = 0;
-+
-+ /* Initialising the broadcast filter */
-+ memset(priv->broadcast_filter.MacAddr, 0xFF, ETH_ALEN);
-+ priv->broadcast_filter.nummacaddr = 1;
-+ priv->broadcast_filter.address_mode = 1;
-+ priv->broadcast_filter.filter_mode = 1;
-+ priv->htcap = false;
-+#ifdef AP_HT_COMPAT_FIX
-+ priv->ht_compat_det = 0;
-+ priv->ht_compat_cnt = 0;
-+#endif
-+
-+ sta_printk(XRADIO_DBG_ALWY, "!!!%s: id=%d, type=%d, p2p=%d\n",
-+ __func__, priv->if_id, priv->vif->type, priv->vif->p2p);
-+
-+ atomic_set(&priv->enabled, 1);
-+
-+ /* default EDCA */
-+ WSM_EDCA_SET(&priv->edca, 0, 0x0002, 0x0003, 0x0007,
-+ 47, 0xc8, false);
-+ WSM_EDCA_SET(&priv->edca, 1, 0x0002, 0x0007, 0x000f,
-+ 94, 0xc8, false);
-+
-+// if(priv->vif->p2p == true) {
-+ WSM_EDCA_SET(&priv->edca, 2, 0x0002, 0x0003, 0x0007,
-+ 0, 0xc8, false);
-+ sta_printk(XRADIO_DBG_MSG, "EDCA params Best effort for sta/p2p is " \
-+ "aifs=%u, cw_min=%u, cw_max=%u \n",
-+ priv->edca.params[2].aifns, priv->edca.params[2].cwMin,
-+ priv->edca.params[2].cwMax);
-+#if 0
-+ }else {
-+ WSM_EDCA_SET(&priv->edca, 2, 0x0003, 0x000f, 0x03ff,
-+ 0, 0xc8, false);
-+ sta_printk(XRADIO_DBG_MSG, "EDCA params Best effort for sta is " \
-+ "aifs=%u, cw_min=%u, cw_max=%u \n",
-+ priv->edca.params[2].aifns, priv->edca.params[2].cwMin,
-+ priv->edca.params[2].cwMax);
-+ }
-+#endif
-+ WSM_EDCA_SET(&priv->edca, 3, 0x0007, 0x000f, 0x03ff,
-+ 0, 0xc8, false);
-+
-+ ret = wsm_set_edca_params(hw_priv, &priv->edca, priv->if_id);
-+ if (WARN_ON(ret))
-+ goto out;
-+
-+ ret = xradio_set_uapsd_param(priv, &priv->edca);
-+ if (WARN_ON(ret))
-+ goto out;
-+
-+ memset(priv->bssid, ~0, ETH_ALEN);
-+ priv->wep_default_key_id = -1;
-+ priv->cipherType = 0;
-+ priv->cqm_link_loss_count = XRADIO_LINK_LOSS_THOLD_DEF;
-+ priv->cqm_beacon_loss_count = XRADIO_BSS_LOSS_THOLD_DEF;
-+
-+ /* Temporary configuration - beacon filter table */
-+ __xradio_bf_configure(priv);
-+
-+out:
-+ return ret;
-+}
-+
-+int xradio_setup_mac_pvif(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ /* NOTE: There is a bug in FW: it reports signal
-+ * as RSSI if RSSI subscription is enabled.
-+ * It's not enough to set WSM_RCPI_RSSI_USE_RSSI. */
-+ /* NOTE2: RSSI based reports have been switched to RCPI, since
-+ * FW has a bug and RSSI reported values are not stable,
-+ * what can leads to signal level oscilations in user-end applications */
-+ struct wsm_rcpi_rssi_threshold threshold = {
-+ .rssiRcpiMode = WSM_RCPI_RSSI_THRESHOLD_ENABLE |
-+ WSM_RCPI_RSSI_DONT_USE_UPPER |
-+ WSM_RCPI_RSSI_DONT_USE_LOWER,
-+ .rollingAverageCount = 16,
-+ };
-+
-+
-+ /* Remember the decission here to make sure, we will handle
-+ * the RCPI/RSSI value correctly on WSM_EVENT_RCPI_RSS */
-+ if (threshold.rssiRcpiMode & WSM_RCPI_RSSI_USE_RSSI)
-+ priv->cqm_use_rssi = true;
-+
-+
-+ /* Configure RSSI/SCPI reporting as RSSI. */
-+ ret = wsm_set_rcpi_rssi_threshold(priv->hw_priv, &threshold, priv->if_id);
-+ return ret;
-+}
-+
-+void xradio_rem_chan_timeout(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, rem_chan_timeout.work);
-+ int ret, if_id;
-+ struct xradio_vif *priv;
-+
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ if(TES_P2P_0002_state == TES_P2P_0002_STATE_GET_PKTID) {
-+ sta_printk(XRADIO_DBG_WARN, "[Restart rem_chan_timeout:Timeout]\n");
-+ return;
-+ }
-+#endif
-+
-+ if (atomic_read(&hw_priv->remain_on_channel) == 0) {
-+ return;
-+ }
-+ ieee80211_remain_on_channel_expired(hw_priv->hw);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if_id = hw_priv->roc_if_id;
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_ERROR, "ROC TO IN %d\n", if_id);
-+#endif
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, if_id);
-+ ret = WARN_ON(__xradio_flush(hw_priv, false, if_id));
-+ if (!ret) {
-+ xradio_disable_listening(priv);
-+ }
-+ atomic_set(&hw_priv->remain_on_channel, 0);
-+ hw_priv->roc_if_id = -1;
-+
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_ERROR, "ROC TO OUT %d\n", if_id);
-+#endif
-+
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+}
-+const u8 *xradio_get_ie(u8 *start, size_t len, u8 ie)
-+{
-+ u8 *end, *pos;
-+
-+
-+ pos = start;
-+ if (pos == NULL)
-+ return NULL;
-+ end = pos + len;
-+
-+ while (pos + 1 < end) {
-+ if (pos + 2 + pos[1] > end)
-+ break;
-+ if (pos[0] == ie)
-+ return pos;
-+ pos += 2 + pos[1];
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * xradio_set_macaddrfilter -called when tesmode command
-+ * is for setting mac address filter
-+ *
-+ * @hw: the hardware
-+ * @data: incoming data
-+ *
-+ * Returns: 0 on success or non zero value on failure
-+ */
-+int xradio_set_macaddrfilter(struct xradio_common *hw_priv, struct xradio_vif *priv, u8 *data)
-+{
-+ struct wsm_mac_addr_filter *mac_addr_filter = NULL;
-+ struct wsm_mac_addr_info *addr_info = NULL;
-+ u8 action_mode = 0, no_of_mac_addr = 0, i = 0;
-+ int ret = 0;
-+ u16 macaddrfiltersize = 0;
-+
-+
-+ /* Retrieving Action Mode */
-+ action_mode = data[0];
-+ /* Retrieving number of address entries */
-+ no_of_mac_addr = data[1];
-+
-+ addr_info = (struct wsm_mac_addr_info *)&data[2];
-+
-+ /* Computing sizeof Mac addr filter */
-+ macaddrfiltersize = sizeof(*mac_addr_filter) + \
-+ (no_of_mac_addr * sizeof(struct wsm_mac_addr_info));
-+
-+ mac_addr_filter = kzalloc(macaddrfiltersize, GFP_KERNEL);
-+ if (!mac_addr_filter) {
-+ ret = -ENOMEM;
-+ goto exit_p;
-+ }
-+ mac_addr_filter->action_mode = action_mode;
-+ mac_addr_filter->numfilter = no_of_mac_addr;
-+
-+ for (i = 0; i < no_of_mac_addr; i++) {
-+ mac_addr_filter->macaddrfilter[i].address_mode = \
-+ addr_info[i].address_mode;
-+ memcpy(mac_addr_filter->macaddrfilter[i].MacAddr, \
-+ addr_info[i].MacAddr , ETH_ALEN);
-+ mac_addr_filter->macaddrfilter[i].filter_mode = \
-+ addr_info[i].filter_mode;
-+ }
-+ ret = WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_MAC_ADDR_FILTER, \
-+ mac_addr_filter, macaddrfiltersize, priv->if_id));
-+
-+ kfree(mac_addr_filter);
-+exit_p:
-+ return ret;
-+}
-+
-+/**
-+ * xradio_set_arpreply -called for creating and
-+ * configuring arp response template frame
-+ *
-+ * @hw: the hardware
-+ *
-+ * Returns: 0 on success or non zero value on failure
-+ */
-+int xradio_set_arpreply(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-+{
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct xradio_common *hw_priv = (struct xradio_common *)hw->priv;
-+ u32 framehdrlen, encrypthdr, encrypttailsize, framebdylen = 0;
-+ bool encrypt = false;
-+ int ret = 0;
-+ u8 *template_frame = NULL;
-+ struct ieee80211_hdr_3addr *dot11hdr = NULL;
-+ struct ieee80211_snap_hdr *snaphdr = NULL;
-+ struct arphdr *arp_hdr = NULL;
-+
-+
-+ template_frame = kzalloc(MAX_ARP_REPLY_TEMPLATE_SIZE, GFP_KERNEL);
-+ if (!template_frame) {
-+ sta_printk(XRADIO_DBG_ERROR, "Template frame memory failed\n");
-+ ret = -ENOMEM;
-+ goto exit_p;
-+ }
-+ dot11hdr = (struct ieee80211_hdr_3addr *)&template_frame[4];
-+
-+ framehdrlen = sizeof(*dot11hdr);
-+ if ((priv->vif->type == NL80211_IFTYPE_AP) && priv->vif->p2p)
-+ priv->cipherType = WLAN_CIPHER_SUITE_CCMP;
-+ switch (priv->cipherType) {
-+
-+ case WLAN_CIPHER_SUITE_WEP40:
-+ case WLAN_CIPHER_SUITE_WEP104:
-+ sta_printk(XRADIO_DBG_NIY, "WEP\n");
-+ encrypthdr = WEP_ENCRYPT_HDR_SIZE;
-+ encrypttailsize = WEP_ENCRYPT_TAIL_SIZE;
-+ encrypt = 1;
-+ break;
-+
-+
-+ case WLAN_CIPHER_SUITE_TKIP:
-+ sta_printk(XRADIO_DBG_NIY, "WPA\n");
-+ encrypthdr = WPA_ENCRYPT_HDR_SIZE;
-+ encrypttailsize = WPA_ENCRYPT_TAIL_SIZE;
-+ encrypt = 1;
-+ break;
-+
-+ case WLAN_CIPHER_SUITE_CCMP:
-+ sta_printk(XRADIO_DBG_NIY, "WPA2\n");
-+ encrypthdr = WPA2_ENCRYPT_HDR_SIZE;
-+ encrypttailsize = WPA2_ENCRYPT_TAIL_SIZE;
-+ encrypt = 1;
-+ break;
-+
-+ case WLAN_CIPHER_SUITE_SMS4:
-+ sta_printk(XRADIO_DBG_NIY, "WAPI\n");
-+ encrypthdr = WAPI_ENCRYPT_HDR_SIZE;
-+ encrypttailsize = WAPI_ENCRYPT_TAIL_SIZE;
-+ encrypt = 1;
-+ break;
-+
-+ default:
-+ encrypthdr = 0;
-+ encrypttailsize = 0;
-+ encrypt = 0;
-+ break;
-+ }
-+
-+ framehdrlen += encrypthdr;
-+ /* Filling the 802.11 Hdr */
-+ dot11hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA);
-+ if (priv->vif->type == NL80211_IFTYPE_STATION)
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
-+ else
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
-+
-+ if (encrypt)
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_WEP);
-+
-+ if (priv->vif->bss_conf.qos) {
-+ sta_printk(XRADIO_DBG_NIY, "QOS Enabled\n");
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_QOS_DATAGRP);
-+ *(u16 *)(dot11hdr + 1) = 0x0;
-+ framehdrlen += 2;
-+ } else {
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_STYPE_DATA);
-+ }
-+
-+ memcpy(dot11hdr->addr1, priv->vif->bss_conf.bssid, ETH_ALEN);
-+ memcpy(dot11hdr->addr2, priv->vif->addr, ETH_ALEN);
-+ memcpy(dot11hdr->addr3, priv->vif->bss_conf.bssid, ETH_ALEN);
-+
-+ /* Filling the LLC/SNAP Hdr */
-+ snaphdr = (struct ieee80211_snap_hdr *)((u8 *)dot11hdr + framehdrlen);
-+ memcpy(snaphdr, (struct ieee80211_snap_hdr *)rfc1042_header, \
-+ sizeof(*snaphdr));
-+ *(u16 *)(++snaphdr) = cpu_to_be16(ETH_P_ARP);
-+ /* Updating the framebdylen with snaphdr and LLC hdr size */
-+ framebdylen = sizeof(*snaphdr) + 2;
-+
-+ /* Filling the ARP Reply Payload */
-+ arp_hdr = (struct arphdr *)((u8 *)dot11hdr + framehdrlen + framebdylen);
-+ arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER);
-+ arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP);
-+ arp_hdr->ar_hln = ETH_ALEN;
-+ arp_hdr->ar_pln = 4;
-+ arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY);
-+
-+ /* Updating the frmbdylen with Arp Reply Hdr and Arp payload size(20) */
-+ framebdylen += sizeof(*arp_hdr) + 20;
-+
-+ /* Updating the framebdylen with Encryption Tail Size */
-+ framebdylen += encrypttailsize;
-+
-+ /* Filling the Template Frame Hdr */
-+ template_frame[0] = WSM_FRAME_TYPE_ARP_REPLY; /* Template frame type */
-+ template_frame[1] = 0xFF; /* Rate to be fixed */
-+ ((u16 *)&template_frame[2])[0] = framehdrlen + framebdylen;
-+
-+ ret = WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_TEMPLATE_FRAME, \
-+ template_frame, (framehdrlen+framebdylen+4),
-+ priv->if_id));
-+ kfree(template_frame);
-+exit_p:
-+ return ret;
-+}
-+
-+#ifdef ROAM_OFFLOAD
-+/**
-+ * xradio_testmode_event -send asynchronous event
-+ * to userspace
-+ *
-+ * @wiphy: the wiphy
-+ * @msg_id: XR msg ID
-+ * @data: data to be sent
-+ * @len: data length
-+ * @gfp: allocation flag
-+ *
-+ * Returns: 0 on success or non zero value on failure
-+ */
-+int xradio_testmode_event(struct wiphy *wiphy, const u32 msg_id,
-+ const void *data, int len, gfp_t gfp)
-+{
-+ struct sk_buff *skb = NULL;
-+
-+
-+ skb = cfg80211_testmode_alloc_event_skb(wiphy,
-+ nla_total_size(len+sizeof(msg_id)), gfp);
-+
-+ if (!skb)
-+ return -ENOMEM;
-+
-+ cfg80211_testmode_event(skb, gfp);
-+ return 0;
-+}
-+#endif /*ROAM_OFFLOAD*/
-diff --git a/drivers/net/wireless/xradio/sta.h b/drivers/net/wireless/xradio/sta.h
-new file mode 100644
-index 0000000..42ea2f6
---- /dev/null
-+++ b/drivers/net/wireless/xradio/sta.h
-@@ -0,0 +1,122 @@
-+/*
-+ * sta interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef STA_H_INCLUDED
-+#define STA_H_INCLUDED
-+
-+
-+#ifdef XRADIO_USE_LONG_KEEP_ALIVE_PERIOD
-+#define XRADIO_KEEP_ALIVE_PERIOD (28)
-+#else
-+/*For Samsung, it is defined as 4*/
-+#define XRADIO_KEEP_ALIVE_PERIOD (4)
-+#endif
-+
-+#ifdef XRADIO_USE_LONG_DTIM_PERIOD
-+#define XRADIO_BSS_LOSS_THOLD_DEF 30
-+#define XRADIO_LINK_LOSS_THOLD_DEF 50
-+#else
-+#define XRADIO_BSS_LOSS_THOLD_DEF 20
-+#define XRADIO_LINK_LOSS_THOLD_DEF 40
-+#endif
-+
-+/* ******************************************************************** */
-+/* mac80211 API */
-+
-+int xradio_start(struct ieee80211_hw *dev);
-+void xradio_stop(struct ieee80211_hw *dev);
-+int xradio_add_interface(struct ieee80211_hw *dev, struct ieee80211_vif *vif);
-+void xradio_remove_interface(struct ieee80211_hw *dev, struct ieee80211_vif *vif);
-+int xradio_change_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ enum nl80211_iftype new_type,
-+ bool p2p);
-+int xradio_config(struct ieee80211_hw *dev, u32 changed);
-+int xradio_change_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ enum nl80211_iftype new_type,
-+ bool p2p);
-+void xradio_configure_filter(struct ieee80211_hw *dev,
-+ unsigned int changed_flags,
-+ unsigned int *total_flags,
-+ u64 multicast);
-+int xradio_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
-+ u16 queue, const struct ieee80211_tx_queue_params *params);
-+int xradio_get_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_low_level_stats *stats);
-+/* Not more a part of interface?
-+int xradio_get_tx_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_tx_queue_stats *stats);
-+*/
-+int xradio_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
-+
-+void xradio_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop);
-+
-+
-+int xradio_remain_on_channel(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_channel *chan,
-+ int duration, enum ieee80211_roc_type type);
-+int xradio_cancel_remain_on_channel(struct ieee80211_hw *hw);
-+int xradio_set_arpreply(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-+u64 xradio_prepare_multicast(struct ieee80211_hw *hw,
-+ struct netdev_hw_addr_list *mc_list);
-+int xradio_set_pm(struct xradio_vif *priv, const struct wsm_set_pm *arg);
-+void xradio_set_data_filter(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ void *data,
-+ int len);
-+
-+/* ******************************************************************** */
-+/* WSM callbacks */
-+
-+/* void xradio_set_pm_complete_cb(struct xradio_common *hw_priv,
-+ struct wsm_set_pm_complete *arg); */
-+void xradio_channel_switch_cb(struct xradio_common *hw_priv);
-+
-+/* ******************************************************************** */
-+/* WSM events */
-+
-+void xradio_free_event_queue(struct xradio_common *hw_priv);
-+void xradio_event_handler(struct work_struct *work);
-+void xradio_bss_loss_work(struct work_struct *work);
-+void xradio_connection_loss_work(struct work_struct *work);
-+void xradio_keep_alive_work(struct work_struct *work);
-+void xradio_tx_failure_work(struct work_struct *work);
-+
-+/* ******************************************************************** */
-+/* Internal API */
-+
-+int xradio_setup_mac(struct xradio_common *hw_priv);
-+void xradio_join_work(struct work_struct *work);
-+void xradio_join_timeout(struct work_struct *work);
-+void xradio_unjoin_work(struct work_struct *work);
-+void xradio_offchannel_work(struct work_struct *work);
-+void xradio_wep_key_work(struct work_struct *work);
-+void xradio_update_filtering(struct xradio_vif *priv);
-+void xradio_update_filtering_work(struct work_struct *work);
-+int __xradio_flush(struct xradio_common *hw_priv, bool drop, int if_id);
-+void xradio_set_beacon_wakeup_period_work(struct work_struct *work);
-+int xradio_enable_listening(struct xradio_vif *priv, struct ieee80211_channel *chan);
-+int xradio_disable_listening(struct xradio_vif *priv);
-+int xradio_set_uapsd_param(struct xradio_vif *priv, const struct wsm_edca_params *arg);
-+void xradio_ba_work(struct work_struct *work);
-+void xradio_ba_timer(struct timer_list *t);
-+const u8 *xradio_get_ie(u8 *start, size_t len, u8 ie);
-+int xradio_vif_setup(struct xradio_vif *priv);
-+int xradio_setup_mac_pvif(struct xradio_vif *priv);
-+void xradio_iterate_vifs(void *data, u8 *mac, struct ieee80211_vif *vif);
-+void xradio_rem_chan_timeout(struct work_struct *work);
-+int xradio_set_macaddrfilter(struct xradio_common *hw_priv, struct xradio_vif *priv, u8 *data);
-+#ifdef ROAM_OFFLOAD
-+int xradio_testmode_event(struct wiphy *wiphy, const u32 msg_id,
-+ const void *data, int len, gfp_t gfp);
-+#endif /*ROAM_OFFLOAD*/
-+#endif
-diff --git a/drivers/net/wireless/xradio/tx.c b/drivers/net/wireless/xradio/tx.c
-new file mode 100644
-index 0000000..72c04ef
---- /dev/null
-+++ b/drivers/net/wireless/xradio/tx.c
-@@ -0,0 +1,1455 @@
-+/*
-+ * Datapath implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "wsm.h"
-+#include "bh.h"
-+#include "ap.h"
-+#include "sta.h"
-+#include "sdio.h"
-+#include "common.h"
-+#include "p2p.h"
-+
-+#define B_RATE_INDEX 0 //11b rate for important short frames in 2.4G.
-+#define AG_RATE_INDEX 6 //11a/g rate for important short frames in 5G.
-+#define XRADIO_INVALID_RATE_ID (0xFF)
-+
-+/* rate should fall quickly to avoid dropping frames by aps.
-+ * Add by yangfh 2014-9-22 13:39:57
-+ */
-+#define HIGH_RATE_MAX_RETRY 7
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+#include
-+#endif
-+
-+//for test yangfh
-+extern u32 tx_retrylimit;
-+extern u32 tx_over_limit;
-+extern u32 tx_lower_limit;
-+extern int retry_mis;
-+
-+static const struct ieee80211_rate *
-+xradio_get_tx_rate(const struct xradio_common *hw_priv,
-+ const struct ieee80211_tx_rate *rate);
-+
-+/* ******************************************************************** */
-+/* TX policy cache implementation */
-+
-+static void tx_policy_dump(struct tx_policy *policy)
-+{
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] "
-+ "%.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X"
-+ "%.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X"
-+ "%.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X: %d\n",
-+ policy->raw[0] & 0x0F, policy->raw[0] >> 4,
-+ policy->raw[1] & 0x0F, policy->raw[1] >> 4,
-+ policy->raw[2] & 0x0F, policy->raw[2] >> 4,
-+ policy->raw[3] & 0x0F, policy->raw[3] >> 4,
-+ policy->raw[4] & 0x0F, policy->raw[4] >> 4,
-+ policy->raw[5] & 0x0F, policy->raw[5] >> 4,
-+ policy->raw[6] & 0x0F, policy->raw[6] >> 4,
-+ policy->raw[7] & 0x0F, policy->raw[7] >> 4,
-+ policy->raw[8] & 0x0F, policy->raw[8] >> 4,
-+ policy->raw[9] & 0x0F, policy->raw[9] >> 4,
-+ policy->raw[10] & 0x0F, policy->raw[10] >> 4,
-+ policy->raw[11] & 0x0F, policy->raw[11] >> 4,
-+ policy->defined);
-+}
-+
-+static void xradio_check_go_neg_conf_success(struct xradio_common *hw_priv,
-+ u8 *action)
-+{
-+ if (action[2] == 0x50 && action[3] == 0x6F && action[4] == 0x9A &&
-+ action[5] == 0x09 && action[6] == 0x02) {
-+ if(action[17] == 0) {
-+ hw_priv->is_go_thru_go_neg = true;
-+ }
-+ else {
-+ hw_priv->is_go_thru_go_neg = false;
-+ }
-+ }
-+}
-+
-+static void xradio_check_prov_desc_req(struct xradio_common *hw_priv,
-+ u8 *action)
-+{
-+ if (action[2] == 0x50 && action[3] == 0x6F && action[4] == 0x9A &&
-+ action[5] == 0x09 && action[6] == 0x07) {
-+ hw_priv->is_go_thru_go_neg = false;
-+ }
-+}
-+
-+//modified by yangfh
-+static void tx_policy_build(const struct xradio_common *hw_priv,
-+ /* [out] */ struct tx_policy *policy,
-+ struct ieee80211_tx_rate *rates, size_t count)
-+{
-+ int i, j;
-+ struct ieee80211_rate * tmp_rate = NULL;
-+ unsigned limit = hw_priv->short_frame_max_tx_count;
-+ unsigned max_rates_cnt = count;
-+ unsigned total = 0;
-+ BUG_ON(rates[0].idx < 0);
-+ memset(policy, 0, sizeof(*policy));
-+
-+
-+ txrx_printk(XRADIO_DBG_NIY,"============================");
-+#if 0
-+ //debug yangfh
-+ for (i = 0; i < count; ++i) {
-+ if(rates[i].idx>=0) {
-+ tmp_rate = xradio_get_tx_rate(hw_priv, &rates[i]);
-+ txrx_printk(XRADIO_DBG_NIY,"[TX policy] Org %d.%dMps=%d",
-+ tmp_rate->bitrate/10, tmp_rate->bitrate%10, rates[i].count);
-+ }
-+ }
-+ txrx_printk(XRADIO_DBG_NIY,"----------------------------");
-+#endif
-+
-+ /* minstrel is buggy a little bit, so distille
-+ * incoming rates first.
-+ */
-+ /* Sort rates in descending order. */
-+ total = rates[0].count;
-+ for (i = 1; i < count; ++i) {
-+ if (rates[i].idx > rates[i-1].idx) {
-+ rates[i].idx = rates[i-1].idx>0?(rates[i-1].idx-1):-1;
-+ }
-+ if (rates[i].idx < 0 || i>=limit) {
-+ count = i;
-+ break;
-+ } else {
-+ total += rates[i].count;
-+ }
-+ }
-+
-+ /* Add lowest rate to the end when 11a/n.
-+ * Don't apply in 11b/g because p2p unsupport 1Mbps.
-+ * TODO: it's better to do this in rate control of mac80211.
-+ */
-+ if (((rates[0].flags & IEEE80211_TX_RC_MCS) ||
-+ hw_priv->channel->band == NL80211_BAND_5GHZ) &&
-+ count < max_rates_cnt && rates[count-1].idx != 0) {
-+ rates[count].idx = 0;
-+ rates[count].count = rates[0].count;
-+ rates[count].flags = rates[0].flags;
-+ total += rates[count].count;
-+ count++;
-+ }
-+
-+ /* adjust tx count to limit, rates should fall quickly
-+ * and lower rates should be more retry, because reorder
-+ * buffer of reciever will be timeout and clear probably.
-+ */
-+ if (count < 2) {
-+ rates[0].count = limit;
-+ total = limit;
-+ } else {
-+ u8 end_retry = 0; //the retry should be add to last rate.
-+ if (limit > HIGH_RATE_MAX_RETRY) {
-+ end_retry = limit - HIGH_RATE_MAX_RETRY;
-+ limit = HIGH_RATE_MAX_RETRY;
-+ }
-+ for (i = 0; (limit != total) && (i < 100); ++i) { //i<100 to avoid dead loop
-+ j = i % count;
-+ if(limit < total) {
-+ total += (rates[j].count > 1? -1 : 0);
-+ rates[j].count += (rates[j].count > 1? -1 : 0);
-+ } else {
-+ j = count - 1 - j;
-+ if (rates[j].count > 0) {
-+ total++;
-+ rates[j].count++;
-+ }
-+ }
-+ }
-+ if (end_retry) {
-+ rates[count-1].count += end_retry;
-+ limit += end_retry;
-+ }
-+ }
-+
-+ /* Eliminate duplicates. */
-+ total = rates[0].count;
-+ for (i = 0, j = 1; j < count; ++j) {
-+ if (rates[j].idx == rates[i].idx) {
-+ rates[i].count += rates[j].count;
-+ } else if (rates[j].idx > rates[i].idx) {
-+ break;
-+ } else {
-+ ++i;
-+ if (i != j)
-+ rates[i] = rates[j];
-+ }
-+ total += rates[j].count;
-+ }
-+ count = i + 1;
-+
-+ /* Re-fill policy trying to keep every requested rate and with
-+ * respect to the global max tx retransmission count.
-+ */
-+ if (limit < count)
-+ limit = count;
-+ if (total > limit) {
-+ for (i = 0; i < count; ++i) {
-+ int left = count - i - 1;
-+ if (rates[i].count > limit - left)
-+ rates[i].count = limit - left;
-+ limit -= rates[i].count;
-+ }
-+ }
-+
-+ /* HACK!!! Device has problems (at least) switching from
-+ * 54Mbps CTS to 1Mbps. This switch takes enormous amount
-+ * of time (100-200 ms), leading to valuable throughput drop.
-+ * As a workaround, additional g-rates are injected to the
-+ * policy.
-+ */
-+ if (count == 2 && !(rates[0].flags & IEEE80211_TX_RC_MCS) &&
-+ rates[0].idx > 4 && rates[0].count > 2 &&
-+ rates[1].idx < 2) {
-+ /* ">> 1" is an equivalent of "/ 2", but faster */
-+ int mid_rate = (rates[0].idx + 4) >> 1;
-+
-+ /* Decrease number of retries for the initial rate */
-+ rates[0].count -= 2;
-+
-+ if (mid_rate != 4) {
-+ /* Keep fallback rate at 1Mbps. */
-+ rates[3] = rates[1];
-+
-+ /* Inject 1 transmission on lowest g-rate */
-+ rates[2].idx = 4;
-+ rates[2].count = 1;
-+ rates[2].flags = rates[1].flags;
-+
-+ /* Inject 1 transmission on mid-rate */
-+ rates[1].idx = mid_rate;
-+ rates[1].count = 1;
-+
-+ /* Fallback to 1 Mbps is a really bad thing,
-+ * so let's try to increase probability of
-+ * successful transmission on the lowest g rate
-+ * even more */
-+ if (rates[0].count >= 3) {
-+ --rates[0].count;
-+ ++rates[2].count;
-+ }
-+
-+ /* Adjust amount of rates defined */
-+ count += 2;
-+ } else {
-+ /* Keep fallback rate at 1Mbps. */
-+ rates[2] = rates[1];
-+
-+ /* Inject 2 transmissions on lowest g-rate */
-+ rates[1].idx = 4;
-+ rates[1].count = 2;
-+
-+ /* Adjust amount of rates defined */
-+ count += 1;
-+ }
-+ }
-+
-+ tmp_rate = (struct ieee80211_rate *)xradio_get_tx_rate(hw_priv, &rates[0]);
-+ if(tmp_rate)
-+ policy->defined = tmp_rate->hw_value + 1;
-+
-+ for (i = 0; i < count; ++i) {
-+ register unsigned rateid, off, shift, retries;
-+
-+ tmp_rate = (struct ieee80211_rate *)xradio_get_tx_rate(hw_priv, &rates[i]);
-+ if(tmp_rate) {
-+ rateid = tmp_rate->hw_value;
-+ } else {
-+ break;
-+ }
-+ off = rateid >> 3; /* eq. rateid / 8 */
-+ shift = (rateid & 0x07) << 2; /* eq. (rateid % 8) * 4 */
-+
-+ retries = rates[i].count;
-+ if (unlikely(retries > 0x0F))
-+ rates[i].count = retries = 0x0F;
-+ policy->tbl[off] |= __cpu_to_le32(retries << shift);
-+ policy->retry_count += retries;
-+ txrx_printk(XRADIO_DBG_NIY,"[TX policy] %d.%dMps=%d",
-+ tmp_rate->bitrate/10, tmp_rate->bitrate%10, retries);
-+ }
-+
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] Dst Policy (%d): " \
-+ "%d:%d, %d:%d, %d:%d, %d:%d, %d:%d\n",
-+ count,
-+ rates[0].idx, rates[0].count,
-+ rates[1].idx, rates[1].count,
-+ rates[2].idx, rates[2].count,
-+ rates[3].idx, rates[3].count,
-+ rates[4].idx, rates[4].count);
-+}
-+
-+static inline bool tx_policy_is_equal(const struct tx_policy *wanted,
-+ const struct tx_policy *cached)
-+{
-+ size_t count = wanted->defined >> 1;
-+
-+ if (wanted->defined > cached->defined)
-+ return false;
-+ if (count) {
-+ if (memcmp(wanted->raw, cached->raw, count))
-+ return false;
-+ }
-+ if (wanted->defined & 1) {
-+ if ((wanted->raw[count] & 0x0F) != (cached->raw[count] & 0x0F))
-+ return false;
-+ }
-+ return true;
-+}
-+
-+static int tx_policy_find(struct tx_policy_cache *cache,
-+ const struct tx_policy *wanted)
-+{
-+ /* O(n) complexity. Not so good, but there's only 8 entries in
-+ * the cache.
-+ * Also lru helps to reduce search time. */
-+ struct tx_policy_cache_entry *it;
-+ /* Search for policy in "used" list */
-+ list_for_each_entry(it, &cache->used, link) {
-+ if (tx_policy_is_equal(wanted, &it->policy))
-+ return it - cache->cache;
-+ }
-+ /* Then - in "free list" */
-+ list_for_each_entry(it, &cache->free, link) {
-+ if (tx_policy_is_equal(wanted, &it->policy))
-+ return it - cache->cache;
-+ }
-+ return -1;
-+}
-+
-+static inline void tx_policy_use(struct tx_policy_cache *cache,
-+ struct tx_policy_cache_entry *entry)
-+{
-+ ++entry->policy.usage_count;
-+ list_move(&entry->link, &cache->used);
-+}
-+
-+static inline int tx_policy_release(struct tx_policy_cache *cache,
-+ struct tx_policy_cache_entry *entry)
-+{
-+ int ret = --entry->policy.usage_count;
-+ if (!ret)
-+ list_move(&entry->link, &cache->free);
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+/* External TX policy cache API */
-+
-+void tx_policy_init(struct xradio_common *hw_priv)
-+{
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+ int i;
-+
-+ memset(cache, 0, sizeof(*cache));
-+
-+ spin_lock_init(&cache->lock);
-+ INIT_LIST_HEAD(&cache->used);
-+ INIT_LIST_HEAD(&cache->free);
-+
-+ for (i = 0; i < TX_POLICY_CACHE_SIZE; ++i)
-+ list_add(&cache->cache[i].link, &cache->free);
-+}
-+
-+static int tx_policy_get(struct xradio_common *hw_priv,
-+ struct ieee80211_tx_rate *rates,
-+ u8 use_bg_rate, bool *renew)
-+{
-+ int idx;
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+ struct tx_policy wanted;
-+
-+
-+ if(use_bg_rate) {
-+ u8 rate = (u8)(use_bg_rate & 0x3f);
-+ u8 shitf = ((rate&0x7)<<2);
-+ u8 off = (rate>>3);
-+ memset(&wanted, 0, sizeof(wanted));
-+ wanted.defined = rate + 1;
-+ wanted.retry_count = (hw_priv->short_frame_max_tx_count&0xf);
-+ wanted.tbl[off] = wanted.retry_count<lock);
-+ idx = tx_policy_find(cache, &wanted);
-+ if (idx >= 0) {
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] Used TX policy: %d\n",
-+ idx);
-+ *renew = false;
-+ } else {
-+ struct tx_policy_cache_entry *entry;
-+ if (WARN_ON_ONCE(list_empty(&cache->free))) {
-+ spin_unlock_bh(&cache->lock);
-+ txrx_printk(XRADIO_DBG_ERROR, "[TX policy] no policy cache\n");
-+ return XRADIO_INVALID_RATE_ID;
-+ }
-+ /* If policy is not found create a new one
-+ * using the oldest entry in "free" list */
-+ *renew = true;
-+ entry = list_entry(cache->free.prev,
-+ struct tx_policy_cache_entry, link);
-+ entry->policy = wanted;
-+ idx = entry - cache->cache;
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] New TX policy: %d\n",
-+ idx);
-+ tx_policy_dump(&entry->policy);
-+ }
-+ tx_policy_use(cache, &cache->cache[idx]);
-+ if (unlikely(list_empty(&cache->free))) {
-+ /* Lock TX queues. */
-+ txrx_printk(XRADIO_DBG_WARN, "[TX policy] policy cache used up\n");
-+ xradio_tx_queues_lock(hw_priv);
-+ }
-+ spin_unlock_bh(&cache->lock);
-+
-+ return idx;
-+}
-+
-+static void tx_policy_put(struct xradio_common *hw_priv, int idx)
-+{
-+ int usage, locked;
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+
-+ spin_lock_bh(&cache->lock);
-+ locked = list_empty(&cache->free);
-+ usage = tx_policy_release(cache, &cache->cache[idx]);
-+ if (unlikely(locked) && !usage) {
-+ /* Unlock TX queues. */
-+ xradio_tx_queues_unlock(hw_priv);
-+ }
-+ spin_unlock_bh(&cache->lock);
-+}
-+
-+/*
-+bool tx_policy_cache_full(struct xradio_common *hw_priv)
-+{
-+ bool ret;
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+ spin_lock_bh(&cache->lock);
-+ ret = list_empty(&cache->free);
-+ spin_unlock_bh(&cache->lock);
-+ return ret;
-+}
-+*/
-+extern u32 policy_upload;
-+extern u32 policy_num;
-+static int tx_policy_upload(struct xradio_common *hw_priv)
-+{
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+ int i;
-+ struct wsm_set_tx_rate_retry_policy arg = {
-+ .hdr = {
-+ .numTxRatePolicies = 0,
-+ }
-+ };
-+ int if_id = 0;
-+
-+ spin_lock_bh(&cache->lock);
-+ /* Upload only modified entries. */
-+ for (i = 0; i < TX_POLICY_CACHE_SIZE; ++i) {
-+ struct tx_policy *src = &cache->cache[i].policy;
-+ if (src->retry_count && !src->uploaded) {
-+ struct wsm_set_tx_rate_retry_policy_policy *dst =
-+ &arg.tbl[arg.hdr.numTxRatePolicies];
-+ dst->policyIndex = i;
-+ dst->shortRetryCount = hw_priv->short_frame_max_tx_count-1;
-+ //only RTS need use longRetryCount, should be short_frame.
-+ dst->longRetryCount = hw_priv->short_frame_max_tx_count-1;
-+
-+ /* BIT(2) - Terminate retries when Tx rate retry policy
-+ * finishes.
-+ * BIT(3) - Count initial frame transmission as part of
-+ * rate retry counting but not as a retry
-+ * attempt */
-+ dst->policyFlags = BIT(2) | BIT(3);
-+ memcpy(dst->rateCountIndices, src->tbl,
-+ sizeof(dst->rateCountIndices));
-+ src->uploaded = 1;
-+ ++arg.hdr.numTxRatePolicies;
-+ }
-+ }
-+ spin_unlock_bh(&cache->lock);
-+ atomic_set(&hw_priv->upload_count, 0);
-+
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] Upload %d policies\n",
-+ arg.hdr.numTxRatePolicies);
-+
-+ /*TODO: COMBO*/
-+ return wsm_set_tx_rate_retry_policy(hw_priv, &arg, if_id);
-+}
-+
-+void tx_policy_upload_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, tx_policy_upload_work);
-+
-+ WARN_ON(tx_policy_upload(hw_priv));
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+/* ******************************************************************** */
-+/* xradio TX implementation */
-+
-+struct xradio_txinfo {
-+ struct sk_buff *skb;
-+ unsigned queue;
-+ struct ieee80211_tx_info *tx_info;
-+ const struct ieee80211_rate *rate;
-+ struct ieee80211_hdr *hdr;
-+ size_t hdrlen;
-+ const u8 *da;
-+ struct xradio_sta_priv *sta_priv;
-+ struct xradio_txpriv txpriv;
-+};
-+
-+u32 xradio_rate_mask_to_wsm(struct xradio_common *hw_priv, u32 rates)
-+{
-+ u32 ret = 0;
-+ int i;
-+ u32 n_bitrates =
-+ hw_priv->hw->wiphy->bands[hw_priv->channel->band]->n_bitrates;
-+ struct ieee80211_rate * bitrates =
-+ hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates;
-+
-+ for (i = 0; i < n_bitrates; ++i) {
-+ if (rates & BIT(i))
-+ ret |= BIT(bitrates[i].hw_value);
-+ }
-+ return ret;
-+}
-+
-+static const struct ieee80211_rate *
-+xradio_get_tx_rate(const struct xradio_common *hw_priv,
-+ const struct ieee80211_tx_rate *rate)
-+{
-+ if (rate->idx < 0)
-+ return NULL;
-+ if (rate->flags & IEEE80211_TX_RC_MCS)
-+ return &hw_priv->mcs_rates[rate->idx];
-+ return &hw_priv->hw->wiphy->bands[hw_priv->channel->band]->
-+ bitrates[rate->idx];
-+}
-+
-+inline static s8
-+xradio_get_rate_idx(const struct xradio_common *hw_priv, u8 flag, u16 hw_value)
-+{
-+ s16 ret = (s16)hw_value;
-+ if(flag & IEEE80211_TX_RC_MCS) { //11n
-+ if(hw_value <= hw_priv->mcs_rates[7].hw_value &&
-+ hw_value >= hw_priv->mcs_rates[0].hw_value)
-+ ret -= hw_priv->mcs_rates[0].hw_value;
-+ else
-+ ret = -1;
-+ } else { //11b/g
-+ if(hw_value>5 && hw_valuemcs_rates[0].hw_value) {
-+ ret -= hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates[0].hw_value;
-+ if(hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates[0].hw_value<5) //11a
-+ ret -= 2;
-+ } else if(hw_value<4) {
-+ ret -= hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates[0].hw_value;
-+ } else {
-+ ret = -1;
-+ }
-+ }
-+ return (s8)ret;
-+}
-+
-+static int
-+xradio_tx_h_calc_link_ids(struct xradio_vif *priv,
-+ struct ieee80211_tx_control *control,
-+ struct xradio_txinfo *t)
-+{
-+
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ if ((t->tx_info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
-+ (hw_priv->roc_if_id == priv->if_id))
-+ t->txpriv.offchannel_if_id = 2;
-+ else
-+ t->txpriv.offchannel_if_id = 0;
-+
-+ if (likely(control->sta && t->sta_priv->link_id))
-+ t->txpriv.raw_link_id =
-+ t->txpriv.link_id =
-+ t->sta_priv->link_id;
-+ else if (priv->mode != NL80211_IFTYPE_AP)
-+ t->txpriv.raw_link_id =
-+ t->txpriv.link_id = 0;
-+ else if (is_multicast_ether_addr(t->da)) {
-+ if (priv->enable_beacon) {
-+ t->txpriv.raw_link_id = 0;
-+ t->txpriv.link_id = priv->link_id_after_dtim;
-+ } else {
-+ t->txpriv.raw_link_id = 0;
-+ t->txpriv.link_id = 0;
-+ }
-+ } else {
-+ t->txpriv.link_id =
-+ xradio_find_link_id(priv, t->da);
-+ /* Do not assign valid link id for deauth/disassoc frame being
-+ transmitted to an unassociated STA */
-+ if (!(t->txpriv.link_id) &&
-+ (ieee80211_is_deauth(t->hdr->frame_control) ||
-+ ieee80211_is_disassoc(t->hdr->frame_control))) {
-+ t->txpriv.link_id = 0;
-+ } else {
-+ if (!t->txpriv.link_id)
-+ t->txpriv.link_id = xradio_alloc_link_id(priv, t->da);
-+ if (!t->txpriv.link_id) {
-+ txrx_printk(XRADIO_DBG_ERROR,
-+ "%s: No more link IDs available.\n", __func__);
-+ return -ENOENT;
-+ }
-+ }
-+ t->txpriv.raw_link_id = t->txpriv.link_id;
-+ }
-+ if (t->txpriv.raw_link_id)
-+ priv->link_id_db[t->txpriv.raw_link_id - 1].timestamp =
-+ jiffies;
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ if (control->sta &&
-+ (control->sta->uapsd_queues & BIT(t->queue)))
-+ t->txpriv.link_id = priv->link_id_uapsd;
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ return 0;
-+}
-+
-+static void
-+xradio_tx_h_pm(struct xradio_vif *priv,
-+ struct xradio_txinfo *t)
-+{
-+ if (unlikely(ieee80211_is_auth(t->hdr->frame_control))) {
-+ u32 mask = ~BIT(t->txpriv.raw_link_id);
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->sta_asleep_mask &= mask;
-+ priv->pspoll_mask &= mask;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ }
-+}
-+
-+static void
-+xradio_tx_h_calc_tid(struct xradio_vif *priv,
-+ struct xradio_txinfo *t)
-+{
-+ if (ieee80211_is_data_qos(t->hdr->frame_control)) {
-+ u8 *qos = ieee80211_get_qos_ctl(t->hdr);
-+ t->txpriv.tid = qos[0] & IEEE80211_QOS_CTL_TID_MASK;
-+ } else if (ieee80211_is_data(t->hdr->frame_control)) {
-+ t->txpriv.tid = 0;
-+ }
-+}
-+
-+/* IV/ICV injection. */
-+/* TODO: Quite unoptimal. It's better co modify mac80211
-+ * to reserve space for IV */
-+static int
-+xradio_tx_h_crypt(struct xradio_vif *priv,
-+ struct xradio_txinfo *t)
-+{
-+ size_t iv_len;
-+ size_t icv_len;
-+ u8 *icv;
-+
-+ if (!t->tx_info->control.hw_key ||
-+ !(t->hdr->frame_control &
-+ __cpu_to_le32(IEEE80211_FCTL_PROTECTED)))
-+ return 0;
-+
-+ iv_len = t->tx_info->control.hw_key->iv_len;
-+ icv_len = t->tx_info->control.hw_key->icv_len;
-+
-+ if (t->tx_info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
-+ icv_len += 8; /* MIC */
-+
-+ if (unlikely((skb_headroom(t->skb) + skb_tailroom(t->skb) <
-+ iv_len + icv_len + WSM_TX_EXTRA_HEADROOM) ||
-+ (skb_headroom(t->skb) <
-+ iv_len + WSM_TX_EXTRA_HEADROOM))) {
-+ dev_dbg(priv->hw_priv->pdev,
-+ "no space allocated for crypto headers.\n"
-+ "headroom: %d, tailroom: %d, "
-+ "req_headroom: %d, req_tailroom: %d\n"
-+ "Please fix it in xradio_get_skb().\n",
-+ skb_headroom(t->skb), skb_tailroom(t->skb),
-+ iv_len + WSM_TX_EXTRA_HEADROOM, icv_len);
-+ return -ENOMEM;
-+ } else if (unlikely(skb_tailroom(t->skb) < icv_len)) {
-+ size_t offset = icv_len - skb_tailroom(t->skb);
-+ u8 *p;
-+ dev_dbg(priv->hw_priv->pdev,
-+ "Slowpath: tailroom is not big enough. "
-+ "Req: %d, got: %d.\n",
-+ icv_len, skb_tailroom(t->skb));
-+
-+ p = skb_push(t->skb, offset);
-+ memmove(p, &p[offset], t->skb->len - offset);
-+ skb_trim(t->skb, t->skb->len - offset);
-+ }
-+ /* ccmp pkt from umac to driver,it has iv room,,so ccmp pkt do not add iv room */
-+ if (t->tx_info->control.hw_key->cipher != WLAN_CIPHER_SUITE_CCMP){
-+ u8 *newhdr;
-+ newhdr = skb_push(t->skb, iv_len);
-+ memmove(newhdr, newhdr + iv_len, t->hdrlen);
-+ t->hdr = (struct ieee80211_hdr *) newhdr;
-+ }
-+ t->hdrlen += iv_len;
-+ icv = skb_put(t->skb, icv_len);
-+
-+ return 0;
-+}
-+
-+static int
-+xradio_tx_h_align(struct xradio_vif *priv, struct xradio_txinfo *t,
-+ u8 *flags)
-+{
-+ size_t offset = (size_t)t->skb->data & 3;
-+ u8 *newhdr;//add by dingxh
-+
-+
-+ if (!offset)
-+ return 0;
-+
-+ if (skb_headroom(t->skb) < offset) {
-+ txrx_printk(XRADIO_DBG_ERROR,
-+ "Bug: no space allocated "
-+ "for DMA alignment.\n"
-+ "headroom: %d\n",
-+ skb_headroom(t->skb));
-+ return -ENOMEM;
-+ }
-+ //offset = 1or3 process add by dingxh
-+ if (offset & 1) {
-+ newhdr = skb_push(t->skb, offset);
-+ memmove(newhdr, newhdr + offset, t->skb->len-offset);
-+ skb_trim(t->skb, t->skb->len-offset);
-+ t->hdr = (struct ieee80211_hdr *) newhdr;
-+ return 0;
-+ }
-+ //add by dingxh
-+ //offset=2 process
-+ skb_push(t->skb, offset);
-+ t->hdrlen += offset;
-+ t->txpriv.offset += offset;
-+ *flags |= WSM_TX_2BYTES_SHIFT;
-+ return 0;
-+}
-+
-+static int
-+xradio_tx_h_action(struct xradio_vif *priv, struct xradio_txinfo *t)
-+{
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)t->hdr;
-+
-+ if (ieee80211_is_action(t->hdr->frame_control) &&
-+ mgmt->u.action.category == WLAN_CATEGORY_BACK)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+/* Add WSM header */
-+static struct wsm_tx *
-+xradio_tx_h_wsm(struct xradio_vif *priv, struct xradio_txinfo *t)
-+{
-+ struct wsm_tx *wsm;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ if (skb_headroom(t->skb) < sizeof(struct wsm_tx)) {
-+ txrx_printk(XRADIO_DBG_ERROR,
-+ "Bug: no space allocated "
-+ "for WSM header.\n"
-+ "headroom: %d\n",
-+ skb_headroom(t->skb));
-+ return NULL;
-+ }
-+
-+ wsm = (struct wsm_tx *)skb_push(t->skb, sizeof(struct wsm_tx));
-+ t->txpriv.offset += sizeof(struct wsm_tx);
-+ memset(wsm, 0, sizeof(*wsm));
-+ wsm->hdr.len = __cpu_to_le16(t->skb->len);
-+ wsm->hdr.id = __cpu_to_le16(0x0004);
-+ wsm->queueId = (t->txpriv.raw_link_id << 2) | wsm_queue_id_to_wsm(t->queue);
-+ if (wsm->hdr.len > hw_priv->wsm_caps.sizeInpChBuf) {
-+ txrx_printk(XRADIO_DBG_ERROR,"%s,msg length too big=%d\n",
-+ __func__, wsm->hdr.len);
-+ wsm = NULL;
-+ }
-+
-+ return wsm;
-+}
-+
-+/* BT Coex specific handling */
-+static void
-+xradio_tx_h_bt(struct xradio_vif *priv, struct xradio_txinfo *t, struct wsm_tx *wsm)
-+{
-+ u8 priority = 0;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ if (!hw_priv->is_BT_Present)
-+ return;
-+
-+ if (unlikely(ieee80211_is_nullfunc(t->hdr->frame_control)))
-+ priority = WSM_EPTA_PRIORITY_MGT;
-+ else if (ieee80211_is_data(t->hdr->frame_control)) {
-+ /* Skip LLC SNAP header (+6) */
-+ u8 *payload = &t->skb->data[t->hdrlen];
-+ u16 *ethertype = (u16 *) &payload[6];
-+ if (unlikely(*ethertype == __be16_to_cpu(ETH_P_PAE)))
-+ priority = WSM_EPTA_PRIORITY_EAPOL;
-+ } else if (unlikely(ieee80211_is_assoc_req(t->hdr->frame_control) ||
-+ ieee80211_is_reassoc_req(t->hdr->frame_control))) {
-+ struct ieee80211_mgmt *mgt_frame =
-+ (struct ieee80211_mgmt *)t->hdr;
-+
-+ if (mgt_frame->u.assoc_req.listen_interval <
-+ priv->listen_interval) {
-+ txrx_printk(XRADIO_DBG_MSG,
-+ "Modified Listen Interval to %d from %d\n",
-+ priv->listen_interval,
-+ mgt_frame->u.assoc_req.listen_interval);
-+ /* Replace listen interval derieved from
-+ * the one read from SDD */
-+ mgt_frame->u.assoc_req.listen_interval =
-+ priv->listen_interval;
-+ }
-+ }
-+
-+ if (likely(!priority)) {
-+ if (ieee80211_is_action(t->hdr->frame_control))
-+ priority = WSM_EPTA_PRIORITY_ACTION;
-+ else if (ieee80211_is_mgmt(t->hdr->frame_control))
-+ priority = WSM_EPTA_PRIORITY_MGT;
-+ else if ((wsm->queueId == WSM_QUEUE_VOICE))
-+ priority = WSM_EPTA_PRIORITY_VOICE;
-+ else if ((wsm->queueId == WSM_QUEUE_VIDEO))
-+ priority = WSM_EPTA_PRIORITY_VIDEO;
-+ else
-+ priority = WSM_EPTA_PRIORITY_DATA;
-+ }
-+
-+ txrx_printk(XRADIO_DBG_MSG, "[TX] EPTA priority %d.\n",
-+ priority);
-+
-+ wsm->flags |= priority << 1;
-+}
-+
-+static int
-+xradio_tx_h_rate_policy(struct xradio_common *hw_priv, struct xradio_txinfo *t,
-+ struct wsm_tx *wsm)
-+{
-+ bool tx_policy_renew = false;
-+ struct xradio_vif *priv =
-+ xrwl_get_vif_from_ieee80211(t->tx_info->control.vif);
-+
-+ t->txpriv.rate_id = tx_policy_get(hw_priv,
-+ t->tx_info->control.rates, t->txpriv.use_bg_rate,
-+ &tx_policy_renew);
-+ if (t->txpriv.rate_id == XRADIO_INVALID_RATE_ID)
-+ return -EFAULT;
-+
-+ wsm->flags |= t->txpriv.rate_id << 4;
-+ t->rate = xradio_get_tx_rate(hw_priv, &t->tx_info->control.rates[0]);
-+ if (t->txpriv.use_bg_rate)
-+ wsm->maxTxRate = (u8)(t->txpriv.use_bg_rate & 0x3f);
-+ else
-+ wsm->maxTxRate = t->rate->hw_value;
-+
-+ if (t->rate->flags & IEEE80211_TX_RC_MCS) {
-+ if (priv->association_mode.greenfieldMode)
-+ wsm->htTxParameters |=
-+ __cpu_to_le32(WSM_HT_TX_GREENFIELD);
-+ else
-+ wsm->htTxParameters |=
-+ __cpu_to_le32(WSM_HT_TX_MIXED);
-+ }
-+
-+ if (tx_policy_renew) {
-+ txrx_printk(XRADIO_DBG_MSG, "[TX] TX policy renew.\n");
-+ /* It's not so optimal to stop TX queues every now and then.
-+ * Maybe it's better to reimplement task scheduling with
-+ * a counter. */
-+ /* xradio_tx_queues_lock(priv); */
-+ /* Definetly better. TODO. */
-+ if (atomic_add_return(1, &hw_priv->upload_count) == 1) {
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue,
-+ &hw_priv->tx_policy_upload_work) <= 0) {
-+ atomic_set(&hw_priv->upload_count, 0);
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
-+static bool
-+xradio_tx_h_pm_state(struct xradio_vif *priv, struct xradio_txinfo *t)
-+{
-+ int was_buffered = 1;
-+
-+
-+ if (t->txpriv.link_id == priv->link_id_after_dtim &&
-+ !priv->buffered_multicasts) {
-+ priv->buffered_multicasts = true;
-+ if (priv->sta_asleep_mask)
-+ queue_work(priv->hw_priv->workqueue,
-+ &priv->multicast_start_work);
-+ }
-+
-+ if (t->txpriv.raw_link_id && t->txpriv.tid < XRADIO_MAX_TID)
-+ was_buffered = priv->link_id_db[t->txpriv.raw_link_id - 1]
-+ .buffered[t->txpriv.tid]++;
-+
-+ return !was_buffered;
-+}
-+
-+static void
-+xradio_tx_h_ba_stat(struct xradio_vif *priv,
-+ struct xradio_txinfo *t)
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_STA)
-+ return;
-+ if (!xradio_is_ht(&hw_priv->ht_oper))
-+ return;
-+ if (!priv->setbssparams_done)
-+ return;
-+ if (!ieee80211_is_data(t->hdr->frame_control))
-+ return;
-+
-+ spin_lock_bh(&hw_priv->ba_lock);
-+ hw_priv->ba_acc += t->skb->len - t->hdrlen;
-+ if (!(hw_priv->ba_cnt_rx || hw_priv->ba_cnt)) {
-+ mod_timer(&hw_priv->ba_timer,
-+ jiffies + XRADIO_BLOCK_ACK_INTERVAL);
-+ }
-+ hw_priv->ba_cnt++;
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+}
-+
-+static int
-+xradio_tx_h_skb_pad(struct xradio_common *priv,
-+ struct wsm_tx *wsm,
-+ struct sk_buff *skb)
-+{
-+ size_t len = __le16_to_cpu(wsm->hdr.len);
-+ size_t padded_len = sdio_align_len(priv, len);
-+
-+
-+ if (WARN_ON(skb_padto(skb, padded_len) != 0)) {
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+void xradio_tx(struct ieee80211_hw *dev, struct ieee80211_tx_control *control, struct sk_buff *skb)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_txinfo t = {
-+ .skb = skb,
-+ .queue = skb_get_queue_mapping(skb),
-+ .tx_info = IEEE80211_SKB_CB(skb),
-+ .hdr = (struct ieee80211_hdr *)skb->data,
-+ .txpriv.tid = XRADIO_MAX_TID,
-+ .txpriv.rate_id = XRADIO_INVALID_RATE_ID,
-+ .txpriv.use_bg_rate = 0,
-+ };
-+ struct ieee80211_sta *sta;
-+ struct wsm_tx *wsm;
-+ bool tid_update = 0;
-+ u8 flags = 0;
-+ int ret = 0;
-+ struct xradio_vif *priv;
-+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-+
-+ if (!skb->data)
-+ BUG_ON(1);
-+
-+ if (!(t.tx_info->control.vif)) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+ priv = xrwl_get_vif_from_ieee80211(t.tx_info->control.vif);
-+ if (!priv) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ if (atomic_read(&priv->enabled) == 0) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ //dhcp and 80211 frames are important, use b/g rate and delay scan.
-+ //it can make sense, such as accelerate connect.
-+ if (ieee80211_is_auth(frame->frame_control)) {
-+ hw_priv->connet_time[priv->if_id] = jiffies;
-+ } else if (ieee80211_is_data_present(frame->frame_control)) {
-+ /* since Umac had already alloc IV space in ccmp skb, so we need to add this iv_len as the new offset to LLC */
-+ u8* llc = NULL;
-+ if(t.tx_info->control.hw_key &&
-+ (t.hdr->frame_control & __cpu_to_le32(IEEE80211_FCTL_PROTECTED)) &&
-+ (t.tx_info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP))
-+ llc = skb->data+ieee80211_hdrlen(frame->frame_control) + t.tx_info->control.hw_key->iv_len;
-+ else
-+ llc = skb->data+ieee80211_hdrlen(frame->frame_control);
-+ if (is_dhcp(llc) || is_8021x(llc)) {
-+ t.txpriv.use_bg_rate =
-+ hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates[0].hw_value;
-+ if (priv->vif->p2p)
-+ t.txpriv.use_bg_rate = AG_RATE_INDEX;
-+ t.txpriv.use_bg_rate |= 0x80;
-+ }
-+ if (t.txpriv.use_bg_rate){
-+ hw_priv->connet_time[priv->if_id] = jiffies;
-+ }
-+ } else if (ieee80211_is_deauth(frame->frame_control) ||
-+ ieee80211_is_disassoc(frame->frame_control)) {
-+ hw_priv->connet_time[priv->if_id] = 0;
-+ }
-+
-+#ifdef AP_HT_COMPAT_FIX
-+ if (ieee80211_is_assoc_req(frame->frame_control) &&
-+ priv->if_id == 0 && !(priv->ht_compat_det & 0x10)) {
-+ xradio_remove_ht_ie(priv, skb);
-+ }
-+#endif
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ xradio_frame_monitor(hw_priv,skb,true);
-+#endif
-+
-+ if (ieee80211_is_action(frame->frame_control) &&
-+ mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
-+ u8 *action = (u8*)&mgmt->u.action.category;
-+ xradio_check_go_neg_conf_success(hw_priv, action);
-+ xradio_check_prov_desc_req(hw_priv, action);
-+ }
-+
-+ t.txpriv.if_id = priv->if_id;
-+ t.hdrlen = ieee80211_hdrlen(t.hdr->frame_control);
-+ t.da = ieee80211_get_DA(t.hdr);
-+ t.sta_priv =
-+ (struct xradio_sta_priv *)&control->sta->drv_priv;
-+
-+ if (WARN_ON(t.queue >= 4)) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ //spin_lock_bh(&hw_priv->tx_queue[t.queue].lock);
-+ //if ((priv->if_id == 0) &&
-+ // (hw_priv->tx_queue[t.queue].num_queued_vif[0] >=
-+ // hw_priv->vif0_throttle)) {
-+ // spin_unlock_bh(&hw_priv->tx_queue[t.queue].lock);
-+ //
-+ // ret = __LINE__;
-+ // goto drop;
-+ //} else if ((priv->if_id == 1) &&
-+ // (hw_priv->tx_queue[t.queue].num_queued_vif[1] >=
-+ // hw_priv->vif1_throttle)) {
-+ // spin_unlock_bh(&hw_priv->tx_queue[t.queue].lock);
-+ //
-+ // ret = __LINE__;
-+ // goto drop;
-+ //}
-+ //spin_unlock_bh(&hw_priv->tx_queue[t.queue].lock);
-+
-+ ret = xradio_tx_h_calc_link_ids(priv, control, &t);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ dev_dbg(hw_priv->pdev, "vif %d: tx, %d bytes queue %d, link_id %d(%d).\n",
-+ priv->if_id, skb->len, t.queue, t.txpriv.link_id, t.txpriv.raw_link_id);
-+ if(ieee80211_is_assoc_resp(frame->frame_control)){
-+ dev_dbg(hw_priv->pdev, "vif %d: association response\n", priv->if_id);
-+ }
-+
-+ xradio_tx_h_pm(priv, &t);
-+ xradio_tx_h_calc_tid(priv, &t);
-+ ret = xradio_tx_h_crypt(priv, &t);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+ ret = xradio_tx_h_align(priv, &t, &flags);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+ ret = xradio_tx_h_action(priv, &t);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+ wsm = xradio_tx_h_wsm(priv, &t);
-+ if (!wsm) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ wsm->flags |= flags;
-+ xradio_tx_h_bt(priv, &t, wsm);
-+ ret = xradio_tx_h_rate_policy(hw_priv, &t, wsm);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ ret = xradio_tx_h_skb_pad(hw_priv, wsm, skb);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ rcu_read_lock();
-+ sta = rcu_dereference(control->sta);
-+
-+ xradio_tx_h_ba_stat(priv, &t);
-+ spin_lock_bh(&priv->ps_state_lock);
-+ {
-+ tid_update = xradio_tx_h_pm_state(priv, &t);
-+ BUG_ON(xradio_queue_put(&hw_priv->tx_queue[t.queue],
-+ t.skb, &t.txpriv));
-+#ifdef ROC_DEBUG
-+ txrx_printk(XRADIO_DBG_ERROR, "QPUT %x, %pM, if_id - %d\n",
-+ t.hdr->frame_control, t.da, priv->if_id);
-+#endif
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ if (tid_update && sta)
-+ ieee80211_sta_set_buffered(sta,
-+ t.txpriv.tid, true);
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+
-+ rcu_read_unlock();
-+
-+ xradio_bh_wakeup(hw_priv);
-+
-+ return;
-+
-+drop:
-+ dev_dbg(hw_priv->pdev, "dropped tx at line %d, fctl=0x%04x.\n", ret, frame->frame_control);
-+ xradio_skb_dtor(hw_priv, skb, &t.txpriv);
-+ return;
-+}
-+
-+void xradio_tx_confirm_cb(struct xradio_common *hw_priv,
-+ struct wsm_tx_confirm *arg)
-+{
-+ u8 queue_id = xradio_queue_get_queue_id(arg->packetID);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queue_id];
-+ struct sk_buff *skb;
-+ const struct xradio_txpriv *txpriv;
-+ struct xradio_vif *priv;
-+ u32 feedback_retry = 0;
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, arg->if_id);
-+ if (unlikely(!priv))
-+ return;
-+
-+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
-+ /* STA is stopped. */
-+ spin_unlock(&priv->vif_lock);
-+ return;
-+ }
-+
-+ if (WARN_ON(queue_id >= 4)) {
-+ spin_unlock(&priv->vif_lock);
-+ return;
-+ }
-+
-+ dev_dbg(hw_priv->pdev, "vif %d: tx confirm status=%d, retry=%d, lastRate=%d\n",
-+ priv->if_id, arg->status, arg->ackFailures, arg->txedRate);
-+
-+ if ((arg->status == WSM_REQUEUE) &&
-+ (arg->flags & WSM_TX_STATUS_REQUEUE)) {
-+ /* "Requeue" means "implicit suspend" */
-+ struct wsm_suspend_resume suspend = {
-+ .link_id = arg->link_id,
-+ .stop = 1,
-+ .multicast = !arg->link_id,
-+ .if_id = arg->if_id,
-+ };
-+ xradio_suspend_resume(priv, &suspend);
-+ txrx_printk(XRADIO_DBG_WARN, "Requeue for link_id %d (try %d)."
-+ " STAs asleep: 0x%.8X\n",
-+ arg->link_id,
-+ xradio_queue_get_generation(arg->packetID) + 1,
-+ priv->sta_asleep_mask);
-+
-+ WARN_ON(xradio_queue_requeue(queue,
-+ arg->packetID, true));
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ if (!arg->link_id) {
-+ priv->buffered_multicasts = true;
-+ if (priv->sta_asleep_mask) {
-+ queue_work(hw_priv->workqueue,
-+ &priv->multicast_start_work);
-+ }
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ spin_unlock(&priv->vif_lock);
-+ } else if (!WARN_ON(xradio_queue_get_skb(
-+ queue, arg->packetID, &skb, &txpriv))) {
-+ struct ieee80211_tx_info *tx = IEEE80211_SKB_CB(skb);
-+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)&skb->data[txpriv->offset];
-+ int tx_count = arg->ackFailures;
-+ u8 ht_flags = 0;
-+ int i;
-+
-+ //yangfh add to reset if_0 in firmware when STA-unjoined,
-+ //fix the errors when switch APs in combo mode.
-+ if (unlikely(ieee80211_is_disassoc(frame->frame_control) ||
-+ ieee80211_is_deauth(frame->frame_control))) {
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ wms_send_deauth_to_self(hw_priv, priv);
-+ /* Shedule unjoin work */
-+ txrx_printk(XRADIO_DBG_WARN, "Issue unjoin command(TX) by self.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->unjoin_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+
-+ if (priv->association_mode.greenfieldMode)
-+ ht_flags |= IEEE80211_TX_RC_GREEN_FIELD;
-+
-+ //bss loss confirm.
-+ if (unlikely(priv->bss_loss_status == XRADIO_BSS_LOSS_CONFIRMING &&
-+ priv->bss_loss_confirm_id == arg->packetID)) {
-+ spin_lock(&priv->bss_loss_lock);
-+ priv->bss_loss_status = arg->status?
-+ XRADIO_BSS_LOSS_CONFIRMED : XRADIO_BSS_LOSS_NONE;
-+ spin_unlock(&priv->bss_loss_lock);
-+ }
-+
-+ if (likely(!arg->status)) {
-+ tx->flags |= IEEE80211_TX_STAT_ACK;
-+ priv->cqm_tx_failure_count = 0;
-+ ++tx_count;
-+
-+ if (arg->flags & WSM_TX_STATUS_AGGREGATION) {
-+ /* Do not report aggregation to mac80211:
-+ * it confuses minstrel a lot. */
-+ /* tx->flags |= IEEE80211_TX_STAT_AMPDU; */
-+ }
-+ } else {
-+ /* TODO: Update TX failure counters */
-+ if (unlikely(priv->cqm_tx_failure_thold &&
-+ (++priv->cqm_tx_failure_count >
-+ priv->cqm_tx_failure_thold))) {
-+ priv->cqm_tx_failure_thold = 0;
-+ queue_work(hw_priv->workqueue,
-+ &priv->tx_failure_work);
-+ }
-+ if (tx_count)
-+ ++tx_count;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+
-+ tx->status.ampdu_len = 1;
-+ tx->status.ampdu_ack_len = 1;
-+
-+ txrx_printk(XRADIO_DBG_NIY,"feedback:%08x, %08x, %08x.\n",
-+ arg->rate_try[2], arg->rate_try[1], arg->rate_try[0]);
-+ if(txpriv->use_bg_rate) { //bg rates
-+ tx->status.rates[0].count = arg->ackFailures+1;
-+ tx->status.rates[0].idx = 0;
-+ tx->status.rates[1].idx = -1;
-+ tx->status.rates[2].idx = -1;
-+ tx->status.rates[3].idx = -1;
-+ } else {
-+ int j;
-+ s8 txed_idx;
-+ register u8 rate_num=0, shift=0, retries=0;
-+ u8 flag = tx->status.rates[0].flags;
-+
-+ //get retry rate idx.
-+ for(i=2; i>=0;i--) {
-+ if(arg->rate_try[i]) {
-+ for(j=7; j>=0;j--) {
-+ shift = j<<2;
-+ retries = (arg->rate_try[i]>>shift)&0xf;
-+ if(retries) {
-+ feedback_retry += retries;
-+ txed_idx = xradio_get_rate_idx(hw_priv,flag,((i<<3)+j));
-+ txrx_printk(XRADIO_DBG_NIY, "rate_num=%d, hw=%d, idx=%d, "
-+ "retries=%d, flag=%d", rate_num, ((i<<3)+j),
-+ txed_idx, retries, flag);
-+ if(likely(txed_idx>=0)) {
-+ tx->status.rates[rate_num].idx = txed_idx;
-+ tx->status.rates[rate_num].count = retries;
-+ if (tx->status.rates[rate_num].flags & IEEE80211_TX_RC_MCS)
-+ tx->status.rates[rate_num].flags |= ht_flags;
-+ rate_num++;
-+ if(rate_num>=IEEE80211_TX_MAX_RATES) {
-+ i = -1;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+ //clear other rate.
-+ for (i=rate_num; i < IEEE80211_TX_MAX_RATES; ++i) {
-+ tx->status.rates[i].count = 0;
-+ tx->status.rates[i].idx = -1;
-+ }
-+ //get successful rate idx.
-+ if(!arg->status) {
-+ txed_idx = xradio_get_rate_idx(hw_priv, flag, arg->txedRate);
-+ if(rate_num == 0) {
-+ tx->status.rates[0].idx = txed_idx;
-+ tx->status.rates[0].count = 1;
-+ } else if(rate_num <= IEEE80211_TX_MAX_RATES){
-+ --rate_num;
-+ if(txed_idx == tx->status.rates[rate_num].idx) {
-+ tx->status.rates[rate_num].count += 1;
-+ } else if(rate_num<(IEEE80211_TX_MAX_RATES-1)){
-+ ++rate_num;
-+ tx->status.rates[rate_num].idx = txed_idx;
-+ tx->status.rates[rate_num].count = 1;
-+ } else if(txed_idx >=0) {
-+ tx->status.rates[rate_num].idx = txed_idx;
-+ tx->status.rates[rate_num].count = 1;
-+ }
-+ }
-+ }
-+ }
-+
-+ dev_dbg(hw_priv->pdev, "[TX policy] Ack: " \
-+ "%d:%d, %d:%d, %d:%d, %d:%d\n",
-+ tx->status.rates[0].idx, tx->status.rates[0].count,
-+ tx->status.rates[1].idx, tx->status.rates[1].count,
-+ tx->status.rates[2].idx, tx->status.rates[2].count,
-+ tx->status.rates[3].idx, tx->status.rates[3].count);
-+
-+
-+ xradio_queue_remove(queue, arg->packetID);
-+ }
-+}
-+
-+static void xradio_notify_buffered_tx(struct xradio_vif *priv,
-+ struct sk_buff *skb, int link_id, int tid)
-+{
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ struct ieee80211_sta *sta;
-+ struct ieee80211_hdr *hdr;
-+ u8 *buffered;
-+ u8 still_buffered = 0;
-+
-+
-+ if (link_id && tid < XRADIO_MAX_TID) {
-+ buffered = priv->link_id_db
-+ [link_id - 1].buffered;
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ if (!WARN_ON(!buffered[tid]))
-+ still_buffered = --buffered[tid];
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+ if (!still_buffered && tid < XRADIO_MAX_TID) {
-+ hdr = (struct ieee80211_hdr *) skb->data;
-+ rcu_read_lock();
-+ sta = ieee80211_find_sta(priv->vif, hdr->addr1);
-+ if (sta)
-+ ieee80211_sta_set_buffered(sta, tid, false);
-+ rcu_read_unlock();
-+ }
-+ }
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+}
-+
-+void xradio_skb_dtor(struct xradio_common *hw_priv,
-+ struct sk_buff *skb,
-+ const struct xradio_txpriv *txpriv)
-+{
-+ struct xradio_vif *priv =
-+ __xrwl_hwpriv_to_vifpriv(hw_priv, txpriv->if_id);
-+
-+
-+ skb_pull(skb, txpriv->offset);
-+ if (priv && txpriv->rate_id != XRADIO_INVALID_RATE_ID) {
-+ xradio_notify_buffered_tx(priv, skb,
-+ txpriv->raw_link_id, txpriv->tid);
-+ tx_policy_put(hw_priv, txpriv->rate_id);
-+ }
-+ ieee80211_tx_status(hw_priv->hw, skb);
-+}
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+/* Workaround for WFD test case 6.1.10 */
-+void xradio_link_id_reset(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, linkid_reset_work);
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+ int temp_linkid;
-+
-+
-+ if (!priv->action_linkid) {
-+ /* In GO mode we can receive ACTION frames without a linkID */
-+ temp_linkid = xradio_alloc_link_id(priv,
-+ &priv->action_frame_sa[0]);
-+ WARN_ON(!temp_linkid);
-+ if (temp_linkid) {
-+ /* Make sure we execute the WQ */
-+ flush_workqueue(hw_priv->workqueue);
-+ /* Release the link ID */
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->link_id_db[temp_linkid - 1].prev_status =
-+ priv->link_id_db[temp_linkid - 1].status;
-+ priv->link_id_db[temp_linkid - 1].status =
-+ XRADIO_LINK_RESET;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue,
-+ &priv->link_id_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ } else {
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->link_id_db[priv->action_linkid - 1].prev_status =
-+ priv->link_id_db[priv->action_linkid - 1].status;
-+ priv->link_id_db[priv->action_linkid - 1].status =
-+ XRADIO_LINK_RESET_REMAP;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->link_id_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ flush_workqueue(hw_priv->workqueue);
-+ }
-+}
-+#endif
-diff --git a/drivers/net/wireless/xradio/tx.h b/drivers/net/wireless/xradio/tx.h
-new file mode 100644
-index 0000000..e08bb71
---- /dev/null
-+++ b/drivers/net/wireless/xradio/tx.h
-@@ -0,0 +1,86 @@
-+/*
-+ * txrx interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_TXRX_H
-+#define XRADIO_TXRX_H
-+
-+#include
-+
-+/* extern */ struct ieee80211_hw;
-+/* extern */ struct sk_buff;
-+/* extern */ struct wsm_tx;
-+/* extern */ struct wsm_rx;
-+/* extern */ struct wsm_tx_confirm;
-+/* extern */ struct xradio_txpriv;
-+/* extern */ struct xradio_vif;
-+
-+struct tx_policy {
-+ union {
-+ __le32 tbl[3];
-+ u8 raw[12];
-+ };
-+ u8 defined; /* TODO: u32 or u8, profile and select best */
-+ u8 usage_count; /* --// -- */
-+ u8 retry_count; /* --// -- */
-+ u8 uploaded;
-+};
-+
-+struct tx_policy_cache_entry {
-+ struct tx_policy policy;
-+ struct list_head link;
-+};
-+
-+#define TX_POLICY_CACHE_SIZE (8)
-+struct tx_policy_cache {
-+ struct tx_policy_cache_entry cache[TX_POLICY_CACHE_SIZE];
-+ struct list_head used;
-+ struct list_head free;
-+ spinlock_t lock;
-+};
-+
-+/* ******************************************************************** */
-+/* TX policy cache */
-+/* Intention of TX policy cache is an overcomplicated WSM API.
-+ * Device does not accept per-PDU tx retry sequence.
-+ * It uses "tx retry policy id" instead, so driver code has to sync
-+ * linux tx retry sequences with a retry policy table in the device.
-+ */
-+void tx_policy_init(struct xradio_common *hw_priv);
-+void tx_policy_upload_work(struct work_struct *work);
-+
-+/* ******************************************************************** */
-+/* TX implementation */
-+
-+u32 xradio_rate_mask_to_wsm(struct xradio_common *hw_priv,
-+ u32 rates);
-+void xradio_tx(struct ieee80211_hw *dev, struct ieee80211_tx_control *control, struct sk_buff *skb);
-+void xradio_skb_dtor(struct xradio_common *hw_priv,
-+ struct sk_buff *skb,
-+ const struct xradio_txpriv *txpriv);
-+
-+/* ******************************************************************** */
-+/* WSM callbacks */
-+
-+void xradio_tx_confirm_cb(struct xradio_common *hw_priv,
-+ struct wsm_tx_confirm *arg);
-+
-+/* ******************************************************************** */
-+/* Timeout */
-+
-+void xradio_tx_timeout(struct work_struct *work);
-+
-+/* ******************************************************************** */
-+/* Workaround for WFD test case 6.1.10 */
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+void xradio_link_id_reset(struct work_struct *work);
-+#endif
-+
-+#endif /* XRADIO_TXRX_H */
-diff --git a/drivers/net/wireless/xradio/wsm.c b/drivers/net/wireless/xradio/wsm.c
-new file mode 100644
-index 0000000..3842116
---- /dev/null
-+++ b/drivers/net/wireless/xradio/wsm.c
-@@ -0,0 +1,3004 @@
-+/*
-+ * WSM host interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "wsm.h"
-+#include "bh.h"
-+#include "ap.h"
-+#include "sta.h"
-+#include "rx.h"
-+
-+#define WSM_CMD_TIMEOUT (2 * HZ) /* With respect to interrupt loss */
-+#define WSM_CMD_JOIN_TIMEOUT (7 * HZ) /* Join timeout is 5 sec. in FW */
-+#define WSM_CMD_START_TIMEOUT (7 * HZ)
-+#define WSM_CMD_RESET_TIMEOUT (3 * HZ) /* 2 sec. timeout was observed. */
-+#define WSM_CMD_DEFAULT_TIMEOUT (3 * HZ)
-+#define WSM_SKIP(buf, size) \
-+ do { \
-+ if (unlikely((buf)->data + size > (buf)->end)) \
-+ goto underflow; \
-+ (buf)->data += size; \
-+ } while (0)
-+
-+#define WSM_GET(buf, ptr, size) \
-+ do { \
-+ if (unlikely((buf)->data + size > (buf)->end)) \
-+ goto underflow; \
-+ memcpy(ptr, (buf)->data, size); \
-+ (buf)->data += size; \
-+ } while (0)
-+
-+#define __WSM_GET(buf, type, cvt) \
-+ ({ \
-+ type val; \
-+ if (unlikely((buf)->data + sizeof(type) > (buf)->end)) \
-+ goto underflow; \
-+ val = cvt(*(type *)(buf)->data); \
-+ (buf)->data += sizeof(type); \
-+ val; \
-+ })
-+
-+#define WSM_GET8(buf) __WSM_GET(buf, u8, (u8))
-+#define WSM_GET16(buf) __WSM_GET(buf, u16, __le16_to_cpu)
-+#define WSM_GET32(buf) __WSM_GET(buf, u32, __le32_to_cpu)
-+
-+#define WSM_PUT(buf, ptr, size) \
-+ do { \
-+ if (unlikely((buf)->data + size > (buf)->end)) \
-+ if (unlikely(wsm_buf_reserve((buf), size))) \
-+ goto nomem; \
-+ memcpy((buf)->data, ptr, size); \
-+ (buf)->data += size; \
-+ } while (0)
-+
-+#define __WSM_PUT(buf, val, type, cvt) \
-+ do { \
-+ if (unlikely((buf)->data + sizeof(type) > (buf)->end)) \
-+ if (unlikely(wsm_buf_reserve((buf), sizeof(type)))) \
-+ goto nomem; \
-+ *(type *)(buf)->data = cvt(val); \
-+ (buf)->data += sizeof(type); \
-+ } while (0)
-+
-+#define WSM_PUT8(buf, val) __WSM_PUT(buf, val, u8, (u8))
-+#define WSM_PUT16(buf, val) __WSM_PUT(buf, val, u16, __cpu_to_le16)
-+#define WSM_PUT32(buf, val) __WSM_PUT(buf, val, u32, __cpu_to_le32)
-+
-+static void wsm_buf_reset(struct wsm_buf *buf);
-+static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size);
-+static int get_interface_id_scanning(struct xradio_common *hw_priv);
-+
-+static int wsm_cmd_send(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf,
-+ void *arg, u16 cmd, long tmo, int if_id);
-+
-+static struct xradio_vif
-+ *wsm_get_interface_for_tx(struct xradio_common *hw_priv);
-+
-+static inline void wsm_cmd_lock(struct xradio_common *hw_priv)
-+{
-+ mutex_lock(&hw_priv->wsm_cmd_mux);
-+}
-+
-+static inline void wsm_cmd_unlock(struct xradio_common *hw_priv)
-+{
-+ mutex_unlock(&hw_priv->wsm_cmd_mux);
-+}
-+
-+static inline void wsm_oper_lock(struct xradio_common *hw_priv)
-+{
-+ mutex_lock(&hw_priv->wsm_oper_lock);
-+}
-+
-+static inline void wsm_oper_unlock(struct xradio_common *hw_priv)
-+{
-+ mutex_unlock(&hw_priv->wsm_oper_lock);
-+}
-+
-+/* ******************************************************************** */
-+/* WSM API implementation */
-+
-+static int wsm_generic_confirm(struct xradio_common *hw_priv,
-+ void *arg,
-+ struct wsm_buf *buf)
-+{
-+ u32 status = WSM_GET32(buf);
-+ if (status != WSM_STATUS_SUCCESS)
-+ return -EINVAL;
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+#ifdef XR_RRM//RadioResourceMeasurement
-+static int wsm_start_measure_requset(struct xradio_common *hw_priv,
-+ MEASUREMENT_PARAMETERS *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT(buf, arg, sizeof(*arg));
-+ ret = wsm_cmd_send(hw_priv, buf, arg, 0x000E, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+ nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+
-+}
-+
-+int wsm_11k_measure_requset(struct xradio_common *hw_priv,
-+ u8 measure_type,
-+ u16 ChannelNum,
-+ u16 Duration)
-+{
-+ int ret;
-+ u8 type, sub_type;
-+ MEASUREMENT_PARAMETERS rrm_paras;
-+ LMAC_MEAS_REQUEST *rrm_req = &rrm_paras.MeasurementRequest;
-+// LMAC_MEAS_CHANNEL_LOAD_PARAMS *rrm_req = &rrm_paras.MeasurementRequest;
-+ rrm_paras.TxPowerLevel = 0x11;
-+ rrm_paras.DurationMandatory = 0x22;
-+ rrm_paras.MeasurementRequestLength = 0x33;
-+
-+ type = (measure_type&0xf0)>>4;
-+ sub_type = measure_type&0xf;
-+ rrm_paras.MeasurementType = type;
-+// if (measure_type == ChannelLoadMeasurement) {
-+ if (type == ChannelLoadMeasurement) {
-+ rrm_req->ChannelLoadParams.Reserved = 0;
-+ rrm_req->ChannelLoadParams.ChannelLoadCCA = sub_type;
-+ rrm_req->ChannelLoadParams.ChannelNum = ChannelNum;
-+ //valid when channelload measure, interval bettween request&start
-+ rrm_req->ChannelLoadParams.RandomInterval = 0;
-+ //unit:1TU=1024us
-+ rrm_req->ChannelLoadParams.MeasurementDuration = Duration;
-+ rrm_req->ChannelLoadParams.MeasurementStartTimel = 0;
-+ rrm_req->ChannelLoadParams.MeasurementStartTimeh = 0;
-+ } else if (type == NoiseHistrogramMeasurement) {
-+ rrm_req->NoisHistogramParams.Reserved = 0;
-+ rrm_req->NoisHistogramParams.IpiRpi = sub_type;
-+ rrm_req->NoisHistogramParams.ChannelNum = ChannelNum;
-+ rrm_req->NoisHistogramParams.RandomInterval = 0;
-+ rrm_req->NoisHistogramParams.MeasurementDuration = Duration;
-+ rrm_req->NoisHistogramParams.MeasurementStartTimel = 0;
-+ rrm_req->NoisHistogramParams.MeasurementStartTimeh = 0;
-+ }
-+ ret = wsm_start_measure_requset(hw_priv, &rrm_paras, 0);
-+
-+ return ret;
-+}
-+
-+
-+#endif//RadioResourceMeasurement
-+int wsm_configuration(struct xradio_common *hw_priv,
-+ struct wsm_configuration *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT32(buf, arg->dot11MaxTransmitMsduLifeTime);
-+ WSM_PUT32(buf, arg->dot11MaxReceiveLifeTime);
-+ WSM_PUT32(buf, arg->dot11RtsThreshold);
-+
-+ /* DPD block. */
-+ WSM_PUT16(buf, arg->dpdData_size + 12);
-+ WSM_PUT16(buf, 1); /* DPD version */
-+ WSM_PUT(buf, arg->dot11StationId, ETH_ALEN);
-+ WSM_PUT16(buf, 5); /* DPD flags */
-+ WSM_PUT(buf, arg->dpdData, arg->dpdData_size);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, arg, 0x0009, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+static int wsm_configuration_confirm(struct xradio_common *hw_priv,
-+ struct wsm_configuration *arg,
-+ struct wsm_buf *buf)
-+{
-+ int i;
-+ int status;
-+
-+ status = WSM_GET32(buf);
-+ if (WARN_ON(status != WSM_STATUS_SUCCESS))
-+ return -EINVAL;
-+
-+ WSM_GET(buf, arg->dot11StationId, ETH_ALEN);
-+ arg->dot11FrequencyBandsSupported = WSM_GET8(buf);
-+ WSM_SKIP(buf, 1);
-+ arg->supportedRateMask = WSM_GET32(buf);
-+ for (i = 0; i < 2; ++i) {
-+ arg->txPowerRange[i].min_power_level = WSM_GET32(buf);
-+ arg->txPowerRange[i].max_power_level = WSM_GET32(buf);
-+ arg->txPowerRange[i].stepping = WSM_GET32(buf);
-+ }
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+void wsm_query_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, query_work);
-+ u8 ret[100] = {0};
-+
-+
-+ *(u32*)&ret[0] = hw_priv->query_packetID;
-+ wsm_read_mib(hw_priv, WSM_MIB_ID_REQ_PKT_STATUS, (void*)&ret[0], sizeof(ret), 4);
-+ if(!ret[4]) {
-+ wsm_printk(XRADIO_DBG_ERROR,"QuerypktID=0x%08x, status=0x%x, retry=%d, flags=0x%x, PktDebug=0x%x\n" \
-+ "pktqueue=0x%x, ext1=%d, ext2=%d, ext3=%d, ext4=0x%x, ext5=0x%x\n",
-+ *(u32*)&ret[0], ret[6], ret[7], *(u32*)&ret[8], *(u32*)&ret[12],
-+ ret[44], ret[45], ret[46], ret[47], ret[48], ret[49]);
-+ wsm_printk(XRADIO_DBG_ERROR,"interdebug=0x%x, 0x%x, 0x%x, Soure=0x%x, 0x%x, 0x%x\n" \
-+ "interuse=%d, external=%d, TxOutstanding=%d, QueueStatus=0x%x, BA0=0x%x, BA1=0x%x\n" \
-+ "ScanStatus=0x%x, scanNULL=0x%x, wr_state=0x%x,0x%x,0x%x,0x%x," \
-+ "wr_cnt=%d, %d, %d, %d\n",
-+ *(u32*)&ret[16], *(u32*)&ret[20], *(u32*)&ret[24], ret[28], ret[29], ret[30],
-+ ret[32], ret[33], ret[34], ret[35], *(u32*)&ret[36], *(u32*)&ret[40],
-+ ret[50], ret[51], ret[52], ret[53], ret[54], ret[55],
-+ *(u16*)&ret[56], *(u16*)&ret[58], *(u16*)&ret[60], *(u16*)&ret[62]);
-+ } else {
-+ ret[5] = 0;
-+ wsm_printk(XRADIO_DBG_ERROR,"No req packid=0x%08x!\n", *(u32*)&ret[0]);
-+ }
-+ //hardware error occurs, try to restart wifi.
-+ if(ret[5] & 0x4) {
-+ wsm_printk(XRADIO_DBG_ERROR,"Hardware need to reset 0x%x.\n", ret[5]);
-+ hw_priv->bh_error = 1;
-+ wake_up(&hw_priv->bh_wq);
-+ }
-+ hw_priv->query_packetID = 0;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_reset(struct xradio_common *hw_priv, const struct wsm_reset *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ u16 cmd = 0x000A | WSM_TX_LINK_ID(arg->link_id);
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT32(buf, arg->reset_statistics ? 0 : 1);
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, cmd, WSM_CMD_RESET_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+struct wsm_mib {
-+ u16 mibId;
-+ void *buf;
-+ size_t buf_size;
-+};
-+
-+int wsm_read_mib(struct xradio_common *hw_priv, u16 mibId, void *_buf,
-+ size_t buf_size, size_t arg_size)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ struct wsm_mib mib_buf = {
-+ .mibId = mibId,
-+ .buf = _buf,
-+ .buf_size = buf_size,
-+ };
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT16(buf, mibId);
-+ WSM_PUT16(buf, arg_size);
-+ WSM_PUT(buf, _buf, arg_size);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, &mib_buf, 0x0005, WSM_CMD_TIMEOUT, -1);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+static int wsm_read_mib_confirm(struct xradio_common *hw_priv,
-+ struct wsm_mib *arg,
-+ struct wsm_buf *buf)
-+{
-+ u16 size;
-+ if (WARN_ON(WSM_GET32(buf) != WSM_STATUS_SUCCESS))
-+ return -EINVAL;
-+
-+ if (WARN_ON(WSM_GET16(buf) != arg->mibId))
-+ return -EINVAL;
-+
-+ size = WSM_GET16(buf);
-+ if (size > arg->buf_size)
-+ size = arg->buf_size;
-+
-+ WSM_GET(buf, arg->buf, size);
-+ arg->buf_size = size;
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_write_mib(struct xradio_common *hw_priv, u16 mibId, void *_buf,
-+ size_t buf_size, int if_id)
-+{
-+ int ret = 0;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ struct wsm_mib mib_buf = {
-+ .mibId = mibId,
-+ .buf = _buf,
-+ .buf_size = buf_size,
-+ };
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT16(buf, mibId);
-+ WSM_PUT16(buf, buf_size);
-+ WSM_PUT(buf, _buf, buf_size);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, &mib_buf, 0x0006, WSM_CMD_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+static int wsm_write_mib_confirm(struct xradio_common *hw_priv,
-+ struct wsm_mib *arg,
-+ struct wsm_buf *buf,
-+ int interface_link_id)
-+{
-+ int ret;
-+ int i;
-+ struct xradio_vif *priv;
-+ ret = wsm_generic_confirm(hw_priv, arg, buf);
-+ if (ret)
-+ return ret;
-+
-+ /*wsm_set_operational_mode confirm.*/
-+ if (arg->mibId == 0x1006) {
-+ const char *p = arg->buf;
-+ bool powersave_enabled = (p[0] & 0x0F) ? true : false;
-+
-+ /* update vif PM status. */
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
-+ if (priv) {
-+ xradio_enable_powersave(priv, powersave_enabled);
-+ spin_unlock(&priv->vif_lock);
-+ }
-+
-+ /* HW powersave base on vif except for generic vif. */
-+ spin_lock(&hw_priv->vif_list_lock);
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ powersave_enabled &= !!priv->powersave_enabled;
-+ }
-+ hw_priv->powersave_enabled = powersave_enabled;
-+ spin_unlock(&hw_priv->vif_list_lock);
-+
-+ }
-+ return 0;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_scan(struct xradio_common *hw_priv, const struct wsm_scan *arg,
-+ int if_id)
-+{
-+ int i;
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ if (unlikely(arg->numOfChannels > 48))
-+ return -EINVAL;
-+
-+ if (unlikely(arg->numOfSSIDs > WSM_SCAN_MAX_NUM_OF_SSIDS))
-+ return -EINVAL;
-+
-+ if (unlikely(arg->band > 1))
-+ return -EINVAL;
-+
-+ wsm_oper_lock(hw_priv);
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->band);
-+ WSM_PUT8(buf, arg->scanType);
-+ WSM_PUT8(buf, arg->scanFlags);
-+ WSM_PUT8(buf, arg->maxTransmitRate);
-+ WSM_PUT32(buf, arg->autoScanInterval);
-+ WSM_PUT8(buf, arg->numOfProbeRequests);
-+ WSM_PUT8(buf, arg->numOfChannels);
-+ WSM_PUT8(buf, arg->numOfSSIDs);
-+ WSM_PUT8(buf, arg->probeDelay);
-+
-+ for (i = 0; i < arg->numOfChannels; ++i) {
-+ WSM_PUT16(buf, arg->ch[i].number);
-+ WSM_PUT16(buf, 0);
-+ WSM_PUT32(buf, arg->ch[i].minChannelTime);
-+ WSM_PUT32(buf, arg->ch[i].maxChannelTime);
-+ WSM_PUT32(buf, 0);
-+ }
-+
-+ for (i = 0; i < arg->numOfSSIDs; ++i) {
-+ WSM_PUT32(buf, arg->ssids[i].length);
-+ WSM_PUT(buf, &arg->ssids[i].ssid[0],
-+ sizeof(arg->ssids[i].ssid));
-+ }
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0007, WSM_CMD_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ if (ret)
-+ wsm_oper_unlock(hw_priv);
-+
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_oper_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_stop_scan(struct xradio_common *hw_priv, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ wsm_cmd_lock(hw_priv);
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0008, WSM_CMD_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+}
-+
-+
-+static int wsm_tx_confirm(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf,
-+ int interface_link_id)
-+{
-+ struct wsm_tx_confirm tx_confirm;
-+
-+ tx_confirm.packetID = WSM_GET32(buf);
-+ tx_confirm.status = WSM_GET32(buf);
-+ tx_confirm.txedRate = WSM_GET8(buf);
-+ tx_confirm.ackFailures = WSM_GET8(buf);
-+ tx_confirm.flags = WSM_GET16(buf);
-+ tx_confirm.rate_try[0] = WSM_GET32(buf);
-+ tx_confirm.rate_try[1] = WSM_GET32(buf);
-+ tx_confirm.rate_try[2] = WSM_GET32(buf);
-+ tx_confirm.mediaDelay = WSM_GET32(buf);
-+ tx_confirm.txQueueDelay = WSM_GET32(buf);
-+
-+ if (is_hardware_xradio(hw_priv)) {
-+ /* TODO:COMBO:linkID will be stored in packetID*/
-+ /* TODO:COMBO: Extract traffic resumption map */
-+ tx_confirm.if_id = xradio_queue_get_if_id(tx_confirm.packetID);
-+ tx_confirm.link_id = xradio_queue_get_link_id(
-+ tx_confirm.packetID);
-+ } else {
-+ tx_confirm.link_id = interface_link_id;
-+ tx_confirm.if_id = 0;
-+ }
-+
-+ wsm_release_vif_tx_buffer(hw_priv, tx_confirm.if_id, 1);
-+
-+ xradio_tx_confirm_cb(hw_priv, &tx_confirm);
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+static int wsm_multi_tx_confirm(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf, int interface_link_id)
-+{
-+ struct xradio_vif *priv;
-+ int ret;
-+ int count;
-+ int i;
-+
-+ count = WSM_GET32(buf);
-+ if (WARN_ON(count <= 0))
-+ return -EINVAL;
-+ else if (count > 1) {
-+ ret = wsm_release_tx_buffer(hw_priv, count - 1);
-+ if (ret < 0)
-+ return ret;
-+ else if (ret > 0)
-+ xradio_bh_wakeup(hw_priv);
-+ }
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
-+ if (priv) {
-+ spin_unlock(&priv->vif_lock);
-+ }
-+ for (i = 0; i < count; ++i) {
-+ ret = wsm_tx_confirm(hw_priv, buf, interface_link_id);
-+ if (ret)
-+ return ret;
-+ }
-+ return ret;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+/* ******************************************************************** */
-+
-+static int wsm_join_confirm(struct xradio_common *hw_priv,
-+ struct wsm_join *arg,
-+ struct wsm_buf *buf)
-+{
-+ if (WSM_GET32(buf) != WSM_STATUS_SUCCESS)
-+ return -EINVAL;
-+ arg->minPowerLevel = WSM_GET32(buf);
-+ arg->maxPowerLevel = WSM_GET32(buf);
-+
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+int wsm_join(struct xradio_common *hw_priv, struct wsm_join *arg,
-+ int if_id)
-+/*TODO: combo: make it work per vif.*/
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_oper_lock(hw_priv);
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->mode);
-+ WSM_PUT8(buf, arg->band);
-+ WSM_PUT16(buf, arg->channelNumber);
-+ WSM_PUT(buf, &arg->bssid[0], sizeof(arg->bssid));
-+ WSM_PUT16(buf, arg->atimWindow);
-+ WSM_PUT8(buf, arg->preambleType);
-+ WSM_PUT8(buf, arg->probeForJoin);
-+ WSM_PUT8(buf, arg->dtimPeriod);
-+ WSM_PUT8(buf, arg->flags);
-+ WSM_PUT32(buf, arg->ssidLength);
-+ WSM_PUT(buf, &arg->ssid[0], sizeof(arg->ssid));
-+ WSM_PUT32(buf, arg->beaconInterval);
-+ WSM_PUT32(buf, arg->basicRateSet);
-+
-+ hw_priv->tx_burst_idx = -1;
-+ ret = wsm_cmd_send(hw_priv, buf, arg, 0x000B, WSM_CMD_JOIN_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_oper_unlock(hw_priv); /*confirm, not indcation.*/
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_oper_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_set_bss_params(struct xradio_common *hw_priv,
-+ const struct wsm_set_bss_params *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT8(buf, arg->beaconLostCount);
-+ WSM_PUT16(buf, arg->aid);
-+ WSM_PUT32(buf, arg->operationalRateSet);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0011, WSM_CMD_TIMEOUT,
-+ if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_add_key(struct xradio_common *hw_priv, const struct wsm_add_key *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT(buf, arg, sizeof(*arg));
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x000C, WSM_CMD_TIMEOUT,
-+ if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_remove_key(struct xradio_common *hw_priv,
-+ const struct wsm_remove_key *arg, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->entryIndex);
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT16(buf, 0);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x000D, WSM_CMD_TIMEOUT,
-+ if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_set_tx_queue_params(struct xradio_common *hw_priv,
-+ const struct wsm_set_tx_queue_params *arg,
-+ u8 id, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ u8 queue_id_to_wmm_aci[] = {3, 2, 0, 1};
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, queue_id_to_wmm_aci[id]);
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT8(buf, arg->ackPolicy);
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT32(buf, arg->maxTransmitLifetime);
-+ WSM_PUT16(buf, arg->allowedMediumTime);
-+ WSM_PUT16(buf, 0);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0012, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_set_edca_params(struct xradio_common *hw_priv,
-+ const struct wsm_edca_params *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ /* Implemented according to specification. */
-+
-+ WSM_PUT16(buf, arg->params[3].cwMin);
-+ WSM_PUT16(buf, arg->params[2].cwMin);
-+ WSM_PUT16(buf, arg->params[1].cwMin);
-+ WSM_PUT16(buf, arg->params[0].cwMin);
-+
-+ WSM_PUT16(buf, arg->params[3].cwMax);
-+ WSM_PUT16(buf, arg->params[2].cwMax);
-+ WSM_PUT16(buf, arg->params[1].cwMax);
-+ WSM_PUT16(buf, arg->params[0].cwMax);
-+
-+ WSM_PUT8(buf, arg->params[3].aifns);
-+ WSM_PUT8(buf, arg->params[2].aifns);
-+ WSM_PUT8(buf, arg->params[1].aifns);
-+ WSM_PUT8(buf, arg->params[0].aifns);
-+
-+ WSM_PUT16(buf, arg->params[3].txOpLimit);
-+ WSM_PUT16(buf, arg->params[2].txOpLimit);
-+ WSM_PUT16(buf, arg->params[1].txOpLimit);
-+ WSM_PUT16(buf, arg->params[0].txOpLimit);
-+
-+ WSM_PUT32(buf, arg->params[3].maxReceiveLifetime);
-+ WSM_PUT32(buf, arg->params[2].maxReceiveLifetime);
-+ WSM_PUT32(buf, arg->params[1].maxReceiveLifetime);
-+ WSM_PUT32(buf, arg->params[0].maxReceiveLifetime);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0013, WSM_CMD_TIMEOUT, if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_switch_channel(struct xradio_common *hw_priv,
-+ const struct wsm_switch_channel *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_lock_tx(hw_priv);
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->channelMode);
-+ WSM_PUT8(buf, arg->channelSwitchCount);
-+ WSM_PUT16(buf, arg->newChannelNumber);
-+
-+ hw_priv->channel_switch_in_progress = 1;
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0016, WSM_CMD_TIMEOUT, if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ if (ret) {
-+ wsm_unlock_tx(hw_priv);
-+ hw_priv->channel_switch_in_progress = 0;
-+ }
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_unlock_tx(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_set_pm(struct xradio_common *hw_priv, const struct wsm_set_pm *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_oper_lock(hw_priv);
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->pmMode);
-+ WSM_PUT8(buf, arg->fastPsmIdlePeriod);
-+ WSM_PUT8(buf, arg->apPsmChangePeriod);
-+ WSM_PUT8(buf, arg->minAutoPsPollPeriod);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0010, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ if (ret)
-+ wsm_oper_unlock(hw_priv);
-+
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_oper_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_start(struct xradio_common *hw_priv, const struct wsm_start *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->mode);
-+ WSM_PUT8(buf, arg->band);
-+ WSM_PUT16(buf, arg->channelNumber);
-+ WSM_PUT32(buf, arg->CTWindow);
-+ WSM_PUT32(buf, arg->beaconInterval);
-+ WSM_PUT8(buf, arg->DTIMPeriod);
-+ WSM_PUT8(buf, arg->preambleType);
-+ WSM_PUT8(buf, arg->probeDelay);
-+ WSM_PUT8(buf, arg->ssidLength);
-+ WSM_PUT(buf, arg->ssid, sizeof(arg->ssid));
-+ WSM_PUT32(buf, arg->basicRateSet);
-+
-+ hw_priv->tx_burst_idx = -1;
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0017, WSM_CMD_START_TIMEOUT,
-+ if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+#if 0
-+/* This API is no longer present in WSC */
-+/* ******************************************************************** */
-+
-+int wsm_beacon_transmit(struct xradio_common *hw_priv,
-+ const struct wsm_beacon_transmit *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT32(buf, arg->enableBeaconing ? 1 : 0);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0018, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+#endif
-+
-+/* ******************************************************************** */
-+
-+int wsm_start_find(struct xradio_common *hw_priv, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0019, WSM_CMD_TIMEOUT, if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_stop_find(struct xradio_common *hw_priv, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x001A, WSM_CMD_TIMEOUT, if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_map_link(struct xradio_common *hw_priv, const struct wsm_map_link *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ u16 cmd = 0x001C;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT(buf, &arg->mac_addr[0], sizeof(arg->mac_addr));
-+
-+ if (is_hardware_xradio(hw_priv)) {
-+ WSM_PUT8(buf, arg->unmap);
-+ WSM_PUT8(buf, arg->link_id);
-+ } else {
-+ cmd |= WSM_TX_LINK_ID(arg->link_id);
-+ WSM_PUT16(buf, 0);
-+ }
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, cmd, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_update_ie(struct xradio_common *hw_priv,
-+ const struct wsm_update_ie *arg, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT16(buf, arg->what);
-+ WSM_PUT16(buf, arg->count);
-+ WSM_PUT(buf, arg->ies, arg->length);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x001B, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+
-+}
-+/* ******************************************************************** */
-+#ifdef MCAST_FWDING
-+/* 3.66 */
-+static int wsm_give_buffer_confirm(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ wsm_printk(XRADIO_DBG_MSG, "HW Buf count %d\n", hw_priv->hw_bufs_used);
-+ if (!hw_priv->hw_bufs_used)
-+ wake_up(&hw_priv->bh_evt_wq);
-+
-+ return 0;
-+}
-+
-+/* 3.65 */
-+int wsm_init_release_buffer_request(struct xradio_common *hw_priv, u8 index)
-+{
-+ struct wsm_buf *buf = &hw_priv->wsm_release_buf[index];
-+ u16 cmd = 0x0022; /* Buffer Request */
-+ u8 flags;
-+ size_t buf_len;
-+
-+ wsm_buf_init(buf);
-+
-+ flags = index ? 0: 0x1;
-+
-+ WSM_PUT8(buf, flags);
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT16(buf, 0);
-+
-+ buf_len = buf->data - buf->begin;
-+
-+ /* Fill HI message header */
-+ ((__le16 *)buf->begin)[0] = __cpu_to_le16(buf_len);
-+ ((__le16 *)buf->begin)[1] = __cpu_to_le16(cmd);
-+
-+ return 0;
-+nomem:
-+ return -ENOMEM;
-+}
-+
-+/* 3.65 fixed memory leakage by yangfh*/
-+int wsm_deinit_release_buffer(struct xradio_common *hw_priv)
-+{
-+ struct wsm_buf *buf = NULL;
-+ int i, err = 0;
-+
-+ for (i = 0; i < WSM_MAX_BUF; i++) {
-+ buf = &hw_priv->wsm_release_buf[i];
-+ if(likely(buf)) {
-+ if(likely(buf->begin))
-+ kfree(buf->begin);
-+ buf->begin = buf->data = buf->end = NULL;
-+ } else {
-+ err++;
-+ }
-+ }
-+ if(err) wsm_printk(XRADIO_DBG_ERROR, "%s, NULL buf=%d!\n", __func__, err);
-+ return 0;
-+}
-+
-+/* 3.68 */
-+static int wsm_request_buffer_confirm(struct xradio_vif *priv,
-+ u8 *arg,
-+ struct wsm_buf *buf)
-+{
-+ u8 count;
-+ u32 sta_asleep_mask = 0;
-+ int i;
-+ u32 mask = 0;
-+ u32 change_mask = 0;
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+ /* There is no status field in this message */
-+ sta_asleep_mask = WSM_GET32(buf);
-+ count = WSM_GET8(buf);
-+ count -= 1; /* Current workaround for FW issue */
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ change_mask = (priv->sta_asleep_mask ^ sta_asleep_mask);
-+ wsm_printk(XRADIO_DBG_MSG, "CM %x, HM %x, FWM %x\n", change_mask,priv->sta_asleep_mask, sta_asleep_mask);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+ if (change_mask) {
-+ struct ieee80211_sta *sta;
-+ int ret = 0;
-+
-+
-+ for (i = 0; i < MAX_STA_IN_AP_MODE ; ++i) {
-+
-+ if(XRADIO_LINK_HARD != priv->link_id_db[i].status)
-+ continue;
-+
-+ mask = BIT(i + 1);
-+
-+ /* If FW state and host state for this link are different then notify OMAC */
-+ if(change_mask & mask) {
-+ wsm_printk(XRADIO_DBG_MSG, "PS State Changed %d for sta %pM\n", (sta_asleep_mask & mask) ? 1:0, priv->link_id_db[i].mac);
-+ rcu_read_lock();
-+ sta = ieee80211_find_sta(priv->vif, priv->link_id_db[i].mac);
-+ if (!sta) {
-+ wsm_printk(XRADIO_DBG_MSG, "WRBC - could not find sta %pM\n",
-+ priv->link_id_db[i].mac);
-+ } else {
-+ ret = ieee80211_sta_ps_transition_ni(sta, (sta_asleep_mask & mask) ? true: false);
-+ wsm_printk(XRADIO_DBG_MSG, "PS State NOTIFIED %d\n", ret);
-+ WARN_ON(ret);
-+ }
-+ rcu_read_unlock();
-+ }
-+ }
-+ /* Replace STA mask with one reported by FW */
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->sta_asleep_mask = sta_asleep_mask;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ }
-+
-+ wsm_printk(XRADIO_DBG_MSG, "WRBC - HW Buf count %d SleepMask %d\n",
-+ hw_priv->hw_bufs_used, sta_asleep_mask);
-+ hw_priv->buf_released = 0;
-+ WARN_ON(count != (hw_priv->wsm_caps.numInpChBufs - 1));
-+
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+/* 3.67 */
-+int wsm_request_buffer_request(struct xradio_vif *priv,
-+ u8 *arg)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &priv->hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(priv->hw_priv);
-+
-+ WSM_PUT8(buf, (*arg));
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT16(buf, 0);
-+
-+ ret = wsm_cmd_send(priv->hw_priv, buf, arg, 0x0023, WSM_CMD_JOIN_TIMEOUT,priv->if_id);
-+
-+ wsm_cmd_unlock(priv->hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(priv->hw_priv);
-+ return -ENOMEM;
-+}
-+
-+#endif
-+
-+int wsm_set_keepalive_filter(struct xradio_vif *priv, bool enable)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ priv->rx_filter.keepalive = enable;
-+ return wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
-+}
-+
-+int wsm_set_probe_responder(struct xradio_vif *priv, bool enable)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ priv->rx_filter.probeResponder = enable;
-+ return wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
-+}
-+/* ******************************************************************** */
-+/* WSM indication events implementation */
-+
-+static int wsm_startup_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ u16 status;
-+ static const char * const fw_types[] = {
-+ "ETF",
-+ "WFM",
-+ "WSM",
-+ "HI test",
-+ "Platform test"
-+ };
-+
-+ hw_priv->wsm_caps.numInpChBufs = WSM_GET16(buf);
-+ hw_priv->wsm_caps.sizeInpChBuf = WSM_GET16(buf);
-+ hw_priv->wsm_caps.hardwareId = WSM_GET16(buf);
-+ hw_priv->wsm_caps.hardwareSubId = WSM_GET16(buf);
-+ status = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareCap = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareType = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareApiVer = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareBuildNumber = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareVersion = WSM_GET16(buf);
-+ WSM_GET(buf, &hw_priv->wsm_caps.fw_label[0], WSM_FW_LABEL);
-+ hw_priv->wsm_caps.fw_label[WSM_FW_LABEL+1] = 0; /* Do not trust FW too much. */
-+
-+ if (WARN_ON(status))
-+ return -EINVAL;
-+
-+ if (WARN_ON(hw_priv->wsm_caps.firmwareType > 4))
-+ return -EINVAL;
-+
-+ dev_info(hw_priv->pdev,
-+ " Input buffers: %d x %d bytes\n"
-+ " Hardware: %d.%d\n"
-+ " %s firmware ver: %d, build: %d,"
-+ " api: %d, cap: 0x%.4X\n",
-+ hw_priv->wsm_caps.numInpChBufs,
-+ hw_priv->wsm_caps.sizeInpChBuf,
-+ hw_priv->wsm_caps.hardwareId,
-+ hw_priv->wsm_caps.hardwareSubId,
-+ fw_types[hw_priv->wsm_caps.firmwareType],
-+ hw_priv->wsm_caps.firmwareVersion,
-+ hw_priv->wsm_caps.firmwareBuildNumber,
-+ hw_priv->wsm_caps.firmwareApiVer,
-+ hw_priv->wsm_caps.firmwareCap);
-+
-+ dev_info(hw_priv->pdev, "Firmware Label:%s\n", &hw_priv->wsm_caps.fw_label[0]);
-+
-+ hw_priv->wsm_caps.firmwareReady = 1;
-+
-+ wake_up(&hw_priv->wsm_startup_done);
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+//add by yangfh 2014-10-31 16:58:53
-+void wms_send_deauth_to_self(struct xradio_common *hw_priv, struct xradio_vif *priv)
-+{
-+ struct sk_buff *skb = NULL;
-+ struct ieee80211_mgmt *deauth = NULL;
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ int i = 0;
-+ wsm_printk(XRADIO_DBG_WARN, "AP mode, send_deauth_to_self\n");
-+ for (i = 0; ilink_id_db[i].status == XRADIO_LINK_HARD) {
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, 64);
-+ deauth = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ if(!deauth) {
-+ WARN_ON(1);
-+ return;
-+ }
-+ deauth->frame_control =
-+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
-+ deauth->duration = 0;
-+ memcpy(deauth->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(deauth->sa, priv->link_id_db[i].mac, ETH_ALEN);
-+ memcpy(deauth->bssid, priv->vif->addr, ETH_ALEN);
-+ deauth->seq_ctrl = 0;
-+ deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+ }
-+ } else if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ wsm_printk(XRADIO_DBG_WARN, "STA mode, send_deauth_to_self\n");
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, 64);
-+ deauth = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ if(!deauth) {
-+ WARN_ON(1);
-+ return;
-+ }
-+ deauth->frame_control =
-+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
-+ deauth->duration = 0;
-+ memcpy(deauth->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(deauth->sa, priv->join_bssid, ETH_ALEN);
-+ memcpy(deauth->bssid, priv->join_bssid, ETH_ALEN);
-+ deauth->seq_ctrl = 0;
-+ deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+}
-+
-+void wms_send_disassoc_to_self(struct xradio_common *hw_priv, struct xradio_vif *priv)
-+{
-+ struct sk_buff *skb = NULL;
-+ struct ieee80211_mgmt *disassoc = NULL;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ int i = 0;
-+ wsm_printk(XRADIO_DBG_WARN, "AP mode, wms_send_disassoc_to_self\n");
-+ for (i = 0; ilink_id_db[i].status == XRADIO_LINK_HARD) {
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, 64);
-+ disassoc = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ if(!disassoc) {
-+ WARN_ON(1);
-+ return;
-+ }
-+ disassoc->frame_control =
-+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC);
-+ disassoc->duration = 0;
-+ memcpy(disassoc->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(disassoc->sa, priv->link_id_db[i].mac, ETH_ALEN);
-+ memcpy(disassoc->bssid, priv->vif->addr, ETH_ALEN);
-+ disassoc->seq_ctrl = 0;
-+ disassoc->u.disassoc.reason_code = WLAN_REASON_DISASSOC_STA_HAS_LEFT;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+ }
-+ } else if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ wsm_printk(XRADIO_DBG_WARN, "STA mode, wms_send_disassoc_to_self\n");
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, 64);
-+ disassoc = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ if(!disassoc) {
-+ WARN_ON(1);
-+ return;
-+ }
-+ disassoc->frame_control =
-+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC);
-+ disassoc->duration = 0;
-+ memcpy(disassoc->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(disassoc->sa, priv->join_bssid, ETH_ALEN);
-+ memcpy(disassoc->bssid, priv->join_bssid, ETH_ALEN);
-+ disassoc->seq_ctrl = 0;
-+ disassoc->u.disassoc.reason_code = WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+}
-+
-+static int wsm_receive_indication(struct xradio_common *hw_priv,
-+ int interface_link_id,
-+ struct wsm_buf *buf,
-+ struct sk_buff **skb_p)
-+{
-+ struct xradio_vif *priv;
-+ struct wsm_rx rx;
-+ struct ieee80211_hdr *hdr;
-+ size_t hdr_len;
-+
-+ hw_priv->rx_timestamp = jiffies;
-+
-+ rx.status = WSM_GET32(buf);
-+ rx.channelNumber = WSM_GET16(buf);
-+ rx.rxedRate = WSM_GET8(buf);
-+ rx.rcpiRssi = WSM_GET8(buf);
-+ rx.flags = WSM_GET32(buf);
-+
-+ /* TODO:COMBO: Frames received from scanning are received
-+ * with interface ID == 2 */
-+ if (is_hardware_xradio(hw_priv)) {
-+ if (interface_link_id == XRWL_GENERIC_IF_ID) {
-+ /* Frames received in response to SCAN
-+ * Request */
-+ interface_link_id =
-+ get_interface_id_scanning(hw_priv);
-+ if (interface_link_id == -1) {
-+ interface_link_id = hw_priv->roc_if_id;
-+ }
-+#ifdef ROAM_OFFLOAD
-+ if (hw_priv->auto_scanning) {
-+ interface_link_id = hw_priv->scan.if_id;
-+ }
-+#endif/*ROAM_OFFLOAD*/
-+ }
-+ /* linkid (peer sta id is encoded in bit 25-28 of
-+ flags field */
-+ rx.link_id = ((rx.flags & (0xf << 25)) >> 25);
-+ rx.if_id = interface_link_id;
-+ } else {
-+ rx.link_id = interface_link_id;
-+ rx.if_id = 0;
-+ }
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, rx.if_id);
-+ if (!priv) {
-+ dev_dbg(hw_priv->pdev, "got frame on a vif we don't have, dropped\n");
-+ return 0;
-+ }
-+ //remove wsm hdr of skb
-+ hdr_len = buf->data - buf->begin;
-+ skb_pull(*skb_p, hdr_len);
-+
-+ /* FW Workaround: Drop probe resp or
-+ beacon when RSSI is 0 */
-+ hdr = (struct ieee80211_hdr *) (*skb_p)->data;
-+
-+ if (!rx.rcpiRssi &&
-+ (ieee80211_is_probe_resp(hdr->frame_control) ||
-+ ieee80211_is_beacon(hdr->frame_control))) {
-+ spin_unlock(&priv->vif_lock);
-+ return 0;
-+ }
-+
-+ /* If no RSSI subscription has been made,
-+ * convert RCPI to RSSI here */
-+ if (!priv->cqm_use_rssi)
-+ rx.rcpiRssi = rx.rcpiRssi / 2 - 110;
-+
-+ if (!rx.status && unlikely(ieee80211_is_deauth(hdr->frame_control))) {
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ /* Shedule unjoin work */
-+ dev_dbg(hw_priv->pdev,
-+ "Issue unjoin command (RX).\n");
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue,
-+ &priv->unjoin_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+ xradio_rx_cb(priv, &rx, skb_p);
-+ if (*skb_p)
-+ skb_push(*skb_p, hdr_len);
-+ spin_unlock(&priv->vif_lock);
-+
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+
-+static int wsm_event_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf,
-+ int interface_link_id)
-+{
-+ int first;
-+ struct xradio_wsm_event *event = NULL;
-+ struct xradio_vif *priv;
-+
-+ if (!is_hardware_xradio(hw_priv))
-+ interface_link_id = 0;
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
-+
-+ if (unlikely(!priv)) {
-+ dev_warn(hw_priv->pdev, "Event: %d(%d) for removed "
-+ "interface, ignoring\n", __le32_to_cpu(WSM_GET32(buf)),
-+ __le32_to_cpu(WSM_GET32(buf)));
-+ return 0;
-+ }
-+
-+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
-+ /* STA is stopped. */
-+ return 0;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+
-+ event = kzalloc(sizeof(struct xradio_wsm_event), GFP_KERNEL);
-+ if (event == NULL) {
-+ dev_err(hw_priv->pdev, "xr_kzalloc failed!");
-+ return -EINVAL;
-+ }
-+
-+ event->evt.eventId = __le32_to_cpu(WSM_GET32(buf));
-+ event->evt.eventData = __le32_to_cpu(WSM_GET32(buf));
-+ event->if_id = interface_link_id;
-+
-+ dev_dbg(hw_priv->pdev, "Event: %d(%d)\n",
-+ event->evt.eventId, event->evt.eventData);
-+
-+ spin_lock(&hw_priv->event_queue_lock);
-+ first = list_empty(&hw_priv->event_queue);
-+ list_add_tail(&event->link, &hw_priv->event_queue);
-+ spin_unlock(&hw_priv->event_queue_lock);
-+
-+ if (first)
-+ queue_work(hw_priv->workqueue, &hw_priv->event_handler);
-+
-+ return 0;
-+
-+underflow:
-+ kfree(event);
-+ return -EINVAL;
-+}
-+
-+#define PRINT_11K_MEASRURE 1
-+static int wsm_measure_cmpl_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ MEASUREMENT_COMPLETE measure_cmpl;
-+ u8 cca_chanload;
-+ u32 buf_len = 0;
-+ u32 *data;
-+
-+ LMAC_MEAS_CHANNEL_LOAD_RESULTS *chanload_res;
-+ LMAC_MEAS_NOISE_HISTOGRAM_RESULTS *noise_res;
-+ WSM_GET(buf, &measure_cmpl, 12);
-+
-+ switch (measure_cmpl.MeasurementType) {
-+ case ChannelLoadMeasurement:
-+ buf_len = sizeof(LMAC_MEAS_CHANNEL_LOAD_RESULTS);
-+ break;
-+ case NoiseHistrogramMeasurement:
-+ buf_len = sizeof(LMAC_MEAS_NOISE_HISTOGRAM_RESULTS);
-+ break;
-+ case BeaconReport:
-+ buf_len = sizeof(LMAC_MEAS_BEACON_RESULTS);
-+ break;
-+ case STAstatisticsReport:
-+ buf_len = sizeof(LMAC_MEAS_STA_STATS_RESULTS);
-+ break;
-+ case LinkMeasurement:
-+ buf_len = sizeof(LMAC_MEAS_LINK_MEASUREMENT_RESULTS);
-+ break;
-+ }
-+ wsm_printk(XRADIO_DBG_ERROR, "[11K]buf_len = %d\n", buf_len);
-+ WSM_GET(buf, &measure_cmpl.MeasurementReport, buf_len);
-+
-+ data = (u32 *)(&measure_cmpl);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[0]=%08x\n", data[0]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[1]=%08x\n", data[1]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[2]=%08x\n", data[2]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[3]=%08x\n", data[3]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[4]=%08x\n", data[4]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[5]=%08x\n", data[5]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[6]=%08x\n", data[6]);
-+ wsm_printk(XRADIO_DBG_ERROR, "[***HL***]MeasurementType=%0d\n", measure_cmpl.MeasurementType);
-+
-+ if (measure_cmpl.Status == WSM_STATUS_SUCCESS){
-+ switch (measure_cmpl.MeasurementType) {
-+ case ChannelLoadMeasurement:
-+ chanload_res = &measure_cmpl.MeasurementReport.ChannelLoadResults;
-+ cca_chanload = (chanload_res->ChannelLoadCCA == MEAS_CCA) ?
-+ chanload_res->CCAbusyFraction :
-+ chanload_res->ChannelLoad;
-+ #ifdef PRINT_11K_MEASRURE
-+ wsm_printk(XRADIO_DBG_ERROR, "[11K] ChannelLoadMeasurement Result:\n"\
-+ "ChannelLoadCCA = %d\n"\
-+ "ChannelNum = %d\n"\
-+ "Duration = %d\n"\
-+ "Fraction = %d\n", \
-+ chanload_res->ChannelLoadCCA,\
-+ chanload_res->ChannelNum,\
-+ chanload_res->MeasurementDuration,\
-+ cca_chanload
-+ );
-+ #endif
-+ break;
-+ case NoiseHistrogramMeasurement:
-+ noise_res = &measure_cmpl.MeasurementReport.NoiseHistogramResults;
-+// IpiRpi = (noise_res->IpiRpi == MEAS_RPI) ?
-+// chanload_res->CCAbusyFraction :
-+// chanload_res->ChannelLoad;
-+ #ifdef PRINT_11K_MEASRURE
-+ wsm_printk(XRADIO_DBG_ERROR, "[11K] NoiseHistogramResults:\n"\
-+ "IpiRpi = %d\n"\
-+ "ChannelNum = %d\n"\
-+ "PI_0__Density = %d\n"\
-+ "PI_1__Density = %d\n"\
-+ "PI_2__Density = %d\n"\
-+ "PI_3__Density = %d\n"\
-+ "PI_4__Density = %d\n"\
-+ "PI_5__Density = %d\n"\
-+ "PI_6__Density = %d\n"\
-+ "PI_7__Density = %d\n"\
-+ "PI_8__Density = %d\n"\
-+ "PI_9__Density = %d\n"\
-+ "PI_10_Density = %d\n", \
-+ noise_res->IpiRpi,\
-+ noise_res->ChannelNum,\
-+ noise_res->PI_0_Density,\
-+ noise_res->PI_1_Density,\
-+ noise_res->PI_2_Density,\
-+ noise_res->PI_3_Density,\
-+ noise_res->PI_4_Density,\
-+ noise_res->PI_5_Density,\
-+ noise_res->PI_6_Density,\
-+ noise_res->PI_7_Density,\
-+ noise_res->PI_8_Density,\
-+ noise_res->PI_9_Density,\
-+ noise_res->PI_10_Density
-+ );
-+ #endif
-+ break;
-+ case BeaconReport:
-+ break;
-+ case STAstatisticsReport:
-+ break;
-+ case LinkMeasurement:
-+ break;
-+ }
-+ } else {
-+ wsm_printk(XRADIO_DBG_ERROR, "11K Measure(type=%d) Fail\n", measure_cmpl.MeasurementType);
-+ }
-+
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+/* TODO:COMBO:Make this perVIFF once mac80211 support is available */
-+static int wsm_channel_switch_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ wsm_unlock_tx(hw_priv); /* Re-enable datapath */
-+ WARN_ON(WSM_GET32(buf));
-+
-+ hw_priv->channel_switch_in_progress = 0;
-+ wake_up(&hw_priv->channel_switch_done);
-+
-+
-+ xradio_channel_switch_cb(hw_priv);
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+
-+static int wsm_set_pm_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ wsm_oper_unlock(hw_priv);
-+ return 0;
-+}
-+
-+static int wsm_scan_complete_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ struct wsm_scan_complete arg;
-+#ifdef ROAM_OFFLOAD
-+ if(hw_priv->auto_scanning == 0)
-+ wsm_oper_unlock(hw_priv);
-+#else
-+ wsm_oper_unlock(hw_priv);
-+#endif /*ROAM_OFFLOAD*/
-+
-+ arg.status = WSM_GET32(buf);
-+ arg.psm = WSM_GET8(buf);
-+ arg.numChannels = WSM_GET8(buf);
-+ xradio_scan_complete_cb(hw_priv, &arg);
-+
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+
-+static int wsm_find_complete_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ /* TODO: Implement me. */
-+ //STUB();
-+ return 0;
-+}
-+
-+static int wsm_suspend_resume_indication(struct xradio_common *hw_priv,
-+ int interface_link_id,
-+ struct wsm_buf *buf)
-+{
-+ u32 flags;
-+ struct wsm_suspend_resume arg;
-+ struct xradio_vif *priv;
-+
-+ if (is_hardware_xradio(hw_priv)) {
-+ int i;
-+ arg.if_id = interface_link_id;
-+ /* TODO:COMBO: Extract bitmap from suspend-resume
-+ * TX indication */
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ if (priv->join_status ==
-+ XRADIO_JOIN_STATUS_AP) {
-+ arg.if_id = priv->if_id;
-+ break;
-+ }
-+ arg.link_id = 0;
-+ }
-+ } else {
-+ arg.if_id = 0;
-+ arg.link_id = interface_link_id;
-+ }
-+
-+ flags = WSM_GET32(buf);
-+ arg.stop = !(flags & 1);
-+ arg.multicast = !!(flags & 8);
-+ arg.queue = (flags >> 1) & 3;
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, arg.if_id);
-+ if (unlikely(!priv)) {
-+ wsm_printk(XRADIO_DBG_MSG, "suspend-resume indication"
-+ " for removed interface!\n");
-+ return 0;
-+ }
-+ xradio_suspend_resume(priv, &arg);
-+ spin_unlock(&priv->vif_lock);
-+
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+
-+
-+/* ******************************************************************** */
-+/* WSM TX */
-+
-+int wsm_cmd_send(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf,
-+ void *arg, u16 cmd, long tmo, int if_id)
-+{
-+ size_t buf_len = buf->data - buf->begin;
-+ int ret;
-+
-+ if (cmd == 0x0006 || cmd == 0x0005) /* Write/Read MIB */
-+ wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X [MIB: 0x%.4X] (%d)\n",
-+ cmd, __le16_to_cpu(((__le16 *)buf->begin)[2]),
-+ buf_len);
-+ else
-+ wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X (%d)\n", cmd, buf_len);
-+
-+ if (unlikely(hw_priv->bh_error)) {
-+ wsm_buf_reset(buf);
-+ wsm_printk(XRADIO_DBG_ERROR, "bh error!>>> 0x%.4X (%d)\n", cmd, buf_len);
-+ return -ETIMEDOUT;
-+ }
-+
-+ /* Fill HI message header */
-+ /* BH will add sequence number */
-+
-+ /* TODO:COMBO: Add if_id from to the WSM header */
-+ /* if_id == -1 indicates that command is HW specific,
-+ * eg. wsm_configuration which is called during driver initialzation
-+ * (mac80211 .start callback called when first ifce is created. )*/
-+
-+ /* send hw specific commands on if 0 */
-+ if (if_id == -1)
-+ if_id = 0;
-+
-+ ((__le16 *)buf->begin)[0] = __cpu_to_le16(buf_len);
-+ ((__le16 *)buf->begin)[1] = __cpu_to_le16(cmd |
-+ ((is_hardware_xradio(hw_priv)) ? (if_id << 6) : 0));
-+
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ BUG_ON(hw_priv->wsm_cmd.ptr);
-+ hw_priv->wsm_cmd.done = 0;
-+ hw_priv->wsm_cmd.ptr = buf->begin;
-+ hw_priv->wsm_cmd.len = buf_len;
-+ hw_priv->wsm_cmd.arg = arg;
-+ hw_priv->wsm_cmd.cmd = cmd;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+
-+ xradio_bh_wakeup(hw_priv);
-+
-+ if (unlikely(hw_priv->bh_error)) {
-+ /* Do not wait for timeout if BH is dead. Exit immediately. */
-+ ret = 0;
-+ } else {
-+ unsigned long wsm_cmd_max_tmo;
-+
-+ /* Give start cmd a little more time */
-+ if (unlikely(tmo == WSM_CMD_START_TIMEOUT))
-+ wsm_cmd_max_tmo = WSM_CMD_START_TIMEOUT;
-+ else
-+ wsm_cmd_max_tmo = WSM_CMD_DEFAULT_TIMEOUT;
-+
-+ /*Set max timeout.*/
-+ wsm_cmd_max_tmo = jiffies + wsm_cmd_max_tmo;
-+
-+ /* Firmware prioritizes data traffic over control confirm.
-+ * Loop below checks if data was RXed and increases timeout
-+ * accordingly. */
-+ do {
-+ /* It's safe to use unprotected access to wsm_cmd.done here */
-+ ret = wait_event_timeout(hw_priv->wsm_cmd_wq, hw_priv->wsm_cmd.done, tmo);
-+
-+ /* check time since last rxed and max timeout.*/
-+ } while (!ret &&
-+ time_before_eq(jiffies, hw_priv->rx_timestamp+tmo) &&
-+ time_before(jiffies, wsm_cmd_max_tmo));
-+
-+ }
-+
-+ if (unlikely(ret == 0)) {
-+ u16 raceCheck;
-+
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ raceCheck = hw_priv->wsm_cmd.cmd;
-+ hw_priv->wsm_cmd.arg = NULL;
-+ hw_priv->wsm_cmd.ptr = NULL;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+
-+ dev_err(hw_priv->pdev, "***CMD timeout!>>> 0x%.4X (%d), buf_use=%d, bh_state=%d\n",
-+ cmd, buf_len, hw_priv->hw_bufs_used, hw_priv->bh_error);
-+ /* Race condition check to make sure _confirm is not called
-+ * after exit of _send */
-+ if (raceCheck == 0xFFFF) {
-+ /* If wsm_handle_rx got stuck in _confirm we will hang
-+ * system there. It's better than silently currupt
-+ * stack or heap, isn't it? */
-+ BUG_ON(wait_event_timeout(
-+ hw_priv->wsm_cmd_wq,
-+ hw_priv->wsm_cmd.done,
-+ WSM_CMD_LAST_CHANCE_TIMEOUT) <= 0);
-+ }
-+
-+ /* Kill BH thread to report the error to the top layer. */
-+ hw_priv->bh_error = 1;
-+#ifdef BH_USE_SEMAPHORE
-+ up(&hw_priv->bh_sem);
-+#else
-+ wake_up(&hw_priv->bh_wq);
-+#endif
-+ ret = -ETIMEDOUT;
-+ } else {
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ BUG_ON(!hw_priv->wsm_cmd.done);
-+ ret = hw_priv->wsm_cmd.ret;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ }
-+ wsm_buf_reset(buf);
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+/* WSM TX port control */
-+
-+void wsm_lock_tx(struct xradio_common *hw_priv)
-+{
-+ down(&hw_priv->tx_lock_sem);
-+ atomic_add(1, &hw_priv->tx_lock);
-+ /* always check event if wsm_vif_lock_tx.*/
-+ if (wsm_flush_tx(hw_priv))
-+ wsm_printk(XRADIO_DBG_MSG, "TX is locked.\n");
-+ up(&hw_priv->tx_lock_sem);
-+}
-+
-+void wsm_vif_lock_tx(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+ down(&hw_priv->tx_lock_sem);
-+ if (atomic_add_return(1, &hw_priv->tx_lock) == 1) {
-+ if (wsm_vif_flush_tx(priv))
-+ wsm_printk(XRADIO_DBG_MSG, "TX is locked for"
-+ " if_id %d.\n", priv->if_id);
-+ }
-+ up(&hw_priv->tx_lock_sem);
-+}
-+
-+void wsm_lock_tx_async(struct xradio_common *hw_priv)
-+{
-+ if (atomic_add_return(1, &hw_priv->tx_lock) == 1)
-+ wsm_printk(XRADIO_DBG_MSG, "TX is locked (async).\n");
-+}
-+
-+bool wsm_flush_tx(struct xradio_common *hw_priv)
-+{
-+ long timeout = WSM_CMD_LAST_CHANCE_TIMEOUT;
-+
-+ /* Flush must be called with TX lock held. */
-+ BUG_ON(!atomic_read(&hw_priv->tx_lock));
-+
-+ /* First check if we really need to do something.
-+ * It is safe to use unprotected access, as hw_bufs_used
-+ * can only decrements. */
-+ if (!hw_priv->hw_bufs_used)
-+ return true;
-+
-+ if (hw_priv->bh_error) {
-+ /* In case of failure do not wait for magic. */
-+ wsm_printk(XRADIO_DBG_ERROR, "Fatal error occured, "
-+ "will not flush TX.\n");
-+ return false;
-+ } else {
-+ /* Get "oldest" frame, if any frames stuck in firmware,
-+ query all of them until max timeout. */
-+ int num = hw_priv->hw_bufs_used + 1;
-+ while (xradio_query_txpkt_timeout(hw_priv, XRWL_ALL_IFS,
-+ 0xffffffff, &timeout)) {
-+ if (timeout < 0 || !num) {
-+ /* Hmmm... Not good. Frame had stuck in firmware. */
-+ wsm_printk(XRADIO_DBG_ERROR,
-+ "%s:hw_bufs_used=%d, num=%d, timeout=%ld\n",
-+ __func__, hw_priv->hw_bufs_used, num, timeout);
-+ hw_priv->bh_error = 1;
-+#ifdef BH_USE_SEMAPHORE
-+ up(&hw_priv->bh_sem);
-+#else
-+ wake_up(&hw_priv->bh_wq);
-+#endif
-+ return false;
-+ } else if (wait_event_timeout(hw_priv->bh_evt_wq,
-+ !hw_priv->hw_bufs_used, timeout) > 0) {
-+ return true;
-+ }
-+ --num;
-+ }
-+ if (hw_priv->hw_bufs_used)
-+ wsm_printk(XRADIO_DBG_ERROR, "%s:No pengding, but hw_bufs_used=%d\n",
-+ __func__, hw_priv->hw_bufs_used);
-+ /* Ok, everything is flushed. */
-+ return true;
-+ }
-+}
-+
-+bool wsm_vif_flush_tx(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+ long timeout = WSM_CMD_LAST_CHANCE_TIMEOUT;
-+ int if_id = priv->if_id;
-+
-+ /* Flush must be called with TX lock held. */
-+ BUG_ON(!atomic_read(&hw_priv->tx_lock));
-+
-+ /* First check if we really need to do something.
-+ * It is safe to use unprotected access, as hw_bufs_used
-+ * can only decrements. */
-+ if (!hw_priv->hw_bufs_used_vif[if_id])
-+ return true;
-+
-+ if (hw_priv->bh_error) {
-+ /* In case of failure do not wait for magic. */
-+ wsm_printk(XRADIO_DBG_ERROR, "Fatal error occured, "
-+ "will not flush TX.\n");
-+ return false;
-+ } else {
-+ /* Get "oldest" frame, if any frames stuck in firmware,
-+ query all of them until max timeout. */
-+ int num = hw_priv->hw_bufs_used_vif[if_id] + 1;
-+ while (xradio_query_txpkt_timeout(hw_priv, if_id, 0xffffffff, &timeout)) {
-+ if (timeout < 0 || !num) {
-+ /* Hmmm... Not good. Frame had stuck in firmware. */
-+ wsm_printk(XRADIO_DBG_ERROR, "%s: if_id=%d, hw_bufs_used_vif=%d, num=%d\n",
-+ __func__, if_id, hw_priv->hw_bufs_used_vif[priv->if_id],
-+ num);
-+ hw_priv->bh_error = 1;
-+ #ifdef BH_USE_SEMAPHORE
-+ up(&hw_priv->bh_sem);
-+ #else
-+ wake_up(&hw_priv->bh_wq);
-+ #endif
-+ return false;
-+ } else if (wait_event_timeout(hw_priv->bh_evt_wq,
-+ !hw_priv->hw_bufs_used_vif[if_id], timeout) > 0) {
-+ return true;
-+ }
-+ --num;
-+ }
-+ if (hw_priv->hw_bufs_used_vif[if_id])
-+ wsm_printk(XRADIO_DBG_ERROR, "%s:No pengding, but hw_bufs_used_vif=%d\n",
-+ __func__, hw_priv->hw_bufs_used_vif[priv->if_id]);
-+ /* Ok, everything is flushed. */
-+ return true;
-+ }
-+}
-+
-+
-+void wsm_unlock_tx(struct xradio_common *hw_priv)
-+{
-+ int tx_lock;
-+ if (hw_priv->bh_error)
-+ wsm_printk(XRADIO_DBG_ERROR, "bh_error=%d, wsm_unlock_tx is unsafe\n",
-+ hw_priv->bh_error);
-+ else {
-+ tx_lock = atomic_sub_return(1, &hw_priv->tx_lock);
-+ if (tx_lock < 0) {
-+ BUG_ON(1);
-+ } else if (tx_lock == 0) {
-+ xradio_bh_wakeup(hw_priv);
-+ wsm_printk(XRADIO_DBG_MSG, "TX is unlocked.\n");
-+ }
-+ }
-+}
-+
-+/* ******************************************************************** */
-+/* WSM RX */
-+
-+int wsm_handle_exception(struct xradio_common *hw_priv, u8 *data, size_t len)
-+{
-+ struct wsm_buf buf;
-+ u32 reason;
-+ u32 reg[18];
-+ char fname[48];
-+ int i = 0;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ struct xradio_vif *priv = NULL;
-+#endif
-+
-+ static const char * const reason_str[] = {
-+ "undefined instruction",
-+ "prefetch abort",
-+ "data abort",
-+ "unknown error",
-+ };
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ /* Send the event upwards on the FW exception */
-+ xradio_pm_stay_awake(&hw_priv->pm_state, 3*HZ);
-+
-+ spin_lock(&hw_priv->vif_list_lock);
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ //ieee80211_driver_hang_notify(priv->vif, GFP_KERNEL);
-+ }
-+ spin_unlock(&hw_priv->vif_list_lock);
-+#endif
-+
-+ buf.begin = buf.data = data;
-+ buf.end = &buf.begin[len];
-+
-+ reason = WSM_GET32(&buf);
-+ for (i = 0; i < ARRAY_SIZE(reg); ++i)
-+ reg[i] = WSM_GET32(&buf);
-+ WSM_GET(&buf, fname, sizeof(fname));
-+
-+ if (reason < 4) {
-+ dev_err(hw_priv->pdev, "Firmware exception: %s.\n",
-+ reason_str[reason]);
-+ } else {
-+ dev_err(hw_priv->pdev, "Firmware assert at %.*s, line %d, reason=0x%x\n",
-+ sizeof(fname), fname, reg[1], reg[2]);
-+ }
-+
-+ for (i = 0; i < 12; i += 4) {
-+ dev_err(hw_priv->pdev, "Firmware:" \
-+ "R%d: 0x%.8X, R%d: 0x%.8X, R%d: 0x%.8X, R%d: 0x%.8X,\n",
-+ i + 0, reg[i + 0], i + 1, reg[i + 1],
-+ i + 2, reg[i + 2], i + 3, reg[i + 3]);
-+ }
-+ dev_err(hw_priv->pdev, "Firmware:" \
-+ "R12: 0x%.8X, SP: 0x%.8X, LR: 0x%.8X, PC: 0x%.8X,\n",
-+ reg[i + 0], reg[i + 1], reg[i + 2], reg[i + 3]);
-+ i += 4;
-+ dev_err(hw_priv->pdev, "Firmware:CPSR: 0x%.8X, SPSR: 0x%.8X\n",
-+ reg[i + 0], reg[i + 1]);
-+
-+ return 0;
-+
-+underflow:
-+ dev_err(hw_priv->pdev, "Firmware exception.\n");
-+ print_hex_dump_bytes("Exception: ", DUMP_PREFIX_NONE, data, len);
-+ return -EINVAL;
-+}
-+
-+static int wsm_debug_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ //for only one debug item.
-+ u32 dbg_id, buf_data=0;
-+ u16 dbg_buf_len;
-+ u8 dbg_len;
-+ u8 *dbg_buf;
-+ dbg_id = WSM_GET32(buf);
-+
-+ dbg_buf_len = buf->end - buf->data;
-+
-+ if (dbg_id == 5) {
-+ do {
-+ dbg_buf_len = buf->end - buf->data;
-+ dbg_len = WSM_GET8(buf);
-+ if (dbg_len > dbg_buf_len - sizeof(dbg_len)) {
-+ wsm_printk(XRADIO_DBG_ERROR, "[FW]dbg_len = %d\n", dbg_len);
-+ wsm_printk(XRADIO_DBG_ERROR, "[FW]dbg_buf_len = %d\n", dbg_buf_len);
-+ wsm_printk(XRADIO_DBG_ERROR, "[FW]debug ind err\n");
-+ //ret = -EINVAL;
-+ //return ret;
-+
-+
-+ break;
-+ }
-+
-+ dbg_buf = buf->data;
-+ //print it;
-+ wsm_printk(XRADIO_DBG_ALWY, "[FW-LOG] %s", dbg_buf);
-+ //
-+ buf->data += dbg_len;
-+
-+ } while (buf->data < buf->end);
-+ } else {
-+ if (dbg_buf_len >= 4) {
-+ buf_data = WSM_GET32(buf);
-+ wsm_printk(XRADIO_DBG_ALWY, "[FW-DEBUG] DbgId = %d, data = %d", dbg_id, buf_data);
-+ } else {
-+ wsm_printk(XRADIO_DBG_ALWY, "[FW-DEBUG] DbgId = %d", dbg_id);
-+ }
-+ }
-+
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+int wsm_handle_rx(struct xradio_common *hw_priv, int id,
-+ struct wsm_hdr *wsm, struct sk_buff **skb_p)
-+{
-+ int ret = 0;
-+ struct wsm_buf wsm_buf;
-+ /* struct xradio_vif *priv = NULL; MRK: unused variable, see if 0 below */
-+ /* int i = 0; MRK: unused variable, see if 0 below */
-+ int interface_link_id = (id >> 6) & 0x0F;
-+#ifdef ROAM_OFFLOAD
-+#if 0
-+ struct xradio_vif *priv;
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
-+ if (unlikely(!priv)) {
-+ WARN_ON(1);
-+ return 0;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+#endif
-+#endif/*ROAM_OFFLOAD*/
-+
-+ /* Strip link id. */
-+ id &= ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX);
-+
-+ wsm_buf.begin = (u8 *)&wsm[0];
-+ wsm_buf.data = (u8 *)&wsm[1];
-+ wsm_buf.end = &wsm_buf.begin[__le32_to_cpu(wsm->len)];
-+
-+ wsm_printk(XRADIO_DBG_MSG, "<<< 0x%.4X (%d)\n", id,
-+ wsm_buf.end - wsm_buf.begin);
-+
-+#if defined(DGB_XRADIO_HWT)
-+/***************************for HWT ********************************/
-+ if (id == 0x0424) {
-+ u16 TestID = *(u16 *)(wsm_buf.data);
-+ if (TestID == 1) //test frame confirm.
-+ wsm_hwt_tx_confirm(hw_priv, &wsm_buf);
-+ else {
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ hw_priv->wsm_cmd.ret = *((u16 *)(wsm_buf.data) + 1);
-+ hw_priv->wsm_cmd.done = 1;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ wake_up(&hw_priv->wsm_cmd_wq);
-+ wsm_printk(XRADIO_DBG_ALWY, "HWT TestID=0x%x Confirm ret=%d\n",
-+ *(u16 *)(wsm_buf.data), hw_priv->wsm_cmd.ret);
-+ }
-+ return 0;
-+ } else if (id == 0x0824) {
-+ u16 TestID = *(u16 *)(wsm_buf.data);
-+ switch (TestID) {
-+ case 2: //recieve a test frame.
-+ wsm_hwt_rx_frames(hw_priv, &wsm_buf);
-+ break;
-+ case 3: //enc test result.
-+ wsm_hwt_enc_results(hw_priv, &wsm_buf);
-+ break;
-+ case 4: //mic test result.
-+ wsm_hwt_mic_results(hw_priv, &wsm_buf);
-+ break;
-+ default:
-+ wsm_printk(XRADIO_DBG_ERROR, "HWT ERROR Indication TestID=0x%x\n", TestID);
-+ break;
-+ }
-+ return 0;
-+ }
-+/***************************for HWT ********************************/
-+#endif //DGB_XRADIO_HWT
-+
-+ if (id == 0x404) {
-+ ret = wsm_tx_confirm(hw_priv, &wsm_buf, interface_link_id);
-+#ifdef MCAST_FWDING
-+#if 1
-+ } else if (id == 0x422) {
-+ ret = wsm_give_buffer_confirm(hw_priv, &wsm_buf);
-+#endif
-+#endif
-+
-+ } else if (id == 0x41E) {
-+ ret = wsm_multi_tx_confirm(hw_priv, &wsm_buf,
-+ interface_link_id);
-+ } else if (id & 0x0400) {
-+ void *wsm_arg;
-+ u16 wsm_cmd;
-+
-+ /* Do not trust FW too much. Protection against repeated
-+ * response and race condition removal (see above). */
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ wsm_arg = hw_priv->wsm_cmd.arg;
-+ wsm_cmd = hw_priv->wsm_cmd.cmd &
-+ ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX);
-+ hw_priv->wsm_cmd.cmd = 0xFFFF;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+
-+ if (WARN_ON((id & ~0x0400) != wsm_cmd)) {
-+ /* Note that any non-zero is a fatal retcode. */
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ switch (id) {
-+ case 0x0409:
-+ /* Note that wsm_arg can be NULL in case of timeout in
-+ * wsm_cmd_send(). */
-+ if (likely(wsm_arg))
-+ ret = wsm_configuration_confirm(hw_priv,
-+ wsm_arg,
-+ &wsm_buf);
-+ break;
-+ case 0x0405:
-+ if (likely(wsm_arg))
-+ ret = wsm_read_mib_confirm(hw_priv, wsm_arg,
-+ &wsm_buf);
-+ break;
-+ case 0x0406:
-+ if (likely(wsm_arg))
-+ ret = wsm_write_mib_confirm(hw_priv, wsm_arg,
-+ &wsm_buf,
-+ interface_link_id);
-+ break;
-+ case 0x040B:
-+ if (likely(wsm_arg))
-+ ret = wsm_join_confirm(hw_priv, wsm_arg, &wsm_buf);
-+ if (ret)
-+ wsm_printk(XRADIO_DBG_WARN, "Join confirm Failed!\n");
-+ break;
-+ case 0x040E: /* 11K measure*/
-+ if (likely(wsm_arg))
-+ ret = wsm_generic_confirm(hw_priv, wsm_arg, &wsm_buf);
-+ if (ret)
-+ wsm_printk(XRADIO_DBG_ERROR, "[***HL***]11K Confirm Error\n");
-+
-+ break;
-+
-+#ifdef MCAST_FWDING
-+ case 0x0423: /* req buffer cfm*/
-+ if (likely(wsm_arg)){
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (priv && (priv->join_status == XRADIO_JOIN_STATUS_AP))
-+ ret = wsm_request_buffer_confirm(priv,
-+ wsm_arg, &wsm_buf);
-+ }
-+ }
-+ break;
-+#endif
-+ case 0x0407: /* start-scan */
-+#ifdef ROAM_OFFLOAD
-+ if (hw_priv->auto_scanning) {
-+ if (atomic_read(&hw_priv->scan.in_progress)) {
-+ hw_priv->auto_scanning = 0;
-+ }
-+ else {
-+ wsm_oper_unlock(hw_priv);
-+ up(&hw_priv->scan.lock);
-+ }
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+ case 0x0408: /* stop-scan */
-+ case 0x040A: /* wsm_reset */
-+ case 0x040C: /* add_key */
-+ case 0x040D: /* remove_key */
-+ case 0x0410: /* wsm_set_pm */
-+ case 0x0411: /* set_bss_params */
-+ case 0x0412: /* set_tx_queue_params */
-+ case 0x0413: /* set_edca_params */
-+ case 0x0416: /* switch_channel */
-+ case 0x0417: /* start */
-+ case 0x0418: /* beacon_transmit */
-+ case 0x0419: /* start_find */
-+ case 0x041A: /* stop_find */
-+ case 0x041B: /* update_ie */
-+ case 0x041C: /* map_link */
-+ WARN_ON(wsm_arg != NULL);
-+ ret = wsm_generic_confirm(hw_priv, wsm_arg, &wsm_buf);
-+ if (ret)
-+ wsm_printk(XRADIO_DBG_ERROR,
-+ "wsm_generic_confirm "
-+ "failed for request 0x%.4X.\n",
-+ id & ~0x0400);
-+ break;
-+ default:
-+ BUG_ON(1);
-+ }
-+
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ hw_priv->wsm_cmd.ret = ret;
-+ hw_priv->wsm_cmd.done = 1;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ ret = 0; /* Error response from device should ne stop BH. */
-+
-+ wake_up(&hw_priv->wsm_cmd_wq);
-+ } else if (id & 0x0800) {
-+ switch (id) {
-+ case 0x0801:
-+ ret = wsm_startup_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x0804:
-+ ret = wsm_receive_indication(hw_priv, interface_link_id,
-+ &wsm_buf, skb_p);
-+ break;
-+ case 0x0805:
-+ ret = wsm_event_indication(hw_priv, &wsm_buf,
-+ interface_link_id);
-+ break;
-+ case 0x0807:
-+ wsm_printk(XRADIO_DBG_ERROR, "[11K]wsm_measure_cmpl_indication\n");
-+// wsm_printk(XRADIO_DBG_ERROR, "[11K]wsm->len = %d\n",wsm->len);
-+
-+ ret = wsm_measure_cmpl_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x080A:
-+ ret = wsm_channel_switch_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x0809:
-+ ret = wsm_set_pm_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x0806:
-+#ifdef ROAM_OFFLOAD
-+ if(hw_priv->auto_scanning && hw_priv->frame_rcvd) {
-+ struct xradio_vif *priv;
-+ hw_priv->frame_rcvd = 0;
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
-+ if (unlikely(!priv)) {
-+ WARN_ON(1);
-+ return 0;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+ if (hw_priv->beacon) {
-+ struct wsm_scan_complete *scan_cmpl = \
-+ (struct wsm_scan_complete *) \
-+ ((u8 *)wsm + sizeof(struct wsm_hdr));
-+ struct ieee80211_rx_status *rhdr = \
-+ IEEE80211_SKB_RXCB(hw_priv->beacon);
-+ rhdr->signal = (s8)scan_cmpl->reserved;
-+ if (!priv->cqm_use_rssi) {
-+ rhdr->signal = rhdr->signal / 2 - 110;
-+ }
-+ if (!hw_priv->beacon_bkp)
-+ hw_priv->beacon_bkp = \
-+ skb_copy(hw_priv->beacon, GFP_ATOMIC);
-+ ieee80211_rx_irqsafe(hw_priv->hw, hw_priv->beacon);
-+ hw_priv->beacon = hw_priv->beacon_bkp;
-+
-+ hw_priv->beacon_bkp = NULL;
-+ }
-+ wsm_printk(XRADIO_DBG_MSG, \
-+ "Send Testmode Event.\n");
-+ xradio_testmode_event(priv->hw->wiphy,
-+ NL80211_CMD_NEW_SCAN_RESULTS, 0,
-+ 0, GFP_KERNEL);
-+
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+ ret = wsm_scan_complete_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x080B:
-+ ret = wsm_find_complete_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x080C:
-+ ret = wsm_suspend_resume_indication(hw_priv,
-+ interface_link_id, &wsm_buf);
-+ break;
-+ case 0x080E:
-+ wsm_printk(XRADIO_DBG_MSG, "wsm_debug_indication");
-+ ret = wsm_debug_indication(hw_priv, &wsm_buf);
-+ break;
-+
-+ default:
-+ wsm_printk(XRADIO_DBG_ERROR, "unknown Indmsg ID=0x%04x,len=%d\n",
-+ wsm->id, wsm->len);
-+ break;
-+ }
-+ } else {
-+ WARN_ON(1);
-+ ret = -EINVAL;
-+ }
-+out:
-+ return ret;
-+}
-+
-+static bool wsm_handle_tx_data(struct xradio_vif *priv,
-+ const struct wsm_tx *wsm,
-+ const struct ieee80211_tx_info *tx_info,
-+ struct xradio_txpriv *txpriv,
-+ struct xradio_queue *queue)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ bool handled = false;
-+ const struct ieee80211_hdr *frame =
-+ (struct ieee80211_hdr *) &((u8 *)wsm)[txpriv->offset];
-+ __le16 fctl = frame->frame_control;
-+ enum {
-+ doProbe,
-+ doDrop,
-+ doJoin,
-+ doOffchannel,
-+ doWep,
-+ doTx,
-+ } action = doTx;
-+
-+ hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ frame = (struct ieee80211_hdr *) &((u8 *)wsm)[txpriv->offset];
-+ fctl = frame->frame_control;
-+
-+ switch (priv->mode) {
-+ case NL80211_IFTYPE_STATION:
-+ if (unlikely(priv->bss_loss_status == XRADIO_BSS_LOSS_CHECKING &&
-+ priv->join_status == XRADIO_JOIN_STATUS_STA) &&
-+ ieee80211_is_data(fctl)) {
-+ spin_lock(&priv->bss_loss_lock);
-+ priv->bss_loss_confirm_id = wsm->packetID;
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_CONFIRMING;
-+ spin_unlock(&priv->bss_loss_lock);
-+ } else if (unlikely((priv->join_status <= XRADIO_JOIN_STATUS_MONITOR) ||
-+ memcmp(frame->addr1, priv->join_bssid,sizeof(priv->join_bssid)))) {
-+ if (ieee80211_is_auth(fctl))
-+ action = doJoin;
-+ else if ((ieee80211_is_deauth(fctl) || ieee80211_is_disassoc(fctl))&&
-+ priv->join_status < XRADIO_JOIN_STATUS_MONITOR)
-+ action = doDrop; //no need to send deauth when STA-unjoined, yangfh 2014-10-31 16:32:16.
-+ else if (ieee80211_is_probe_req(fctl))
-+ action = doTx;
-+ else if (memcmp(frame->addr1, priv->join_bssid,
-+ sizeof(priv->join_bssid)) &&
-+ (priv->join_status ==
-+ XRADIO_JOIN_STATUS_STA) &&
-+ (ieee80211_is_data(fctl))) {
-+ action = doDrop;
-+ }
-+ else if (priv->join_status >=
-+ XRADIO_JOIN_STATUS_MONITOR)
-+ action = doTx;
-+ else if (get_interface_id_scanning(hw_priv) != -1) {
-+ wsm_printk(XRADIO_DBG_WARN, "Scan ONGOING dropping"
-+ " offchannel eligible frame.\n");
-+ action = doDrop;
-+ } else {
-+ if (ieee80211_is_probe_resp(fctl))
-+ action = doDrop;
-+ else
-+ action = doOffchannel;
-+ wsm_printk(XRADIO_DBG_WARN, "Offchannel fctl=0x%04x", fctl);
-+ }
-+ }
-+ break;
-+ case NL80211_IFTYPE_AP:
-+ if (unlikely(!priv->join_status))
-+ action = doDrop;
-+ else if (unlikely(!(BIT(txpriv->raw_link_id) &
-+ (BIT(0) | priv->link_id_map)))) {
-+ wsm_printk(XRADIO_DBG_WARN,
-+ "A frame with expired link id "
-+ "is dropped.\n");
-+ action = doDrop;
-+ }
-+ if (xradio_queue_get_generation(wsm->packetID) >
-+ XRADIO_MAX_REQUEUE_ATTEMPTS) {
-+ /* HACK!!! WSM324 firmware has tendency to requeue
-+ * multicast frames in a loop, causing performance
-+ * drop and high power consumption of the driver.
-+ * In this situation it is better just to drop
-+ * the problematic frame. */
-+ wsm_printk(XRADIO_DBG_WARN,
-+ "Too many attempts "
-+ "to requeue a frame. "
-+ "Frame is dropped, fctl=0x%04x.\n", fctl);
-+ action = doDrop;
-+ }
-+ break;
-+ case NL80211_IFTYPE_ADHOC:
-+ case NL80211_IFTYPE_MESH_POINT:
-+ //STUB();
-+ case NL80211_IFTYPE_MONITOR:
-+ default:
-+ action = doDrop;
-+ break;
-+ }
-+
-+ if (action == doTx) {
-+ if (unlikely(ieee80211_is_probe_req(fctl))) {
-+ action = doProbe;
-+ } else if ((fctl & __cpu_to_le32(IEEE80211_FCTL_PROTECTED)) &&
-+ tx_info->control.hw_key &&
-+ unlikely(tx_info->control.hw_key->keyidx !=
-+ priv->wep_default_key_id) &&
-+ (tx_info->control.hw_key->cipher ==
-+ WLAN_CIPHER_SUITE_WEP40 ||
-+ tx_info->control.hw_key->cipher ==
-+ WLAN_CIPHER_SUITE_WEP104)) {
-+ action = doWep;
-+ }
-+ }
-+
-+ switch (action) {
-+ case doProbe:
-+ {
-+ /* An interesting FW "feature". Device filters
-+ * probe responses.
-+ * The easiest way to get it back is to convert
-+ * probe request into WSM start_scan command. */
-+ wsm_printk(XRADIO_DBG_MSG, \
-+ "Convert probe request to scan.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
-+ queue_delayed_work(hw_priv->workqueue,
-+ &hw_priv->scan.probe_work, 0);
-+ handled = true;
-+ }
-+ break;
-+ case doDrop:
-+ {
-+ /* See detailed description of "join" below.
-+ * We are dropping everything except AUTH in non-joined mode. */
-+ wsm_printk(XRADIO_DBG_MSG, "Drop frame (0x%.4X).\n", fctl);
-+ BUG_ON(xradio_queue_remove(queue,
-+ __le32_to_cpu(wsm->packetID)));
-+ handled = true;
-+ }
-+ break;
-+ case doJoin:
-+ {
-+ /* p2p should disconnect when sta try to join a different channel AP,
-+ * because no good performance in this case.
-+ */
-+ struct xradio_vif *p2p_tmp_vif = __xrwl_hwpriv_to_vifpriv(hw_priv, 1);
-+ if (priv->if_id == 0 && p2p_tmp_vif) {
-+ if (p2p_tmp_vif->join_status >= XRADIO_JOIN_STATUS_STA &&
-+ hw_priv->channel_changed) {
-+ wsm_printk(XRADIO_DBG_WARN, "combo with different channels, p2p disconnect.\n");
-+ wms_send_disassoc_to_self(hw_priv, p2p_tmp_vif);
-+ }
-+ }
-+
-+ /* There is one more interesting "feature"
-+ * in FW: it can't do RX/TX before "join".
-+ * "Join" here is not an association,
-+ * but just a syncronization between AP and STA.
-+ * priv->join_status is used only in bh thread and does
-+ * not require protection */
-+ wsm_printk(XRADIO_DBG_NIY, "Issue join command.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
-+ if (queue_work(hw_priv->workqueue, &priv->join_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ handled = true;
-+ }
-+ break;
-+ case doOffchannel:
-+ {
-+ wsm_printk(XRADIO_DBG_MSG, "Offchannel TX request.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
-+ if (queue_work(hw_priv->workqueue, &priv->offchannel_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ handled = true;
-+ }
-+ break;
-+ case doWep:
-+ {
-+ wsm_printk(XRADIO_DBG_MSG, "Issue set_default_wep_key.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ priv->wep_default_key_id = tx_info->control.hw_key->keyidx;
-+ hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
-+ if (queue_work(hw_priv->workqueue, &priv->wep_key_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ handled = true;
-+ }
-+ break;
-+ case doTx:
-+ {
-+#if 0
-+ /* Kept for history. If you want to implement wsm->more,
-+ * make sure you are able to send a frame after that. */
-+ wsm->more = (count > 1) ? 1 : 0;
-+ if (wsm->more) {
-+ /* HACK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-+ * It's undocumented in WSM spec, but XRADIO hangs
-+ * if 'more' is set and no TX is performed due to TX
-+ * buffers limitation. */
-+ if (priv->hw_bufs_used + 1 ==
-+ priv->wsm_caps.numInpChBufs)
-+ wsm->more = 0;
-+ }
-+
-+ /* BUG!!! FIXME: we can't use 'more' at all: we don't know
-+ * future. It could be a request from upper layer with TX lock
-+ * requirements (scan, for example). If "more" is set device
-+ * will not send data and wsm_tx_lock() will fail...
-+ * It's not obvious how to fix this deadlock. Any ideas?
-+ * As a workaround more is set to 0. */
-+ wsm->more = 0;
-+#endif /* 0 */
-+
-+ if (ieee80211_is_deauth(fctl) &&
-+ priv->mode != NL80211_IFTYPE_AP) {
-+ /* Shedule unjoin work */
-+ wsm_printk(XRADIO_DBG_WARN, "Issue unjoin command(TX).\n");
-+#if 0
-+ wsm->more = 0;
-+#endif /* 0 */
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->unjoin_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+ break;
-+ }
-+ return handled;
-+}
-+
-+static int xradio_get_prio_queue(struct xradio_vif *priv,
-+ u32 link_id_map, int *total)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ static u32 urgent;
-+ struct wsm_edca_queue_params *edca;
-+ unsigned score, best = -1;
-+ int winner = -1;
-+ int queued;
-+ int i;
-+ urgent = BIT(priv->link_id_after_dtim) | BIT(priv->link_id_uapsd);
-+
-+ /* search for a winner using edca params */
-+ for (i = 0; i < 4; ++i) {
-+ queued = xradio_queue_get_num_queued(priv,
-+ &hw_priv->tx_queue[i],
-+ link_id_map);
-+ if (!queued)
-+ continue;
-+ *total += queued;
-+ edca = &priv->edca.params[i];
-+ score = ((edca->aifns + edca->cwMin) << 16) +
-+ (edca->cwMax - edca->cwMin) *
-+ (prandom_u32() & 0xFFFF);
-+ if (score < best && (winner < 0 || i != 3)) {
-+ best = score;
-+ winner = i;
-+ }
-+ }
-+
-+ /* override winner if bursting */
-+ if (winner >= 0 && hw_priv->tx_burst_idx >= 0 &&
-+ winner != hw_priv->tx_burst_idx &&
-+ !xradio_queue_get_num_queued(priv,
-+ &hw_priv->tx_queue[winner],
-+ link_id_map & urgent) &&
-+ xradio_queue_get_num_queued(priv,
-+ &hw_priv->tx_queue[hw_priv->tx_burst_idx],
-+ link_id_map))
-+ winner = hw_priv->tx_burst_idx;
-+
-+ return winner;
-+}
-+
-+static int wsm_get_tx_queue_and_mask(struct xradio_vif *priv,
-+ struct xradio_queue **queue_p,
-+ u32 *tx_allowed_mask_p,
-+ bool *more)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int idx;
-+ u32 tx_allowed_mask;
-+ int total = 0;
-+
-+ /* Search for a queue with multicast frames buffered */
-+ if (priv->tx_multicast) {
-+ tx_allowed_mask = BIT(priv->link_id_after_dtim);
-+ idx = xradio_get_prio_queue(priv,
-+ tx_allowed_mask, &total);
-+ if (idx >= 0) {
-+ *more = total > 1;
-+ goto found;
-+ }
-+ }
-+
-+ /* Search for unicast traffic */
-+ tx_allowed_mask = ~priv->sta_asleep_mask;
-+ tx_allowed_mask |= BIT(priv->link_id_uapsd);
-+ if (priv->sta_asleep_mask) {
-+ tx_allowed_mask |= priv->pspoll_mask;
-+ tx_allowed_mask &= ~BIT(priv->link_id_after_dtim);
-+ } else {
-+ tx_allowed_mask |= BIT(priv->link_id_after_dtim);
-+ }
-+ idx = xradio_get_prio_queue(priv,
-+ tx_allowed_mask, &total);
-+ if (idx < 0)
-+ return -ENOENT;
-+
-+found:
-+ *queue_p = &hw_priv->tx_queue[idx];
-+ *tx_allowed_mask_p = tx_allowed_mask;
-+ return 0;
-+}
-+
-+int wsm_get_tx(struct xradio_common *hw_priv, u8 **data,
-+ size_t *tx_len, int *burst, int *vif_selected)
-+{
-+ struct wsm_tx *wsm = NULL;
-+ struct ieee80211_tx_info *tx_info;
-+ struct xradio_queue *queue = NULL;
-+ int queue_num;
-+ u32 tx_allowed_mask = 0;
-+ struct xradio_txpriv *txpriv = NULL;
-+ /*
-+ * Count was intended as an input for wsm->more flag.
-+ * During implementation it was found that wsm->more
-+ * is not usable, see details above. It is kept just
-+ * in case you would like to try to implement it again.
-+ */
-+ int count = 0;
-+ int if_pending = 1;
-+
-+ /* More is used only for broadcasts. */
-+ bool more = false;
-+
-+ if (hw_priv->wsm_cmd.ptr) {
-+ ++count;
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ BUG_ON(!hw_priv->wsm_cmd.ptr);
-+ *data = hw_priv->wsm_cmd.ptr;
-+ *tx_len = hw_priv->wsm_cmd.len;
-+ *burst = 1;
-+ *vif_selected = -1;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ } else {
-+ for (;;) {
-+ int ret;
-+ struct xradio_vif *priv;
-+#if 0
-+ int num_pending_vif0, num_pending_vif1;
-+#endif
-+ if (atomic_add_return(0, &hw_priv->tx_lock))
-+ break;
-+ /* Keep one buffer reserved for commands. Note
-+ that, hw_bufs_used has already been incremented
-+ before reaching here. */
-+ if (hw_priv->hw_bufs_used >=
-+ hw_priv->wsm_caps.numInpChBufs)
-+ break;
-+ priv = wsm_get_interface_for_tx(hw_priv);
-+ /* go to next interface ID to select next packet */
-+ hw_priv->if_id_selected ^= 1;
-+
-+ /* There might be no interface before add_interface
-+ * call */
-+ if (!priv) {
-+ if (if_pending) {
-+ if_pending = 0;
-+ continue;
-+ }
-+ break;
-+ }
-+
-+#if 0
-+ if (((priv->if_id == 0) &&
-+ (hw_priv->hw_bufs_used_vif[0] >=
-+ XRWL_FW_VIF0_THROTTLE)) ||
-+ ((priv->if_id == 1) &&
-+ (hw_priv->hw_bufs_used_vif[1] >=
-+ XRWL_FW_VIF1_THROTTLE))) {
-+ spin_unlock(&priv->vif_lock);
-+ if (if_pending) {
-+ if_pending = 0;
-+ continue;
-+ }
-+ break;
-+ }
-+#endif
-+
-+ /* This can be removed probably: xradio_vif will not
-+ * be in hw_priv->vif_list (as returned from
-+ * wsm_get_interface_for_tx) until it's fully
-+ * enabled, so statement above will take case of that*/
-+ if (!atomic_read(&priv->enabled)) {
-+ spin_unlock(&priv->vif_lock);
-+ break;
-+ }
-+
-+ /* TODO:COMBO: Find the next interface for which
-+ * packet needs to be found */
-+ spin_lock_bh(&priv->ps_state_lock);
-+ ret = wsm_get_tx_queue_and_mask(priv, &queue,
-+ &tx_allowed_mask, &more);
-+ queue_num = queue - hw_priv->tx_queue;
-+
-+ if (priv->buffered_multicasts &&
-+ (ret || !more) &&
-+ (priv->tx_multicast ||
-+ !priv->sta_asleep_mask)) {
-+ priv->buffered_multicasts = false;
-+ if (priv->tx_multicast) {
-+ priv->tx_multicast = false;
-+ queue_work(hw_priv->workqueue,
-+ &priv->multicast_stop_work);
-+ }
-+ }
-+
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+ if (ret) {
-+ spin_unlock(&priv->vif_lock);
-+ if (if_pending == 1) {
-+ if_pending = 0;
-+ continue;
-+ }
-+ break;
-+ }
-+
-+ if (xradio_queue_get(queue,
-+ priv->if_id,
-+ tx_allowed_mask,
-+ &wsm, &tx_info, &txpriv)) {
-+ spin_unlock(&priv->vif_lock);
-+ if_pending = 0;
-+ continue;
-+ }
-+
-+// #ifdef ROC_DEBUG
-+// {
-+// struct ieee80211_hdr *hdr =
-+// (struct ieee80211_hdr *)
-+// &((u8 *)wsm)[txpriv->offset];
-+//
-+// wsm_printk(XRADIO_DBG_ERROR, "QGET-1 %x, off_id %d,"
-+// " if_id %d\n",
-+// hdr->frame_control,
-+// txpriv->offchannel_if_id,
-+// priv->if_id);
-+// }
-+// #else
-+// {
-+// struct ieee80211_hdr *hdr =
-+// (struct ieee80211_hdr *)
-+// &((u8 *)wsm)[txpriv->offset];
-+//
-+// wsm_printk(XRADIO_DBG_ERROR, "QGET-1 %x, off_id %d,"
-+// " if_id %d\n",
-+// hdr->frame_control,
-+// txpriv->raw_if_id,
-+// priv->if_id);
-+// }
-+// #endif
-+
-+ if (wsm_handle_tx_data(priv, wsm,
-+ tx_info, txpriv, queue)) {
-+ spin_unlock(&priv->vif_lock);
-+ if_pending = 0;
-+ continue; /* Handled by WSM */
-+ }
-+
-+ wsm->hdr.id &= __cpu_to_le16(
-+ ~WSM_TX_IF_ID(WSM_TX_IF_ID_MAX));
-+ if (txpriv->offchannel_if_id)
-+ wsm->hdr.id |= cpu_to_le16(
-+ WSM_TX_IF_ID(txpriv->offchannel_if_id));
-+ else
-+ wsm->hdr.id |= cpu_to_le16(
-+ WSM_TX_IF_ID(priv->if_id));
-+
-+ *vif_selected = priv->if_id;
-+// #ifdef ROC_DEBUG
-+// /* remand the roc debug. */
-+// {
-+// struct ieee80211_hdr *hdr =
-+// (struct ieee80211_hdr *)
-+// &((u8 *)wsm)[txpriv->offset];
-+//
-+// wsm_printk(XRADIO_DBG_ERROR, "QGET-2 %x, off_id %d,"
-+// " if_id %d\n",
-+// hdr->frame_control,
-+// txpriv->offchannel_if_id,
-+// priv->if_id);
-+// }
-+// #else
-+// {
-+// struct ieee80211_hdr *hdr =
-+// (struct ieee80211_hdr *)
-+// &((u8 *)wsm)[txpriv->offset];
-+//
-+// wsm_printk(XRADIO_DBG_ERROR, "QGET-2 %x, off_id %d,"
-+// " if_id %d\n",
-+// hdr->frame_control,
-+// txpriv->raw_if_id,
-+// priv->if_id);
-+// }
-+// #endif
-+
-+ priv->pspoll_mask &= ~BIT(txpriv->raw_link_id);
-+
-+ *data = (u8 *)wsm;
-+ *tx_len = __le16_to_cpu(wsm->hdr.len);
-+
-+ /* allow bursting if txop is set */
-+ if (priv->edca.params[queue_num].txOpLimit)
-+ *burst = min(*burst,
-+ (int)xradio_queue_get_num_queued(priv,
-+ queue, tx_allowed_mask) + 1);
-+ else
-+ *burst = 1;
-+
-+ /* store index of bursting queue */
-+ if (*burst > 1)
-+ hw_priv->tx_burst_idx = queue_num;
-+ else
-+ hw_priv->tx_burst_idx = -1;
-+
-+ if (more) {
-+ struct ieee80211_hdr *hdr =
-+ (struct ieee80211_hdr *)
-+ &((u8 *)wsm)[txpriv->offset];
-+ if(strstr(&priv->ssid[0], "6.1.12")) {
-+ if(hdr->addr1[0] & 0x01 ) {
-+ hdr->frame_control |=
-+ cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-+ }
-+ }
-+ else {
-+ /* more buffered multicast/broadcast frames
-+ * ==> set MoreData flag in IEEE 802.11 header
-+ * to inform PS STAs */
-+ hdr->frame_control |=
-+ cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-+ }
-+ }
-+ wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X (%d) %p %c\n",
-+ 0x0004, *tx_len, *data,
-+ wsm->more ? 'M' : ' ');
-+ ++count;
-+ spin_unlock(&priv->vif_lock);
-+ break;
-+ }
-+ }
-+
-+ return count;
-+}
-+
-+void wsm_txed(struct xradio_common *hw_priv, u8 *data)
-+{
-+ if (data == hw_priv->wsm_cmd.ptr) {
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ hw_priv->wsm_cmd.ptr = NULL;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ }
-+}
-+
-+/* ******************************************************************** */
-+/* WSM buffer */
-+
-+void wsm_buf_init(struct wsm_buf *buf)
-+{
-+ int size = (SDIO_BLOCK_SIZE<<1); //for sdd file big than SDIO_BLOCK_SIZE
-+ BUG_ON(buf->begin);
-+ buf->begin = kmalloc(size, GFP_KERNEL);
-+ buf->end = buf->begin ? &buf->begin[size] : buf->begin;
-+ wsm_buf_reset(buf);
-+}
-+
-+void wsm_buf_deinit(struct wsm_buf *buf)
-+{
-+ if(buf->begin)
-+ kfree(buf->begin);
-+ buf->begin = buf->data = buf->end = NULL;
-+}
-+
-+static void wsm_buf_reset(struct wsm_buf *buf)
-+{
-+ if (buf->begin) {
-+ buf->data = &buf->begin[4];
-+ *(u32 *)buf->begin = 0;
-+ } else
-+ buf->data = buf->begin;
-+}
-+
-+static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size)
-+{
-+ size_t pos = buf->data - buf->begin;
-+ size_t size = pos + extra_size;
-+
-+
-+ if (size & (SDIO_BLOCK_SIZE - 1)) {
-+ size &= SDIO_BLOCK_SIZE;
-+ size += SDIO_BLOCK_SIZE;
-+ }
-+
-+ buf->begin = krealloc(buf->begin, size, GFP_KERNEL);
-+ if (buf->begin) {
-+ buf->data = &buf->begin[pos];
-+ buf->end = &buf->begin[size];
-+ return 0;
-+ } else {
-+ buf->end = buf->data = buf->begin;
-+ return -ENOMEM;
-+ }
-+}
-+
-+static struct xradio_vif
-+ *wsm_get_interface_for_tx(struct xradio_common *hw_priv)
-+{
-+ struct xradio_vif *priv = NULL, *i_priv;
-+ int i = hw_priv->if_id_selected;
-+
-+ if ( 1 /*TODO:COMBO*/) {
-+ spin_lock(&hw_priv->vif_list_lock);
-+ i_priv = hw_priv->vif_list[i] ?
-+ xrwl_get_vif_from_ieee80211(hw_priv->vif_list[i]) : NULL;
-+ if (i_priv) {
-+ priv = i_priv;
-+ spin_lock(&priv->vif_lock);
-+ }
-+ /* TODO:COMBO:
-+ * Find next interface based on TX bitmap announced by the FW
-+ * Find next interface based on load balancing */
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ } else {
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, 0);
-+ }
-+
-+ return priv;
-+}
-+
-+static inline int get_interface_id_scanning(struct xradio_common *hw_priv)
-+{
-+ if (hw_priv->scan.req || hw_priv->scan.direct_probe)
-+ return hw_priv->scan.if_id;
-+ else
-+ return -1;
-+}
-diff --git a/drivers/net/wireless/xradio/wsm.h b/drivers/net/wireless/xradio/wsm.h
-new file mode 100644
-index 0000000..8056abc
---- /dev/null
-+++ b/drivers/net/wireless/xradio/wsm.h
-@@ -0,0 +1,2354 @@
-+/*
-+ * wsm interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_WSM_H_INCLUDED
-+#define XRADIO_WSM_H_INCLUDED
-+
-+#include
-+
-+struct xradio_common;
-+
-+/* Bands */
-+/* Radio band 2.412 -2.484 GHz. */
-+#define WSM_PHY_BAND_2_4G (0)
-+
-+/* Radio band 4.9375-5.8250 GHz. */
-+#define WSM_PHY_BAND_5G (1)
-+
-+/* Transmit rates */
-+/* 1 Mbps ERP-DSSS */
-+#define WSM_TRANSMIT_RATE_1 (0)
-+
-+/* 2 Mbps ERP-DSSS */
-+#define WSM_TRANSMIT_RATE_2 (1)
-+
-+/* 5.5 Mbps ERP-CCK, ERP-PBCC (Not supported) */
-+/* #define WSM_TRANSMIT_RATE_5 (2) */
-+
-+/* 11 Mbps ERP-CCK, ERP-PBCC (Not supported) */
-+/* #define WSM_TRANSMIT_RATE_11 (3) */
-+
-+/* 22 Mbps ERP-PBCC (Not supported) */
-+/* #define WSM_TRANSMIT_RATE_22 (4) */
-+
-+/* 33 Mbps ERP-PBCC (Not supported) */
-+/* #define WSM_TRANSMIT_RATE_33 (5) */
-+
-+/* 6 Mbps (3 Mbps) ERP-OFDM, BPSK coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_6 (6)
-+
-+/* 9 Mbps (4.5 Mbps) ERP-OFDM, BPSK coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_9 (7)
-+
-+/* 12 Mbps (6 Mbps) ERP-OFDM, QPSK coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_12 (8)
-+
-+/* 18 Mbps (9 Mbps) ERP-OFDM, QPSK coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_18 (9)
-+
-+/* 24 Mbps (12 Mbps) ERP-OFDM, 16QAM coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_24 (10)
-+
-+/* 36 Mbps (18 Mbps) ERP-OFDM, 16QAM coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_36 (11)
-+
-+/* 48 Mbps (24 Mbps) ERP-OFDM, 64QAM coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_48 (12)
-+
-+/* 54 Mbps (27 Mbps) ERP-OFDM, 64QAM coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_54 (13)
-+
-+/* 6.5 Mbps HT-OFDM, BPSK coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_HT_6 (14)
-+
-+/* 13 Mbps HT-OFDM, QPSK coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_HT_13 (15)
-+
-+/* 19.5 Mbps HT-OFDM, QPSK coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_HT_19 (16)
-+
-+/* 26 Mbps HT-OFDM, 16QAM coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_HT_26 (17)
-+
-+/* 39 Mbps HT-OFDM, 16QAM coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_HT_39 (18)
-+
-+/* 52 Mbps HT-OFDM, 64QAM coding rate 2/3 */
-+#define WSM_TRANSMIT_RATE_HT_52 (19)
-+
-+/* 58.5 Mbps HT-OFDM, 64QAM coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_HT_58 (20)
-+
-+/* 65 Mbps HT-OFDM, 64QAM coding rate 5/6 */
-+#define WSM_TRANSMIT_RATE_HT_65 (21)
-+
-+/* Scan types */
-+/* Foreground scan */
-+#define WSM_SCAN_TYPE_FOREGROUND (0)
-+
-+/* Background scan */
-+#define WSM_SCAN_TYPE_BACKGROUND (1)
-+
-+/* Auto scan */
-+#define WSM_SCAN_TYPE_AUTO (2)
-+
-+/* Scan flags */
-+/* Forced background scan means if the station cannot */
-+/* enter the power-save mode, it shall force to perform a */
-+/* background scan. Only valid when ScanType is */
-+/* background scan. */
-+#define WSM_SCAN_FLAG_FORCE_BACKGROUND (BIT(0))
-+
-+/* The WLAN device scans one channel at a time so */
-+/* that disturbance to the data traffic is minimized. */
-+#define WSM_SCAN_FLAG_SPLIT_METHOD (BIT(1))
-+
-+/* Preamble Type. Long if not set. */
-+#define WSM_SCAN_FLAG_SHORT_PREAMBLE (BIT(2))
-+
-+/* 11n Tx Mode. Mixed if not set. */
-+#define WSM_SCAN_FLAG_11N_GREENFIELD (BIT(3))
-+
-+#define WSM_FLAG_MAC_INSTANCE_1 (BIT(4))
-+
-+#define WSM_FLAG_MAC_INSTANCE_0 (~(BIT(4)))
-+
-+/* Scan constraints */
-+/* Maximum number of channels to be scanned. */
-+#define WSM_SCAN_MAX_NUM_OF_CHANNELS (48)
-+
-+/* The maximum number of SSIDs that the device can scan for. */
-+#define WSM_SCAN_MAX_NUM_OF_SSIDS (2)
-+
-+/* Power management modes */
-+/* 802.11 Active mode */
-+#define WSM_PSM_ACTIVE (0)
-+
-+/* 802.11 PS mode */
-+#define WSM_PSM_PS BIT(0)
-+
-+/* Fast Power Save bit */
-+#define WSM_PSM_FAST_PS_FLAG BIT(7)
-+
-+/* Dynamic aka Fast power save */
-+#define WSM_PSM_FAST_PS (BIT(0) | BIT(7))
-+
-+/* Undetermined */
-+/* Note : Undetermined status is reported when the */
-+/* NULL data frame used to advertise the PM mode to */
-+/* the AP at Pre or Post Background Scan is not Acknowledged */
-+#define WSM_PSM_UNKNOWN BIT(1)
-+
-+/* Queue IDs */
-+/* best effort/legacy */
-+#define WSM_QUEUE_BEST_EFFORT (0)
-+
-+/* background */
-+#define WSM_QUEUE_BACKGROUND (1)
-+
-+/* video */
-+#define WSM_QUEUE_VIDEO (2)
-+
-+/* voice */
-+#define WSM_QUEUE_VOICE (3)
-+
-+/* HT TX parameters */
-+/* Non-HT */
-+#define WSM_HT_TX_NON_HT (0)
-+
-+/* Mixed format */
-+#define WSM_HT_TX_MIXED (1)
-+
-+/* Greenfield format */
-+#define WSM_HT_TX_GREENFIELD (2)
-+
-+/* STBC allowed */
-+#define WSM_HT_TX_STBC (BIT(7))
-+
-+/* EPTA prioirty flags for BT Coex */
-+/* default epta priority */
-+#define WSM_EPTA_PRIORITY_DEFAULT 4
-+/* use for normal data */
-+#define WSM_EPTA_PRIORITY_DATA 4
-+/* use for connect/disconnect/roaming*/
-+#define WSM_EPTA_PRIORITY_MGT 5
-+/* use for action frames */
-+#define WSM_EPTA_PRIORITY_ACTION 5
-+/* use for AC_VI data */
-+#define WSM_EPTA_PRIORITY_VIDEO 5
-+/* use for AC_VO data */
-+#define WSM_EPTA_PRIORITY_VOICE 6
-+/* use for EAPOL exchange */
-+#define WSM_EPTA_PRIORITY_EAPOL 7
-+
-+/* TX status */
-+/* Frame was sent aggregated */
-+/* Only valid for WSM_SUCCESS status. */
-+#define WSM_TX_STATUS_AGGREGATION (BIT(0))
-+
-+/* Host should requeue this frame later. */
-+/* Valid only when status is WSM_REQUEUE. */
-+#define WSM_TX_STATUS_REQUEUE (BIT(1))
-+
-+/* Normal Ack */
-+#define WSM_TX_STATUS_NORMAL_ACK (0<<2)
-+
-+/* No Ack */
-+#define WSM_TX_STATUS_NO_ACK (1<<2)
-+
-+/* No explicit acknowledgement */
-+#define WSM_TX_STATUS_NO_EXPLICIT_ACK (2<<2)
-+
-+/* Block Ack */
-+/* Only valid for WSM_SUCCESS status. */
-+#define WSM_TX_STATUS_BLOCK_ACK (3<<2)
-+
-+/* RX status */
-+/* Unencrypted */
-+#define WSM_RX_STATUS_UNENCRYPTED (0<<0)
-+
-+/* WEP */
-+#define WSM_RX_STATUS_WEP (1<<0)
-+
-+/* TKIP */
-+#define WSM_RX_STATUS_TKIP (2<<0)
-+
-+/* AES */
-+#define WSM_RX_STATUS_AES (3<<0)
-+
-+/* WAPI */
-+#define WSM_RX_STATUS_WAPI (4<<0)
-+
-+/* Macro to fetch encryption subfield. */
-+#define WSM_RX_STATUS_ENCRYPTION(status) ((status) & 0x07)
-+
-+/* Frame was part of an aggregation */
-+#define WSM_RX_STATUS_AGGREGATE (BIT(3))
-+
-+/* Frame was first in the aggregation */
-+#define WSM_RX_STATUS_AGGREGATE_FIRST (BIT(4))
-+
-+/* Frame was last in the aggregation */
-+#define WSM_RX_STATUS_AGGREGATE_LAST (BIT(5))
-+
-+/* Indicates a defragmented frame */
-+#define WSM_RX_STATUS_DEFRAGMENTED (BIT(6))
-+
-+/* Indicates a Beacon frame */
-+#define WSM_RX_STATUS_BEACON (BIT(7))
-+
-+/* Indicates STA bit beacon TIM field */
-+#define WSM_RX_STATUS_TIM (BIT(8))
-+
-+/* Indicates Beacon frame's virtual bitmap contains multicast bit */
-+#define WSM_RX_STATUS_MULTICAST (BIT(9))
-+
-+/* Indicates frame contains a matching SSID */
-+#define WSM_RX_STATUS_MATCHING_SSID (BIT(10))
-+
-+/* Indicates frame contains a matching BSSI */
-+#define WSM_RX_STATUS_MATCHING_BSSI (BIT(11))
-+
-+/* Indicates More bit set in Framectl field */
-+#define WSM_RX_STATUS_MORE_DATA (BIT(12))
-+
-+/* Indicates frame received during a measurement process */
-+#define WSM_RX_STATUS_MEASUREMENT (BIT(13))
-+
-+/* Indicates frame received as an HT packet */
-+#define WSM_RX_STATUS_HT (BIT(14))
-+
-+/* Indicates frame received with STBC */
-+#define WSM_RX_STATUS_STBC (BIT(15))
-+
-+/* Indicates Address 1 field matches dot11StationId */
-+#define WSM_RX_STATUS_ADDRESS1 (BIT(16))
-+
-+/* Indicates Group address present in the Address 1 field */
-+#define WSM_RX_STATUS_GROUP (BIT(17))
-+
-+/* Indicates Broadcast address present in the Address 1 field */
-+#define WSM_RX_STATUS_BROADCAST (BIT(18))
-+
-+/* Indicates group key used with encrypted frames */
-+#define WSM_RX_STATUS_GROUP_KEY (BIT(19))
-+
-+/* Macro to fetch encryption key index. */
-+#define WSM_RX_STATUS_KEY_IDX(status) (((status >> 20)) & 0x0F)
-+
-+/* Frame Control field starts at Frame offset + 2 */
-+#define WSM_TX_2BYTES_SHIFT (BIT(7))
-+
-+/* Join mode */
-+/* IBSS */
-+#define WSM_JOIN_MODE_IBSS (0)
-+
-+/* BSS */
-+#define WSM_JOIN_MODE_BSS (1)
-+
-+/* PLCP preamble type */
-+/* For long preamble */
-+#define WSM_JOIN_PREAMBLE_LONG (0)
-+
-+/* For short preamble (Long for 1Mbps) */
-+#define WSM_JOIN_PREAMBLE_SHORT (1)
-+
-+/* For short preamble (Long for 1 and 2Mbps) */
-+#define WSM_JOIN_PREAMBLE_SHORT_2 (2)
-+
-+/* Join flags */
-+/* Unsynchronized */
-+#define WSM_JOIN_FLAGS_UNSYNCRONIZED BIT(0)
-+/* The BSS owner is a P2P GO */
-+#define WSM_JOIN_FLAGS_P2P_GO BIT(1)
-+/* Force to join BSS with the BSSID and the
-+ * SSID specified without waiting for beacons. The
-+ * ProbeForJoin parameter is ignored. */
-+#define WSM_JOIN_FLAGS_FORCE BIT(2)
-+/* Give probe request/response higher
-+ * priority over the BT traffic */
-+#define WSM_JOIN_FLAGS_PRIO BIT(3)
-+
-+/* Key types */
-+#define WSM_KEY_TYPE_WEP_DEFAULT (0)
-+#define WSM_KEY_TYPE_WEP_PAIRWISE (1)
-+#define WSM_KEY_TYPE_TKIP_GROUP (2)
-+#define WSM_KEY_TYPE_TKIP_PAIRWISE (3)
-+#define WSM_KEY_TYPE_AES_GROUP (4)
-+#define WSM_KEY_TYPE_AES_PAIRWISE (5)
-+#define WSM_KEY_TYPE_WAPI_GROUP (6)
-+#define WSM_KEY_TYPE_WAPI_PAIRWISE (7)
-+
-+/* Key indexes */
-+#define WSM_KEY_MAX_INDEX (10)
-+
-+/* ACK policy */
-+#define WSM_ACK_POLICY_NORMAL (0)
-+#define WSM_ACK_POLICY_NO_ACK (1)
-+
-+/* Start modes */
-+#define WSM_START_MODE_AP (0) /* Mini AP */
-+#define WSM_START_MODE_P2P_GO (1) /* P2P GO */
-+#define WSM_START_MODE_P2P_DEV (2) /* P2P device */
-+
-+/* SetAssociationMode MIB flags */
-+#define WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE (BIT(0))
-+#define WSM_ASSOCIATION_MODE_USE_HT_MODE (BIT(1))
-+#define WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET (BIT(2))
-+#define WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING (BIT(3))
-+#define WSM_ASSOCIATION_MODE_SNOOP_ASSOC_FRAMES (BIT(4))
-+
-+/* RcpiRssiThreshold MIB flags */
-+#define WSM_RCPI_RSSI_THRESHOLD_ENABLE (BIT(0))
-+#define WSM_RCPI_RSSI_USE_RSSI (BIT(1))
-+#define WSM_RCPI_RSSI_DONT_USE_UPPER (BIT(2))
-+#define WSM_RCPI_RSSI_DONT_USE_LOWER (BIT(3))
-+
-+/* Update-ie constants */
-+#define WSM_UPDATE_IE_BEACON (BIT(0))
-+#define WSM_UPDATE_IE_PROBE_RESP (BIT(1))
-+#define WSM_UPDATE_IE_PROBE_REQ (BIT(2))
-+
-+/* WSM events */
-+/* Error */
-+#define WSM_EVENT_ERROR (0)
-+
-+/* BSS lost */
-+#define WSM_EVENT_BSS_LOST (1)
-+
-+/* BSS regained */
-+#define WSM_EVENT_BSS_REGAINED (2)
-+
-+/* Radar detected */
-+#define WSM_EVENT_RADAR_DETECTED (3)
-+
-+/* RCPI or RSSI threshold triggered */
-+#define WSM_EVENT_RCPI_RSSI (4)
-+
-+/* BT inactive */
-+#define WSM_EVENT_BT_INACTIVE (5)
-+
-+/* BT active */
-+#define WSM_EVENT_BT_ACTIVE (6)
-+
-+#define WSM_EVENT_PS_MODE_ERROR (7)
-+
-+#define WSM_EVENT_INACTIVITY (9)
-+
-+/* MAC Addr Filter */
-+#define WSM_MIB_ID_MAC_ADDR_FILTER 0x1030
-+
-+/* MIB IDs */
-+/* 4.1 dot11StationId */
-+#define WSM_MIB_ID_DOT11_STATION_ID 0x0000
-+
-+/* 4.2 dot11MaxtransmitMsduLifeTime */
-+#define WSM_MIB_ID_DOT11_MAX_TRANSMIT_LIFTIME 0x0001
-+
-+/* 4.3 dot11MaxReceiveLifeTime */
-+#define WSM_MIB_ID_DOT11_MAX_RECEIVE_LIFETIME 0x0002
-+
-+/* 4.4 dot11SlotTime */
-+#define WSM_MIB_ID_DOT11_SLOT_TIME 0x0003
-+
-+/* 4.5 dot11GroupAddressesTable */
-+#define WSM_MIB_ID_DOT11_GROUP_ADDRESSES_TABLE 0x0004
-+#define WSM_MAX_GRP_ADDRTABLE_ENTRIES 8
-+
-+/* 4.6 dot11WepDefaultKeyId */
-+#define WSM_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID 0x0005
-+
-+/* 4.7 dot11CurrentTxPowerLevel */
-+#define WSM_MIB_ID_DOT11_CURRENT_TX_POWER_LEVEL 0x0006
-+
-+/* 4.8 dot11RTSThreshold */
-+#define WSM_MIB_ID_DOT11_RTS_THRESHOLD 0x0007
-+
-+/* Huanglu add for firmware debug control */
-+#define WSM_MIB_ID_FW_DEBUG_CONTROL 0x0008
-+
-+/* yangfh add for read/write registers from firmware*/
-+#define WSM_MIB_ID_RW_FW_REG 0x0009
-+
-+/* yangfh add for Set max number of mpdus in a-mpdu*/
-+#define WSM_MIB_ID_SET_AMPDU_NUM 0x000a
-+
-+/* Huanglu add for tx-ampdu-len-adaption */
-+#define WSM_MIB_ID_SET_TALA_PARA 0x000b
-+
-+/* yangfh add for set TPA param */
-+#define WSM_MIB_ID_SET_TPA_PARAM 0x000c
-+
-+/* 4.9 NonErpProtection */
-+#define WSM_MIB_ID_NON_ERP_PROTECTION 0x1000
-+
-+/* 4.10 ArpIpAddressesTable */
-+#define WSM_MIB_ID_ARP_IP_ADDRESSES_TABLE 0x1001
-+#define WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES 1
-+
-+/* 4.11 TemplateFrame */
-+#define WSM_MIB_ID_TEMPLATE_FRAME 0x1002
-+
-+/* 4.12 RxFilter */
-+#define WSM_MIB_ID_RX_FILTER 0x1003
-+
-+/* 4.13 BeaconFilterTable */
-+#define WSM_MIB_ID_BEACON_FILTER_TABLE 0x1004
-+
-+/* 4.14 BeaconFilterEnable */
-+#define WSM_MIB_ID_BEACON_FILTER_ENABLE 0x1005
-+
-+/* 4.15 OperationalPowerMode */
-+#define WSM_MIB_ID_OPERATIONAL_POWER_MODE 0x1006
-+
-+/* 4.16 BeaconWakeUpPeriod */
-+#define WSM_MIB_ID_BEACON_WAKEUP_PERIOD 0x1007
-+
-+/* 4.17 RcpiRssiThreshold */
-+#define WSM_MIB_ID_RCPI_RSSI_THRESHOLD 0x1009
-+
-+/* 4.18 StatisticsTable */
-+#define WSM_MIB_ID_STATISTICS_TABLE 0x100A
-+
-+/* 4.19 IbssPsConfig */
-+#define WSM_MIB_ID_IBSS_PS_CONFIG 0x100B
-+
-+/* 4.20 CountersTable */
-+#define WSM_MIB_ID_COUNTERS_TABLE 0x100C
-+#define WSM_MIB_ID_AMPDUCOUNTERS_TABLE 0x1036
-+#define WSM_MIB_ID_TXPIPE_TABLE 0x1037
-+#define WSM_MIB_ID_BACKOFF_DBG 0x1038
-+#define WSM_MIB_ID_BACKOFF_CTRL 0x1039
-+
-+//add yangfh for requery packet status
-+#define WSM_MIB_ID_REQ_PKT_STATUS 0x1040
-+
-+//add yangfh for TPA debug informations
-+#define WSM_MIB_ID_TPA_DEBUG_INFO 0x1041
-+
-+//add yangfh for tx power informations
-+#define WSM_MIB_ID_TX_POWER_INFO 0x1042
-+
-+//add yangfh for some hardware information
-+#define WSM_MIB_ID_HW_INFO 0x1043
-+
-+/* 4.21 BlockAckPolicy */
-+#define WSM_MIB_ID_BLOCK_ACK_POLICY 0x100E
-+
-+/* 4.22 OverrideInternalTxRate */
-+#define WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE 0x100F
-+
-+/* 4.23 SetAssociationMode */
-+#define WSM_MIB_ID_SET_ASSOCIATION_MODE 0x1010
-+
-+/* 4.24 UpdateEptaConfigData */
-+#define WSM_MIB_ID_UPDATE_EPTA_CONFIG_DATA 0x1011
-+
-+/* 4.25 SelectCcaMethod */
-+#define WSM_MIB_ID_SELECT_CCA_METHOD 0x1012
-+
-+/* 4.26 SetUpasdInformation */
-+#define WSM_MIB_ID_SET_UAPSD_INFORMATION 0x1013
-+
-+/* 4.27 SetAutoCalibrationMode WBF00004073 */
-+#define WSM_MIB_ID_SET_AUTO_CALIBRATION_MODE 0x1015
-+
-+/* 4.28 SetTxRateRetryPolicy */
-+#define WSM_MIB_ID_SET_TX_RATE_RETRY_POLICY 0x1016
-+
-+/* 4.29 SetHostMessageTypeFilter */
-+#define WSM_MIB_ID_SET_HOST_MSG_TYPE_FILTER 0x1017
-+
-+/* 4.30 P2PFindInfo */
-+#define WSM_MIB_ID_P2P_FIND_INFO 0x1018
-+
-+/* 4.31 P2PPsModeInfo */
-+#define WSM_MIB_ID_P2P_PS_MODE_INFO 0x1019
-+
-+/* 4.32 SetEtherTypeDataFrameFilter */
-+#define WSM_MIB_ID_SET_ETHERTYPE_DATAFRAME_FILTER 0x101A
-+
-+/* 4.33 SetUDPPortDataFrameFilter */
-+#define WSM_MIB_ID_SET_UDPPORT_DATAFRAME_FILTER 0x101B
-+
-+/* 4.34 SetMagicDataFrameFilter */
-+#define WSM_MIB_ID_SET_MAGIC_DATAFRAME_FILTER 0x101C
-+#define WSM_MIB_ID_SET_HOST_SLEEP 0x1050
-+
-+/* This is the end of specification. */
-+
-+/* 4.35 P2PDeviceInfo */
-+#define WSM_MIB_ID_P2P_DEVICE_INFO 0x101D
-+
-+/* 4.36 SetWCDMABand */
-+#define WSM_MIB_ID_SET_WCDMA_BAND 0x101E
-+
-+/* 4.37 GroupTxSequenceCounter */
-+#define WSM_MIB_ID_GRP_SEQ_COUNTER 0x101F
-+
-+/* 4.38 ProtectedMgmtPolicy */
-+#define WSM_MIB_ID_PROTECTED_MGMT_POLICY 0x1020
-+
-+/* 4.39 SetHtProtection */
-+#define WSM_MID_ID_SET_HT_PROTECTION 0x1021
-+
-+/* 4.40 GPIO Command */
-+#define WSM_MIB_ID_GPIO_COMMAND 0x1022
-+
-+/* 4.41 TSF Counter Value */
-+#define WSM_MIB_ID_TSF_COUNTER 0x1023
-+
-+/* Test Purposes Only */
-+#define WSM_MIB_ID_BLOCK_ACK_INFO 0x100D
-+
-+/* 4.42 UseMultiTxConfMessage */
-+#define WSM_MIB_USE_MULTI_TX_CONF 0x1024
-+
-+/* 4.43 Keep-alive period */
-+#define WSM_MIB_ID_KEEP_ALIVE_PERIOD 0x1025
-+
-+/* 4.44 Disable BSSID filter */
-+#define WSM_MIB_ID_DISABLE_BSSID_FILTER 0x1026
-+
-+/* Inactivity */
-+#define WSM_MIB_ID_SET_INACTIVITY 0x1035
-+
-+/* MAC Addr Filter */
-+#define WSM_MIB_ID_MAC_ADDR_FILTER 0x1030
-+
-+#ifdef MCAST_FWDING
-+/* 4.51 Set Forwarding Offload */
-+#define WSM_MIB_ID_FORWARDING_OFFLOAD 0x1033
-+#endif
-+
-+/* Frame template types */
-+#define WSM_FRAME_TYPE_PROBE_REQUEST (0)
-+#define WSM_FRAME_TYPE_BEACON (1)
-+#define WSM_FRAME_TYPE_NULL (2)
-+#define WSM_FRAME_TYPE_QOS_NULL (3)
-+#define WSM_FRAME_TYPE_PS_POLL (4)
-+#define WSM_FRAME_TYPE_PROBE_RESPONSE (5)
-+#define WSM_FRAME_TYPE_ARP_REPLY (6)
-+
-+#define WSM_FRAME_GREENFIELD (0x80) /* See 4.11 */
-+
-+/* Status */
-+/* The WSM firmware has completed a request */
-+/* successfully. */
-+#define WSM_STATUS_SUCCESS (0)
-+
-+/* This is a generic failure code if other error codes do */
-+/* not apply. */
-+#define WSM_STATUS_FAILURE (1)
-+
-+/* A request contains one or more invalid parameters. */
-+#define WSM_INVALID_PARAMETER (2)
-+
-+/* The request cannot perform because the device is in */
-+/* an inappropriate mode. */
-+#define WSM_ACCESS_DENIED (3)
-+
-+/* The frame received includes a decryption error. */
-+#define WSM_STATUS_DECRYPTFAILURE (4)
-+
-+/* A MIC failure is detected in the received packets. */
-+#define WSM_STATUS_MICFAILURE (5)
-+
-+/* The transmit request failed due to retry limit being */
-+/* exceeded. */
-+#define WSM_STATUS_RETRY_EXCEEDED (6)
-+
-+/* The transmit request failed due to MSDU life time */
-+/* being exceeded. */
-+#define WSM_STATUS_TX_LIFETIME_EXCEEDED (7)
-+
-+/* The link to the AP is lost. */
-+#define WSM_STATUS_LINK_LOST (8)
-+
-+/* No key was found for the encrypted frame */
-+#define WSM_STATUS_NO_KEY_FOUND (9)
-+
-+/* Jammer was detected when transmitting this frame */
-+#define WSM_STATUS_JAMMER_DETECTED (10)
-+
-+/* The message should be requeued later. */
-+/* This is applicable only to Transmit */
-+#define WSM_REQUEUE (11)
-+
-+/* Advanced filtering options */
-+#define WSM_MAX_FILTER_ELEMENTS (4)
-+
-+#define WSM_FILTER_ACTION_IGNORE (0)
-+#define WSM_FILTER_ACTION_FILTER_IN (1)
-+#define WSM_FILTER_ACTION_FILTER_OUT (2)
-+
-+#define WSM_FILTER_PORT_TYPE_DST (0)
-+#define WSM_FILTER_PORT_TYPE_SRC (1)
-+
-+
-+
-+struct wsm_hdr {
-+ __le16 len;
-+ __le16 id;
-+};
-+
-+#define WSM_TX_SEQ_MAX (7)
-+#define WSM_TX_SEQ(seq) \
-+ ((seq & WSM_TX_SEQ_MAX) << 13)
-+#define WSM_TX_LINK_ID_MAX (0x0F)
-+#define WSM_TX_LINK_ID(link_id) \
-+ ((link_id & WSM_TX_LINK_ID_MAX) << 6)
-+
-+#define WSM_TX_IF_ID_MAX (0x0F)
-+#define WSM_TX_IF_ID(if_id) \
-+ ((if_id & WSM_TX_IF_ID_MAX) << 6)
-+
-+#define MAX_BEACON_SKIP_TIME_MS 1000
-+
-+#ifdef FPGA_SETUP
-+#define WSM_CMD_LAST_CHANCE_TIMEOUT (HZ * 9 / 2)
-+#else
-+#define WSM_CMD_LAST_CHANCE_TIMEOUT (HZ * 20 / 2)
-+#endif
-+#define WSM_CMD_EXTENDED_TIMEOUT (HZ * 20 / 2)
-+
-+#define WSM_RI_GET_PEER_ID_FROM_FLAGS(_f) (((_f)&(0xF<<25)>>25))
-+
-+
-+/* ******************************************************************** */
-+/* WSM capcbility */
-+#define WSM_FW_LABEL 128
-+struct wsm_caps {
-+ u16 numInpChBufs;
-+ u16 sizeInpChBuf;
-+ u16 hardwareId;
-+ u16 hardwareSubId;
-+ u16 firmwareCap;
-+ u16 firmwareType;
-+ u16 firmwareApiVer;
-+ u16 firmwareBuildNumber;
-+ u16 firmwareVersion;
-+ char fw_label[WSM_FW_LABEL+2];
-+ int firmwareReady;
-+};
-+
-+/* ******************************************************************** */
-+/* WSM commands */
-+
-+struct wsm_tx_power_range {
-+ int min_power_level;
-+ int max_power_level;
-+ u32 stepping;
-+};
-+
-+/* 3.1 */
-+struct wsm_configuration {
-+ /* [in] */ u32 dot11MaxTransmitMsduLifeTime;
-+ /* [in] */ u32 dot11MaxReceiveLifeTime;
-+ /* [in] */ u32 dot11RtsThreshold;
-+ /* [in, out] */ u8 *dot11StationId;
-+ /* [in] */ const void *dpdData;
-+ /* [in] */ size_t dpdData_size;
-+ /* [out] */ u8 dot11FrequencyBandsSupported;
-+ /* [out] */ u32 supportedRateMask;
-+ /* [out] */ struct wsm_tx_power_range txPowerRange[2];
-+};
-+
-+int wsm_configuration(struct xradio_common *hw_priv,
-+ struct wsm_configuration *arg,
-+ int if_id);
-+
-+/* 3.3 */
-+struct wsm_reset {
-+ /* [in] */ int link_id;
-+ /* [in] */ bool reset_statistics;
-+};
-+
-+int wsm_reset(struct xradio_common *hw_priv, const struct wsm_reset *arg,
-+ int if_id);
-+
-+//add by yangfh
-+void wsm_query_work(struct work_struct *work);
-+
-+/* 3.5 */
-+int wsm_read_mib(struct xradio_common *hw_priv, u16 mibId, void *buf,
-+ size_t buf_size, size_t arg_size);
-+
-+/* 3.7 */
-+int wsm_write_mib(struct xradio_common *hw_priv, u16 mibId, void *buf,
-+ size_t buf_size, int if_id);
-+
-+/* 3.9 */
-+struct wsm_ssid {
-+ u8 ssid[32];
-+ u32 length;
-+};
-+
-+struct wsm_scan_ch {
-+ u16 number;
-+ u32 minChannelTime;
-+ u32 maxChannelTime;
-+ u32 txPowerLevel;
-+};
-+
-+/* 3.13 */
-+struct wsm_scan_complete {
-+ /* WSM_STATUS_... */
-+ u32 status;
-+
-+ /* WSM_PSM_... */
-+ u8 psm;
-+
-+ /* Number of channels that the scan operation completed. */
-+ u8 numChannels;
-+#ifdef ROAM_OFFLOAD
-+ u16 reserved;
-+#endif /*ROAM_OFFLOAD*/
-+};
-+
-+/* 3.9 */
-+struct wsm_scan {
-+ /* WSM_PHY_BAND_... */
-+ /* [in] */ u8 band;
-+
-+ /* WSM_SCAN_TYPE_... */
-+ /* [in] */ u8 scanType;
-+
-+ /* WSM_SCAN_FLAG_... */
-+ /* [in] */ u8 scanFlags;
-+
-+ /* WSM_TRANSMIT_RATE_... */
-+ /* [in] */ u8 maxTransmitRate;
-+
-+ /* Interval period in TUs that the device shall the re- */
-+ /* execute the requested scan. Max value supported by the device */
-+ /* is 256s. */
-+ /* [in] */ u32 autoScanInterval;
-+
-+ /* Number of probe requests (per SSID) sent to one (1) */
-+ /* channel. Zero (0) means that none is send, which */
-+ /* means that a passive scan is to be done. Value */
-+ /* greater than zero (0) means that an active scan is to */
-+ /* be done. */
-+ /* [in] */ u32 numOfProbeRequests;
-+
-+ /* Number of channels to be scanned. */
-+ /* Maximum value is WSM_SCAN_MAX_NUM_OF_CHANNELS. */
-+ /* [in] */ u8 numOfChannels;
-+
-+ /* Number of SSID provided in the scan command (this */
-+ /* is zero (0) in broadcast scan) */
-+ /* The maximum number of SSIDs is WSM_SCAN_MAX_NUM_OF_SSIDS. */
-+ /* [in] */ u8 numOfSSIDs;
-+
-+ /* The delay time (in microseconds) period */
-+ /* before sending a probe-request. */
-+ /* [in] */ u8 probeDelay;
-+
-+ /* SSIDs to be scanned [numOfSSIDs]; */
-+ /* [in] */ struct wsm_ssid *ssids;
-+
-+ /* Channels to be scanned [numOfChannels]; */
-+ /* [in] */ struct wsm_scan_ch *ch;
-+};
-+
-+int wsm_scan(struct xradio_common *hw_priv, const struct wsm_scan *arg,
-+ int if_id);
-+
-+/* 3.11 */
-+int wsm_stop_scan(struct xradio_common *hw_priv, int if_id);
-+
-+/* 3.14 */
-+struct wsm_tx_confirm {
-+ /* Packet identifier used in wsm_tx. */
-+ /* [out] */ u32 packetID;
-+
-+ /* WSM_STATUS_... */
-+ /* [out] */ u32 status;
-+
-+ /* WSM_TRANSMIT_RATE_... */
-+ /* [out] */ u8 txedRate;
-+
-+ /* The number of times the frame was transmitted */
-+ /* without receiving an acknowledgement. */
-+ /* [out] */ u8 ackFailures;
-+
-+ /* WSM_TX_STATUS_... */
-+ /* [out] */ u16 flags;
-+
-+ //rate feed back, add by yangfh
-+ /* [out] */ u32 rate_try[3];
-+
-+ /* The total time in microseconds that the frame spent in */
-+ /* the WLAN device before transmission as completed. */
-+ /* [out] */ u32 mediaDelay;
-+
-+ /* The total time in microseconds that the frame spent in */
-+ /* the WLAN device before transmission was started. */
-+ /* [out] */ u32 txQueueDelay;
-+
-+ /* [out]*/ u32 link_id;
-+
-+ /*[out]*/ int if_id;
-+};
-+
-+/* 3.15 */
-+
-+/* Note that ideology of wsm_tx struct is different against the rest of
-+ * WSM API. wsm_hdr is /not/ a caller-adapted struct to be used as an input
-+ * argument for WSM call, but a prepared bytestream to be sent to firmware.
-+ * It is filled partly in xradio_tx, partly in low-level WSM code.
-+ * Please pay attention once again: ideology is different.
-+ *
-+ * Legend:
-+ * - [in]: xradio_tx must fill this field.
-+ * - [wsm]: the field is filled by low-level WSM.
-+ */
-+struct wsm_tx {
-+ /* common WSM header */
-+ /* [in/wsm] */ struct wsm_hdr hdr;
-+
-+ /* Packet identifier that meant to be used in completion. */
-+ /* [in] */ __le32 packetID;
-+
-+ /* WSM_TRANSMIT_RATE_... */
-+ /* [in] */ u8 maxTxRate;
-+
-+ /* WSM_QUEUE_... */
-+ /* [in] */ u8 queueId;
-+
-+ /* True: another packet is pending on the host for transmission. */
-+ /* [wsm] */ u8 more;
-+
-+ /* Bit 0 = 0 - Start expiry time from first Tx attempt (default) */
-+ /* Bit 0 = 1 - Start expiry time from receipt of Tx Request */
-+ /* Bits 3:1 - PTA Priority */
-+ /* Bits 6:4 - Tx Rate Retry Policy */
-+ /* Bit 7 - Reserved */
-+ /* [in] */ u8 flags;
-+
-+ /* Should be 0. */
-+ /* [in] */ __le32 reserved;
-+
-+ /* The elapsed time in TUs, after the initial transmission */
-+ /* of an MSDU, after which further attempts to transmit */
-+ /* the MSDU shall be terminated. Overrides the global */
-+ /* dot11MaxTransmitMsduLifeTime setting [optional] */
-+ /* Device will set the default value if this is 0. */
-+ /* [wsm] */ __le32 expireTime;
-+
-+ /* WSM_HT_TX_... */
-+ /* [in] */ __le32 htTxParameters;
-+};
-+
-+/* = sizeof(generic hi hdr) + sizeof(wsm hdr) + sizeof(alignment) */
-+#define WSM_TX_EXTRA_HEADROOM (28)
-+
-+/* 3.16 */
-+struct wsm_rx {
-+ /* WSM_STATUS_... */
-+ /* [out] */ u32 status;
-+
-+ /* Specifies the channel of the received packet. */
-+ /* [out] */ u16 channelNumber;
-+
-+ /* WSM_TRANSMIT_RATE_... */
-+ /* [out] */ u8 rxedRate;
-+
-+ /* This value is expressed in signed Q8.0 format for */
-+ /* RSSI and unsigned Q7.1 format for RCPI. */
-+ /* [out] */ u8 rcpiRssi;
-+
-+ /* WSM_RX_STATUS_... */
-+ /* [out] */ u32 flags;
-+
-+ /* An 802.11 frame. */
-+ /* [out] */ void *frame;
-+
-+ /* Size of the frame */
-+ /* [out] */ size_t frame_size;
-+
-+ /* Link ID */
-+ /* [out] */ int link_id;
-+ /* [out] */ int if_id;
-+};
-+
-+/* = sizeof(generic hi hdr) + sizeof(wsm hdr) */
-+#define WSM_RX_EXTRA_HEADROOM (16)
-+
-+/* 3.17 */
-+struct wsm_event {
-+ /* WSM_STATUS_... */
-+ /* [out] */ u32 eventId;
-+
-+ /* Indication parameters. */
-+ /* For error indication, this shall be a 32-bit WSM status. */
-+ /* For RCPI or RSSI indication, this should be an 8-bit */
-+ /* RCPI or RSSI value. */
-+ /* [out] */ u32 eventData;
-+};
-+
-+struct xradio_wsm_event {
-+ struct list_head link;
-+ struct wsm_event evt;
-+ u8 if_id;
-+};
-+
-+/* 3.18 - 3.22 */
-+/* Measurement. Skipped for now. Irrelevent. */
-+
-+
-+/* 3.23 */
-+struct wsm_join {
-+ /* WSM_JOIN_MODE_... */
-+ /* [in] */ u8 mode;
-+
-+ /* WSM_PHY_BAND_... */
-+ /* [in] */ u8 band;
-+
-+ /* Specifies the channel number to join. The channel */
-+ /* number will be mapped to an actual frequency */
-+ /* according to the band */
-+ /* [in] */ u16 channelNumber;
-+
-+ /* Specifies the BSSID of the BSS or IBSS to be joined */
-+ /* or the IBSS to be started. */
-+ /* [in] */ u8 bssid[6];
-+
-+ /* ATIM window of IBSS */
-+ /* When ATIM window is zero the initiated IBSS does */
-+ /* not support power saving. */
-+ /* [in] */ u16 atimWindow;
-+
-+ /* WSM_JOIN_PREAMBLE_... */
-+ /* [in] */ u8 preambleType;
-+
-+ /* Specifies if a probe request should be send with the */
-+ /* specified SSID when joining to the network. */
-+ /* [in] */ u8 probeForJoin;
-+
-+ /* DTIM Period (In multiples of beacon interval) */
-+ /* [in] */ u8 dtimPeriod;
-+
-+ /* WSM_JOIN_FLAGS_... */
-+ /* [in] */ u8 flags;
-+
-+ /* Length of the SSID */
-+ /* [in] */ u32 ssidLength;
-+
-+ /* Specifies the SSID of the IBSS to join or start */
-+ /* [in] */ u8 ssid[32];
-+
-+ /* Specifies the time between TBTTs in TUs */
-+ /* [in] */ u32 beaconInterval;
-+
-+ /* A bit mask that defines the BSS basic rate set. */
-+ /* [in] */ u32 basicRateSet;
-+
-+ /* Minimum transmission power level in units of 0.1dBm */
-+ /* [out] */ int minPowerLevel;
-+
-+ /* Maximum transmission power level in units of 0.1dBm */
-+ /* [out] */ int maxPowerLevel;
-+};
-+
-+int wsm_join(struct xradio_common *hw_priv, struct wsm_join *arg, int if_id);
-+
-+/* 3.25 */
-+struct wsm_set_pm {
-+ /* WSM_PSM_... */
-+ /* [in] */ u8 pmMode;
-+
-+ /* in unit of 500us; 0 to use default */
-+ /* [in] */ u8 fastPsmIdlePeriod;
-+
-+ /* in unit of 500us; 0 to use default */
-+ /* [in] */ u8 apPsmChangePeriod;
-+
-+ /* in unit of 500us; 0 to disable auto-pspoll */
-+ /* [in] */ u8 minAutoPsPollPeriod;
-+};
-+
-+int wsm_set_pm(struct xradio_common *hw_priv, const struct wsm_set_pm *arg,
-+ int if_id);
-+
-+/* 3.27 */
-+struct wsm_set_pm_complete {
-+ u8 psm; /* WSM_PSM_... */
-+};
-+
-+/* 3.28 */
-+struct wsm_set_bss_params {
-+ /* The number of lost consecutive beacons after which */
-+ /* the WLAN device should indicate the BSS-Lost event */
-+ /* to the WLAN host driver. */
-+ u8 beaconLostCount;
-+
-+ /* The AID received during the association process. */
-+ u16 aid;
-+
-+ /* The operational rate set mask */
-+ u32 operationalRateSet;
-+};
-+
-+int wsm_set_bss_params(struct xradio_common *hw_priv,
-+ const struct wsm_set_bss_params *arg, int if_id);
-+
-+/* 3.30 */
-+struct wsm_add_key {
-+ u8 type; /* WSM_KEY_TYPE_... */
-+ u8 entryIndex; /* Key entry index: 0 -- WSM_KEY_MAX_INDEX */
-+ u16 reserved;
-+ union {
-+ struct {
-+ u8 peerAddress[6]; /* MAC address of the
-+ * peer station */
-+ u8 reserved;
-+ u8 keyLength; /* Key length in bytes */
-+ u8 keyData[16]; /* Key data */
-+ } __packed wepPairwiseKey;
-+ struct {
-+ u8 keyId; /* Unique per key identifier
-+ * (0..3) */
-+ u8 keyLength; /* Key length in bytes */
-+ u16 reserved;
-+ u8 keyData[16]; /* Key data */
-+ } __packed wepGroupKey;
-+ struct {
-+ u8 peerAddress[6]; /* MAC address of the
-+ * peer station */
-+ u8 reserved[2];
-+ u8 tkipKeyData[16]; /* TKIP key data */
-+ u8 rxMicKey[8]; /* Rx MIC key */
-+ u8 txMicKey[8]; /* Tx MIC key */
-+ } __packed tkipPairwiseKey;
-+ struct {
-+ u8 tkipKeyData[16]; /* TKIP key data */
-+ u8 rxMicKey[8]; /* Rx MIC key */
-+ u8 keyId; /* Key ID */
-+ u8 reserved[3];
-+ u8 rxSeqCounter[8]; /* Receive Sequence Counter */
-+ } __packed tkipGroupKey;
-+ struct {
-+ u8 peerAddress[6]; /* MAC address of the
-+ * peer station */
-+ u16 reserved;
-+ u8 aesKeyData[16]; /* AES key data */
-+ } __packed aesPairwiseKey;
-+ struct {
-+ u8 aesKeyData[16]; /* AES key data */
-+ u8 keyId; /* Key ID */
-+ u8 reserved[3];
-+ u8 rxSeqCounter[8]; /* Receive Sequence Counter */
-+ } __packed aesGroupKey;
-+ struct {
-+ u8 peerAddress[6]; /* MAC address of the
-+ * peer station */
-+ u8 keyId; /* Key ID */
-+ u8 reserved;
-+ u8 wapiKeyData[16]; /* WAPI key data */
-+ u8 micKeyData[16]; /* MIC key data */
-+ } __packed wapiPairwiseKey;
-+ struct {
-+ u8 wapiKeyData[16]; /* WAPI key data */
-+ u8 micKeyData[16]; /* MIC key data */
-+ u8 keyId; /* Key ID */
-+ u8 reserved[3];
-+ } __packed wapiGroupKey;
-+ } __packed;
-+} __packed;
-+
-+int wsm_add_key(struct xradio_common *hw_priv, const struct wsm_add_key *arg,
-+ int if_id);
-+
-+/* 3.32 */
-+struct wsm_remove_key {
-+ /* Key entry index : 0-10 */
-+ u8 entryIndex;
-+};
-+
-+int wsm_remove_key(struct xradio_common *hw_priv,
-+ const struct wsm_remove_key *arg, int if_id);
-+
-+/* 3.34 */
-+struct wsm_set_tx_queue_params {
-+ /* WSM_ACK_POLICY_... */
-+ u8 ackPolicy;
-+
-+ /* Medium Time of TSPEC (in 32us units) allowed per */
-+ /* One Second Averaging Period for this queue. */
-+ u16 allowedMediumTime;
-+
-+ /* dot11MaxTransmitMsduLifetime to be used for the */
-+ /* specified queue. */
-+ u32 maxTransmitLifetime;
-+};
-+
-+struct wsm_tx_queue_params {
-+ /* NOTE: index is a linux queue id. */
-+ struct wsm_set_tx_queue_params params[4];
-+};
-+
-+#define WSM_TX_QUEUE_SET(queue_params, queue, ack_policy, allowed_time, \
-+ max_life_time) \
-+do { \
-+ struct wsm_set_tx_queue_params *p = &(queue_params)->params[queue]; \
-+ p->ackPolicy = (ack_policy); \
-+ p->allowedMediumTime = (allowed_time); \
-+ p->maxTransmitLifetime = (max_life_time); \
-+} while (0)
-+
-+int wsm_set_tx_queue_params(struct xradio_common *hw_priv,
-+ const struct wsm_set_tx_queue_params *arg,
-+ u8 id, int if_id);
-+
-+/* 3.36 */
-+struct wsm_edca_queue_params {
-+ /* CWmin (in slots) for the access class. */
-+ /* [in] */ u16 cwMin;
-+
-+ /* CWmax (in slots) for the access class. */
-+ /* [in] */ u16 cwMax;
-+
-+ /* AIFS (in slots) for the access class. */
-+ /* [in] */ u8 aifns;
-+
-+ /* TX OP Limit (in microseconds) for the access class. */
-+ /* [in] */ u16 txOpLimit;
-+
-+ /* dot11MaxReceiveLifetime to be used for the specified */
-+ /* the access class. Overrides the global */
-+ /* dot11MaxReceiveLifetime value */
-+ /* [in] */ u32 maxReceiveLifetime;
-+
-+ /* UAPSD trigger support for the access class. */
-+ /* [in] */ bool uapsdEnable;
-+};
-+
-+struct wsm_edca_params {
-+ /* NOTE: index is a linux queue id. */
-+ struct wsm_edca_queue_params params[4];
-+};
-+
-+#define TXOP_UNIT 32
-+#define WSM_EDCA_SET(edca, queue, aifs, cw_min, cw_max, txop, life_time,\
-+ uapsd) \
-+ do { \
-+ struct wsm_edca_queue_params *p = &(edca)->params[queue]; \
-+ p->cwMin = (cw_min); \
-+ p->cwMax = (cw_max); \
-+ p->aifns = (aifs); \
-+ p->txOpLimit = ((txop) * TXOP_UNIT); \
-+ p->maxReceiveLifetime = (life_time); \
-+ p->uapsdEnable = (uapsd); \
-+ } while (0)
-+
-+int wsm_set_edca_params(struct xradio_common *hw_priv,
-+ const struct wsm_edca_params *arg, int if_id);
-+
-+int wsm_set_uapsd_param(struct xradio_common *hw_priv,
-+ const struct wsm_edca_params *arg);
-+
-+/* 3.38 */
-+/* Set-System info. Skipped for now. Irrelevent. */
-+
-+/* 3.40 */
-+struct wsm_switch_channel {
-+ /* 1 - means the STA shall not transmit any further */
-+ /* frames until the channel switch has completed */
-+ /* [in] */ u8 channelMode;
-+
-+ /* Number of TBTTs until channel switch occurs. */
-+ /* 0 - indicates switch shall occur at any time */
-+ /* 1 - occurs immediately before the next TBTT */
-+ /* [in] */ u8 channelSwitchCount;
-+
-+ /* The new channel number to switch to. */
-+ /* Note this is defined as per section 2.7. */
-+ /* [in] */ u16 newChannelNumber;
-+};
-+
-+int wsm_switch_channel(struct xradio_common *hw_priv,
-+ const struct wsm_switch_channel *arg, int if_id);
-+
-+struct wsm_start {
-+ /* WSM_START_MODE_... */
-+ /* [in] */ u8 mode;
-+
-+ /* WSM_PHY_BAND_... */
-+ /* [in] */ u8 band;
-+
-+ /* Channel number */
-+ /* [in] */ u16 channelNumber;
-+
-+ /* Client Traffic window in units of TU */
-+ /* Valid only when mode == ..._P2P */
-+ /* [in] */ u32 CTWindow;
-+
-+ /* Interval between two consecutive */
-+ /* beacon transmissions in TU. */
-+ /* [in] */ u32 beaconInterval;
-+
-+ /* DTIM period in terms of beacon intervals */
-+ /* [in] */ u8 DTIMPeriod;
-+
-+ /* WSM_JOIN_PREAMBLE_... */
-+ /* [in] */ u8 preambleType;
-+
-+ /* The delay time (in microseconds) period */
-+ /* before sending a probe-request. */
-+ /* [in] */ u8 probeDelay;
-+
-+ /* Length of the SSID */
-+ /* [in] */ u8 ssidLength;
-+
-+ /* SSID of the BSS or P2P_GO to be started now. */
-+ /* [in] */ u8 ssid[32];
-+
-+ /* The basic supported rates for the MiniAP. */
-+ /* [in] */ u32 basicRateSet;
-+};
-+
-+int wsm_start(struct xradio_common *hw_priv, const struct wsm_start *arg,
-+ int if_id);
-+
-+#if 0
-+struct wsm_beacon_transmit {
-+ /* 1: enable; 0: disable */
-+ /* [in] */ u8 enableBeaconing;
-+};
-+
-+int wsm_beacon_transmit(struct xradio_common *hw_priv,
-+ const struct wsm_beacon_transmit *arg,
-+ int if_id);
-+#endif
-+
-+int wsm_start_find(struct xradio_common *hw_priv, int if_id);
-+
-+int wsm_stop_find(struct xradio_common *hw_priv, int if_id);
-+
-+struct wsm_suspend_resume {
-+ /* See 3.52 */
-+ /* Link ID */
-+ /* [out] */ int link_id;
-+ /* Stop sending further Tx requests down to device for this link */
-+ /* [out] */ bool stop;
-+ /* Transmit multicast Frames */
-+ /* [out] */ bool multicast;
-+ /* The AC on which Tx to be suspended /resumed. */
-+ /* This is applicable only for U-APSD */
-+ /* WSM_QUEUE_... */
-+ /* [out] */ int queue;
-+ /* [out] */ int if_id;
-+};
-+
-+/* 3.54 Update-IE request. */
-+struct wsm_update_ie {
-+ /* WSM_UPDATE_IE_... */
-+ /* [in] */ u16 what;
-+ /* [in] */ u16 count;
-+ /* [in] */ u8 *ies;
-+ /* [in] */ size_t length;
-+};
-+
-+int wsm_update_ie(struct xradio_common *hw_priv,
-+ const struct wsm_update_ie *arg, int if_id);
-+
-+/* 3.56 */
-+struct wsm_map_link {
-+ /* MAC address of the remote device */
-+ /* [in] */ u8 mac_addr[6];
-+ /* [in] */ u8 unmap;
-+ /* [in] */ u8 link_id;
-+};
-+
-+int wsm_map_link(struct xradio_common *hw_priv, const struct wsm_map_link *arg,
-+ int if_id);
-+
-+#ifdef MCAST_FWDING
-+
-+/* 3.65 Give Buffer Request */
-+int wsm_init_release_buffer_request(struct xradio_common *priv, u8 index);
-+
-+/* 3.65 fixed memory leakage by yangfh*/
-+int wsm_deinit_release_buffer(struct xradio_common *hw_priv);
-+
-+/* 3.67 Request Buffer Request */
-+int wsm_request_buffer_request(struct xradio_vif *priv,
-+ u8 *arg);
-+#endif
-+/* ******************************************************************** */
-+/* MIB shortcats */
-+#define XR_RRM 1
-+#ifdef XR_RRM//RadioResourceMeasurement
-+/* RadioResourceMeasurement Request*/
-+#define MEAS_CCA 0
-+#define MEAS_CHANNELLOAD 1
-+typedef struct LMAC_MEAS_CHANNEL_LOAD_PARAMS_S
-+{
-+ u8 Reserved;
-+ u8 ChannelLoadCCA;
-+ u16 ChannelNum;
-+ u16 RandomInterval;
-+ u16 MeasurementDuration;
-+ u32 MeasurementStartTimel;
-+ u32 MeasurementStartTimeh;
-+}LMAC_MEAS_CHANNEL_LOAD_PARAMS;
-+
-+#define MEAS_RPI 0
-+#define MEAS_IPI 1
-+
-+typedef struct LMAC_MEAS_NOISE_HISTOGRAM_PARAMS_S
-+{
-+ u8 Reserved;
-+ u8 IpiRpi;
-+ u16 ChannelNum;
-+ u16 RandomInterval;
-+ u16 MeasurementDuration;
-+ u32 MeasurementStartTimel;
-+ u32 MeasurementStartTimeh;
-+}LMAC_MEAS_NOISE_HISTOGRAM_PARAMS;
-+
-+#define LMAC_MAX_SSIDS 16
-+#define LMAC_MAX_SSID_LENGTH 32
-+typedef struct LMAC_CHANNELS_S
-+{
-+ u32 ChannelNum;
-+ u32 MinChannelTime;
-+ u32 MaxChannelTime;
-+ s32 TxPowerLevel;
-+}LMAC_CHANNELS;
-+
-+typedef struct LMAC_SSIDS_S
-+{
-+ u32 SSIDLength;
-+ u8 SSID[LMAC_MAX_SSID_LENGTH];
-+}LMAC_SSIDS;
-+
-+typedef struct LMAC_MEAS_BEACON_PARAMS_S
-+{
-+ //u8 RegulatoryClass;
-+ //u8 MeasurementMode;
-+ //u16 ChannelNum;
-+ u16 RandomInterval;
-+ //u16 MeasurementDuration;
-+ //u8 Bssid[6];
-+ u16 Reserved;
-+ //SCAN_PARAMETERS ScanParameters;
-+ u8 Band;
-+ u8 ScanType;
-+ u8 ScanFlags;
-+ u8 MaxTransmitRate;
-+ u32 AutoScanInterval;
-+ u8 NumOfProbeRequests;
-+ u8 NumOfChannels;
-+ u8 NumOfSSIDs;
-+ u8 ProbeDelay;
-+ LMAC_CHANNELS Channels;
-+ LMAC_SSIDS Ssids; // here for SCAN_PARAMETER sizing purposes
-+}LMAC_MEAS_BEACON_PARAMS;
-+
-+typedef struct LMAC_MEAS_STA_STATS_PARAMS_S
-+{
-+ u8 PeerMacAddress[6];
-+ u16 RandomInterval;
-+ u16 MeasurementDuration;
-+ u8 GroupId;
-+ u8 Reserved;
-+}LMAC_MEAS_STA_STATS_PARAMS;
-+
-+typedef struct LMAC_MEAS_LINK_MEASUREMENT_PARAMS_S
-+{
-+ u8 Reserved[4];
-+}LMAC_MEAS_LINK_MEASUREMENT_PARAMS;
-+
-+typedef union LMAC_MEAS_REQUEST_U
-+{
-+ LMAC_MEAS_CHANNEL_LOAD_PARAMS ChannelLoadParams;
-+ LMAC_MEAS_NOISE_HISTOGRAM_PARAMS NoisHistogramParams;
-+ LMAC_MEAS_BEACON_PARAMS BeaconParams;
-+ LMAC_MEAS_STA_STATS_PARAMS StaStatsParams;
-+ LMAC_MEAS_LINK_MEASUREMENT_PARAMS LinkMeasurementParams;
-+} LMAC_MEAS_REQUEST;
-+
-+// This struct is a copy of WSM_HI_START_MEASUREMENT_REQ, except that MsgLen and MsgId is not included
-+typedef struct MEASUREMENT_PARAMETERS_S
-+{
-+// u16 MsgLen;
-+// u16 MsgId;
-+ s32 TxPowerLevel;
-+ u8 DurationMandatory;
-+ u8 MeasurementType;
-+ u8 MeasurementRequestLength;
-+ u8 Reserved[5];
-+ LMAC_MEAS_REQUEST MeasurementRequest;
-+}MEASUREMENT_PARAMETERS;
-+
-+/* RadioResourceMeasurement Result*/
-+ typedef struct LMAC_MEAS_CHANNEL_LOAD_RESULTS_S
-+{
-+ u8 Reserved;
-+ u8 ChannelLoadCCA;
-+ u16 ChannelNum;
-+ u32 ActualMeasurementStartTimel;
-+ u32 ActualMeasurementStartTimeh;
-+ u16 MeasurementDuration;
-+ u8 CCAbusyFraction;
-+ u8 ChannelLoad;
-+}LMAC_MEAS_CHANNEL_LOAD_RESULTS;
-+
-+typedef struct LMAC_MEAS_NOISE_HISTOGRAM_RESULTS_S
-+{
-+ u16 Reserved;
-+ u16 ChannelNum;
-+ u32 ActualMeasurementStartTimel;
-+ u32 ActualMeasurementStartTimeh;
-+ u16 MeasurementDuration;
-+ u8 AntennaID;
-+ u8 IpiRpi;
-+ u8 PI_0_Density;
-+ u8 PI_1_Density;
-+ u8 PI_2_Density;
-+ u8 PI_3_Density;
-+ u8 PI_4_Density;
-+ u8 PI_5_Density;
-+ u8 PI_6_Density;
-+ u8 PI_7_Density;
-+ u8 PI_8_Density;
-+ u8 PI_9_Density;
-+ u8 PI_10_Density;
-+ u8 Reserved2;
-+}LMAC_MEAS_NOISE_HISTOGRAM_RESULTS;
-+
-+typedef struct LMAC_MEAS_BEACON_RESULTS_S
-+{
-+ u16 MeasurementDuration;
-+ u16 Reserved;
-+ u32 StartTsfl;
-+ u32 StartTsfh;
-+ u32 Durationl;
-+ u32 Durationh;
-+ //SCAN_PARAMETERS ScanParameters;
-+ u8 Band;
-+ u8 ScanType;
-+ u8 ScanFlags;
-+ u8 MaxTransmitRate;
-+ u32 AutoScanInterval;
-+ u8 NumOfProbeRequests;
-+ u8 NumOfChannels;
-+ u8 NumOfSSIDs;
-+ u8 ProbeDelay;
-+ LMAC_CHANNELS Channels;
-+ LMAC_SSIDS Ssids;
-+}LMAC_MEAS_BEACON_RESULTS;
-+
-+typedef struct LMAC_MEAS_STA_STATS_RESULTS_S
-+{
-+ u16 MeasurementDuration;
-+ u8 GroupId;
-+ u8 StatisticsGroupDataLength;
-+ u8 StatisticsGroupData[52];
-+}LMAC_MEAS_STA_STATS_RESULTS;
-+
-+typedef struct LMAC_MEAS_LINK_MEASUREMENT_RESULTS_S
-+{
-+ s16 TransmitPower;
-+ u8 RxAntennaID;
-+ u8 TxAntennaID;
-+ s32 NoiseLeveldBm;
-+ s8 LatestRssi;
-+ u8 Reserved1;
-+ u8 Reserved2;
-+ u8 Reserved3;
-+}LMAC_MEAS_LINK_MEASUREMENT_RESULTS;
-+
-+typedef union LMAC_MEAS_REPORT_U
-+{
-+ LMAC_MEAS_CHANNEL_LOAD_RESULTS ChannelLoadResults;
-+ LMAC_MEAS_NOISE_HISTOGRAM_RESULTS NoiseHistogramResults;
-+ LMAC_MEAS_BEACON_RESULTS BeaconResults;
-+ LMAC_MEAS_STA_STATS_RESULTS StaStatsResults;
-+ LMAC_MEAS_LINK_MEASUREMENT_RESULTS LinkMeasurementResults;
-+}LMAC_MEAS_REPORT;
-+
-+// Note: eMeasurementTypes MUST match the #define WSM_MEASURE_TYPE_XXX from wsm_api.h
-+typedef enum {
-+ ChannelLoadMeasurement=0,
-+ NoiseHistrogramMeasurement,
-+ BeaconReport,
-+ STAstatisticsReport,
-+ LinkMeasurement
-+}eMeasurementTypes;
-+
-+typedef struct MEASUREMENT_COMPLETE_S
-+{
-+// u16 RandomInterval;
-+// u16 Reserved0;
-+ u8 Dot11PowerMgmtMode; // From here WSM_HI_MEASURE_CMPL_IND and MEASUREMENT_COMPLETE_S must be identical
-+ u8 MeasurementType;
-+ u16 MoreInd; // Set to 1 if more indications are to follow for this measurement, otherwise 0;
-+ u32 Status;
-+ u8 MeasurementReportLength;
-+ u8 Reserved2[3];
-+ LMAC_MEAS_REPORT MeasurementReport;
-+}MEASUREMENT_COMPLETE; // Note: must be 32 bit aligned
-+
-+#endif
-+int wsm_11k_measure_requset(struct xradio_common *hw_priv,
-+ u8 measure_type,
-+ u16 ChannelNum,
-+ u16 Duration);
-+
-+
-+static inline int wsm_set_fw_debug_control(struct xradio_common *hw_priv,
-+ int debug_control, int if_id)
-+{
-+ __le32 val = __cpu_to_le32(debug_control);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_FW_DEBUG_CONTROL,
-+ &val, sizeof(val), if_id);
-+}
-+
-+static inline int wsm_set_host_sleep(struct xradio_common *hw_priv,
-+ u8 host_sleep, int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_HOST_SLEEP,
-+ &host_sleep, sizeof(host_sleep), if_id);
-+}
-+
-+static inline int wsm_set_output_power(struct xradio_common *hw_priv,
-+ int power_level, int if_id)
-+{
-+ __le32 val = __cpu_to_le32(power_level);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_CURRENT_TX_POWER_LEVEL,
-+ &val, sizeof(val), if_id);
-+}
-+
-+static inline int wsm_set_beacon_wakeup_period(struct xradio_common *hw_priv,
-+ unsigned dtim_interval,
-+ unsigned listen_interval,
-+ int if_id)
-+{
-+ struct {
-+ u8 numBeaconPeriods;
-+ u8 reserved;
-+ __le16 listenInterval;
-+ } val = {
-+ dtim_interval, 0, __cpu_to_le16(listen_interval)};
-+ if (dtim_interval > 0xFF || listen_interval > 0xFFFF)
-+ return -EINVAL;
-+ else
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_WAKEUP_PERIOD,
-+ &val, sizeof(val), if_id);
-+}
-+
-+struct wsm_rcpi_rssi_threshold {
-+ u8 rssiRcpiMode; /* WSM_RCPI_RSSI_... */
-+ u8 lowerThreshold;
-+ u8 upperThreshold;
-+ u8 rollingAverageCount;
-+};
-+
-+static inline int wsm_set_rcpi_rssi_threshold(struct xradio_common *hw_priv,
-+ struct wsm_rcpi_rssi_threshold *arg,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_RCPI_RSSI_THRESHOLD, arg,
-+ sizeof(*arg), if_id);
-+}
-+
-+struct wsm_counters_table {
-+ __le32 countPlcpErrors;
-+ __le32 countFcsErrors;
-+ __le32 countTxPackets;
-+ __le32 countRxPackets;
-+ __le32 countRxPacketErrors;
-+ __le32 countRtsSuccess;
-+ __le32 countRtsFailures;
-+ __le32 countRxFramesSuccess;
-+ __le32 countRxDecryptionFailures;
-+ __le32 countRxMicFailures;
-+ __le32 countRxNoKeyFailures;
-+ __le32 countTxMulticastFrames;
-+ __le32 countTxFramesSuccess;
-+ __le32 countTxFrameFailures;
-+ __le32 countTxFramesRetried;
-+ __le32 countTxFramesMultiRetried;
-+ __le32 countRxFrameDuplicates;
-+ __le32 countAckFailures;
-+ __le32 countRxMulticastFrames;
-+ __le32 countRxCMACICVErrors;
-+ __le32 countRxCMACReplays;
-+ __le32 countRxMgmtCCMPReplays;
-+ __le32 countRxBIPMICErrors;
-+};
-+
-+
-+struct wsm_ampducounters_table {
-+ u32 countTxAMPDUs;
-+ u32 countTxMPDUsInAMPDUs;
-+ u32 countTxOctetsInAMPDUs_l32;
-+ u32 countTxOctetsInAMPDUs_h32;
-+ u32 countRxAMPDUs;
-+ u32 countRxMPDUsInAMPDUs;
-+ u32 countRxOctetsInAMPDUs_l32;
-+ u32 countRxOctetsInAMPDUs_h32;
-+ u32 countRxDelimeterCRCErrorCount;
-+ u32 countImplictBARFailures;
-+ u32 countExplictBARFailures;
-+};
-+
-+struct wsm_txpipe_counter {
-+ u32 count1;
-+ u32 count2;
-+ u32 count3;
-+ u32 count4;
-+ u32 count5;
-+ u32 count6;
-+ u32 count7;
-+ u32 count8;
-+ u32 count9;
-+ u32 counta;
-+};
-+
-+struct wsm_backoff_counter {
-+ u32 count0;
-+ u32 count1;
-+ u32 count2;
-+ u32 count3;
-+ u32 count4;
-+ u32 count5;
-+ u32 count6;
-+ u32 count7;
-+ u32 count8;
-+ u32 count9;
-+};
-+//add by yangfh for read/write fw registers
-+#define WSM_REG_RW_F BIT(0) //0:read, 1:write
-+#define WSM_REG_RET_F BIT(1) //results is valid.
-+#define WSM_REG_BK_F BIT(4) //operate in block mode.
-+
-+struct reg_data {
-+ u32 reg_addr;
-+ u32 reg_val;
-+};
-+
-+typedef struct tag_wsm_reg_w {
-+ u16 flag;
-+ u16 data_size;
-+ struct reg_data arg[16];
-+} WSM_REG_W;
-+
-+typedef struct tag_wsm_reg_r {
-+ u16 flag;
-+ u16 data_size;
-+ u32 arg[16];
-+} WSM_REG_R;
-+
-+struct wsm_backoff_ctrl {
-+ u32 enable;
-+ u32 min;
-+ u32 max;
-+};
-+struct wsm_tala_para {
-+ u32 para;
-+ u32 thresh;
-+};
-+static inline int wsm_get_counters_table(struct xradio_common *hw_priv,
-+ struct wsm_counters_table *arg)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_COUNTERS_TABLE,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_get_ampducounters_table(struct xradio_common *hw_priv,
-+ struct wsm_ampducounters_table *arg)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_AMPDUCOUNTERS_TABLE,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_get_txpipe_table(struct xradio_common *hw_priv,
-+ struct wsm_txpipe_counter *arg)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_TXPIPE_TABLE,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_get_backoff_dbg(struct xradio_common *hw_priv,
-+ struct wsm_backoff_counter *arg)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_BACKOFF_DBG,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_set_backoff_ctrl(struct xradio_common *hw_priv,
-+ struct wsm_backoff_ctrl *arg)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BACKOFF_CTRL,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_set_tala(struct xradio_common *hw_priv,
-+ struct wsm_tala_para *arg)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_TALA_PARA,
-+ arg, sizeof(*arg), 0);
-+}
-+static inline int wsm_get_station_id(struct xradio_common *hw_priv, u8 *mac)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_DOT11_STATION_ID, mac,
-+ ETH_ALEN, 0);
-+}
-+
-+struct wsm_rx_filter {
-+ bool promiscuous;
-+ bool bssid;
-+ bool fcs;
-+ bool probeResponder;
-+ bool keepalive;
-+};
-+
-+static inline int wsm_set_rx_filter(struct xradio_common *hw_priv,
-+ const struct wsm_rx_filter *arg,
-+ int if_id)
-+{
-+ __le32 val = 0;
-+ if (arg->promiscuous)
-+ val |= __cpu_to_le32(BIT(0));
-+ if (arg->bssid)
-+ val |= __cpu_to_le32(BIT(1));
-+ if (arg->fcs)
-+ val |= __cpu_to_le32(BIT(2));
-+ if (arg->probeResponder)
-+ val |= __cpu_to_le32(BIT(3));
-+ if (arg->keepalive)
-+ val |= __cpu_to_le32(BIT(4));
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_RX_FILTER, &val, sizeof(val),
-+ if_id);
-+}
-+
-+int wsm_set_probe_responder(struct xradio_vif *priv, bool enable);
-+int wsm_set_keepalive_filter(struct xradio_vif *priv, bool enable);
-+
-+#define WSM_BEACON_FILTER_IE_HAS_CHANGED BIT(0)
-+#define WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT BIT(1)
-+#define WSM_BEACON_FILTER_IE_HAS_APPEARED BIT(2)
-+
-+struct wsm_beacon_filter_table_entry {
-+ u8 ieId;
-+ u8 actionFlags;
-+ u8 oui[3];
-+ u8 matchData[3];
-+} __packed;
-+
-+struct wsm_beacon_filter_table {
-+ __le32 numOfIEs;
-+ struct wsm_beacon_filter_table_entry entry[10];
-+} __packed;
-+
-+static inline int wsm_set_beacon_filter_table(struct xradio_common *hw_priv,
-+ struct wsm_beacon_filter_table *ft,
-+ int if_id)
-+{
-+ size_t size = __le32_to_cpu(ft->numOfIEs) *
-+ sizeof(struct wsm_beacon_filter_table_entry) +
-+ sizeof(__le32);
-+
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_FILTER_TABLE, ft, size,
-+ if_id);
-+}
-+
-+#define WSM_BEACON_FILTER_ENABLE BIT(0) /* Enable/disable beacon filtering */
-+#define WSM_BEACON_FILTER_AUTO_ERP BIT(1) /* If 1 FW will handle ERP IE changes internally */
-+
-+struct wsm_beacon_filter_control {
-+ int enabled;
-+ int bcn_count;
-+};
-+
-+static inline int wsm_beacon_filter_control(struct xradio_common *hw_priv,
-+ struct wsm_beacon_filter_control *arg,
-+ int if_id)
-+{
-+ struct {
-+ __le32 enabled;
-+ __le32 bcn_count;
-+ } val;
-+ val.enabled = __cpu_to_le32(arg->enabled);
-+ val.bcn_count = __cpu_to_le32(arg->bcn_count);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_FILTER_ENABLE, &val,
-+ sizeof(val), if_id);
-+}
-+
-+enum wsm_power_mode {
-+ wsm_power_mode_active = 0,
-+ wsm_power_mode_doze = 1,
-+ wsm_power_mode_quiescent = 2,
-+};
-+
-+struct wsm_operational_mode {
-+ enum wsm_power_mode power_mode;
-+ int disableMoreFlagUsage;
-+ int performAntDiversity;
-+};
-+
-+static const struct wsm_operational_mode defaultoperationalmode = {
-+ .power_mode = wsm_power_mode_active,
-+ .disableMoreFlagUsage = true,
-+};
-+
-+static inline int wsm_set_operational_mode(struct xradio_common *hw_priv,
-+ const struct wsm_operational_mode *arg,
-+ int if_id)
-+{
-+ u32 val = arg->power_mode;
-+
-+ if (arg->disableMoreFlagUsage)
-+ val |= BIT(4);
-+ if (arg->performAntDiversity)
-+ val |= BIT(5);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_OPERATIONAL_POWER_MODE, &val,
-+ sizeof(val), if_id);
-+}
-+
-+struct wsm_inactivity {
-+ u8 max_inactivity;
-+ u8 min_inactivity;
-+};
-+
-+static inline int wsm_set_inactivity(struct xradio_common *hw_priv,
-+ const struct wsm_inactivity *arg,
-+ int if_id)
-+{
-+ struct {
-+ u8 min_inactive;
-+ u8 max_inactive;
-+ u16 reserved;
-+ } val;
-+
-+ val.max_inactive = arg->max_inactivity;
-+ val.min_inactive = arg->min_inactivity;
-+ val.reserved = 0;
-+
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_INACTIVITY, &val,
-+ sizeof(val), if_id);
-+}
-+
-+struct wsm_template_frame {
-+ u8 frame_type;
-+ u8 rate;
-+ bool disable;
-+ struct sk_buff *skb;
-+};
-+
-+static inline int wsm_set_template_frame(struct xradio_common *hw_priv,
-+ struct wsm_template_frame *arg,
-+ int if_id)
-+{
-+ int ret;
-+ u8 *p = skb_push(arg->skb, 4);
-+ p[0] = arg->frame_type;
-+ p[1] = arg->rate;
-+ if (arg->disable)
-+ ((u16 *) p)[1] = 0;
-+ else
-+ ((u16 *) p)[1] = __cpu_to_le16(arg->skb->len - 4);
-+ ret = wsm_write_mib(hw_priv, WSM_MIB_ID_TEMPLATE_FRAME, p,
-+ arg->skb->len, if_id);
-+ skb_pull(arg->skb, 4);
-+ return ret;
-+}
-+
-+
-+struct wsm_protected_mgmt_policy {
-+ bool protectedMgmtEnable;
-+ bool unprotectedMgmtFramesAllowed;
-+ bool encryptionForAuthFrame;
-+};
-+
-+static inline int
-+wsm_set_protected_mgmt_policy(struct xradio_common *hw_priv,
-+ struct wsm_protected_mgmt_policy *arg,
-+ int if_id)
-+{
-+ __le32 val = 0;
-+ int ret;
-+ if (arg->protectedMgmtEnable)
-+ val |= __cpu_to_le32(BIT(0));
-+ if (arg->unprotectedMgmtFramesAllowed)
-+ val |= __cpu_to_le32(BIT(1));
-+ if (arg->encryptionForAuthFrame)
-+ val |= __cpu_to_le32(BIT(2));
-+ ret = wsm_write_mib(hw_priv, WSM_MIB_ID_PROTECTED_MGMT_POLICY, &val,
-+ sizeof(val), if_id);
-+ return ret;
-+}
-+
-+static inline int wsm_set_block_ack_policy(struct xradio_common *hw_priv,
-+ u8 blockAckTxTidPolicy,
-+ u8 blockAckRxTidPolicy,
-+ int if_id)
-+{
-+ struct {
-+ u8 blockAckTxTidPolicy;
-+ u8 reserved1;
-+ u8 blockAckRxTidPolicy;
-+ u8 reserved2;
-+ } val = {
-+ .blockAckTxTidPolicy = blockAckTxTidPolicy,
-+ .blockAckRxTidPolicy = blockAckRxTidPolicy,
-+ };
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BLOCK_ACK_POLICY, &val,
-+ sizeof(val), if_id);
-+}
-+
-+struct wsm_association_mode {
-+ u8 flags; /* WSM_ASSOCIATION_MODE_... */
-+ u8 preambleType; /* WSM_JOIN_PREAMBLE_... */
-+ u8 greenfieldMode; /* 1 for greenfield */
-+ u8 mpduStartSpacing;
-+ __le32 basicRateSet;
-+};
-+
-+static inline int wsm_set_association_mode(struct xradio_common *hw_priv,
-+ struct wsm_association_mode *arg,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_ASSOCIATION_MODE, arg,
-+ sizeof(*arg), if_id);
-+}
-+
-+struct wsm_set_tx_rate_retry_policy_header {
-+ u8 numTxRatePolicies;
-+ u8 reserved[3];
-+} __packed;
-+
-+struct wsm_set_tx_rate_retry_policy_policy {
-+ u8 policyIndex;
-+ u8 shortRetryCount;
-+ u8 longRetryCount;
-+ u8 policyFlags;
-+ u8 rateRecoveryCount;
-+ u8 reserved[3];
-+ __le32 rateCountIndices[3];
-+} __packed;
-+
-+struct wsm_set_tx_rate_retry_policy {
-+ struct wsm_set_tx_rate_retry_policy_header hdr;
-+ struct wsm_set_tx_rate_retry_policy_policy tbl[8];
-+} __packed;
-+
-+static inline int wsm_set_tx_rate_retry_policy(struct xradio_common *hw_priv,
-+ struct wsm_set_tx_rate_retry_policy *arg,
-+ int if_id)
-+{
-+ size_t size = sizeof(struct wsm_set_tx_rate_retry_policy_header) +
-+ arg->hdr.numTxRatePolicies *
-+ sizeof(struct wsm_set_tx_rate_retry_policy_policy);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_TX_RATE_RETRY_POLICY, arg,
-+ size, if_id);
-+}
-+
-+/* 4.32 SetEtherTypeDataFrameFilter */
-+struct wsm_ether_type_filter_hdr {
-+ u8 nrFilters; /* Up to WSM_MAX_FILTER_ELEMENTS */
-+ u8 reserved[3];
-+} __packed;
-+
-+struct wsm_ether_type_filter {
-+ u8 filterAction; /* WSM_FILTER_ACTION_XXX */
-+ u8 reserved;
-+ __le16 etherType; /* Type of ethernet frame */
-+} __packed;
-+
-+static inline int wsm_set_ether_type_filter(struct xradio_common *hw_priv,
-+ struct wsm_ether_type_filter_hdr *arg,
-+ int if_id)
-+{
-+ size_t size = sizeof(struct wsm_ether_type_filter_hdr) +
-+ arg->nrFilters * sizeof(struct wsm_ether_type_filter);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_ETHERTYPE_DATAFRAME_FILTER,
-+ arg, size, if_id);
-+}
-+
-+
-+/* 4.33 SetUDPPortDataFrameFilter */
-+struct wsm_udp_port_filter_hdr {
-+ u8 nrFilters; /* Up to WSM_MAX_FILTER_ELEMENTS */
-+ u8 reserved[3];
-+} __packed;
-+
-+struct wsm_udp_port_filter {
-+ u8 filterAction; /* WSM_FILTER_ACTION_XXX */
-+ u8 portType; /* WSM_FILTER_PORT_TYPE_XXX */
-+ __le16 udpPort; /* Port number */
-+} __packed;
-+
-+static inline int wsm_set_udp_port_filter(struct xradio_common *hw_priv,
-+ struct wsm_udp_port_filter_hdr *arg,
-+ int if_id)
-+{
-+ size_t size = sizeof(struct wsm_udp_port_filter_hdr) +
-+ arg->nrFilters * sizeof(struct wsm_udp_port_filter);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_UDPPORT_DATAFRAME_FILTER,
-+ arg, size, if_id);
-+}
-+
-+/* Undocumented MIBs: */
-+/* 4.35 P2PDeviceInfo */
-+#define D11_MAX_SSID_LEN (32)
-+
-+struct wsm_p2p_device_type {
-+ __le16 categoryId;
-+ u8 oui[4];
-+ __le16 subCategoryId;
-+} __packed;
-+
-+struct wsm_p2p_device_info {
-+ struct wsm_p2p_device_type primaryDevice;
-+ u8 reserved1[3];
-+ u8 devNameSize;
-+ u8 localDevName[D11_MAX_SSID_LEN];
-+ u8 reserved2[3];
-+ u8 numSecDevSupported;
-+ struct wsm_p2p_device_type secondaryDevices[0];
-+} __packed;
-+
-+/* 4.36 SetWCDMABand - WO */
-+struct wsm_cdma_band {
-+ u8 WCDMA_Band;
-+ u8 reserved[3];
-+} __packed;
-+
-+/* 4.37 GroupTxSequenceCounter - RO */
-+struct wsm_group_tx_seq {
-+ __le32 bits_47_16;
-+ __le16 bits_15_00;
-+ __le16 reserved;
-+} __packed;
-+
-+/* 4.39 SetHtProtection - WO */
-+#define WSM_DUAL_CTS_PROT_ENB (1 << 0)
-+#define WSM_NON_GREENFIELD_STA PRESENT(1 << 1)
-+#define WSM_HT_PROT_MODE__NO_PROT (0 << 2)
-+#define WSM_HT_PROT_MODE__NON_MEMBER (1 << 2)
-+#define WSM_HT_PROT_MODE__20_MHZ (2 << 2)
-+#define WSM_HT_PROT_MODE__NON_HT_MIXED (3 << 2)
-+#define WSM_LSIG_TXOP_PROT_FULL (1 << 4)
-+#define WSM_LARGE_L_LENGTH_PROT (1 << 5)
-+
-+struct wsm_ht_protection {
-+ __le32 flags;
-+} __packed;
-+
-+/* 4.40 GPIO Command - R/W */
-+#define WSM_GPIO_COMMAND_SETUP 0
-+#define WSM_GPIO_COMMAND_READ 1
-+#define WSM_GPIO_COMMAND_WRITE 2
-+#define WSM_GPIO_COMMAND_RESET 3
-+#define WSM_GPIO_ALL_PINS 0xFF
-+
-+struct wsm_gpio_command {
-+ u8 GPIO_Command;
-+ u8 pin;
-+ __le16 config;
-+} __packed;
-+
-+/* 4.41 TSFCounter - RO */
-+struct wsm_tsf_counter {
-+ __le64 TSF_Counter;
-+} __packed;
-+
-+/* 4.43 Keep alive period */
-+struct wsm_keep_alive_period {
-+ __le16 keepAlivePeriod;
-+ u8 reserved[2];
-+} __packed;
-+
-+static inline int wsm_keep_alive_period(struct xradio_common *hw_priv,
-+ int period, int if_id)
-+{
-+ struct wsm_keep_alive_period arg = {
-+ .keepAlivePeriod = __cpu_to_le16(period),
-+ };
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_KEEP_ALIVE_PERIOD,
-+ &arg, sizeof(arg), if_id);
-+};
-+
-+/* BSSID filtering */
-+struct wsm_set_bssid_filtering {
-+ u8 filter;
-+ u8 reserved[3];
-+} __packed;
-+
-+static inline int wsm_set_bssid_filtering(struct xradio_common *hw_priv,
-+ bool enabled, int if_id)
-+{
-+ struct wsm_set_bssid_filtering arg = {
-+ .filter = !enabled,
-+ };
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_DISABLE_BSSID_FILTER,
-+ &arg, sizeof(arg), if_id);
-+}
-+
-+/* Multicat filtering - 4.5 */
-+struct wsm_multicast_filter {
-+ __le32 enable;
-+ __le32 numOfAddresses;
-+ u8 macAddress[WSM_MAX_GRP_ADDRTABLE_ENTRIES][ETH_ALEN];
-+} __packed;
-+
-+/* Mac Addr Filter Info */
-+struct wsm_mac_addr_info {
-+ u8 filter_mode;
-+ u8 address_mode;
-+ u8 MacAddr[6];
-+} __packed;
-+
-+/* Mac Addr Filter */
-+struct wsm_mac_addr_filter {
-+ u8 numfilter;
-+ u8 action_mode;
-+ u8 Reserved[2];
-+ struct wsm_mac_addr_info macaddrfilter[0];
-+} __packed;
-+
-+/* Broadcast Addr Filter */
-+struct wsm_broadcast_addr_filter {
-+ u8 action_mode;
-+ u8 nummacaddr;
-+ u8 filter_mode;
-+ u8 address_mode;
-+ u8 MacAddr[6];
-+} __packed;
-+
-+static inline int wsm_set_multicast_filter(struct xradio_common *hw_priv,
-+ struct wsm_multicast_filter *fp,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_GROUP_ADDRESSES_TABLE,
-+ fp, sizeof(*fp), if_id);
-+}
-+
-+/* ARP IPv4 filtering - 4.10 */
-+struct wsm_arp_ipv4_filter {
-+ __le32 enable;
-+ __be32 ipv4Address[WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES];
-+} __packed;
-+
-+
-+static inline int wsm_set_arp_ipv4_filter(struct xradio_common *hw_priv,
-+ struct wsm_arp_ipv4_filter *fp,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_ARP_IP_ADDRESSES_TABLE,
-+ fp, sizeof(*fp), if_id);
-+}
-+
-+/* P2P Power Save Mode Info - 4.31 */
-+struct wsm_p2p_ps_modeinfo {
-+ u8 oppPsCTWindow;
-+ u8 count;
-+ u8 reserved;
-+ u8 dtimCount;
-+ __le32 duration;
-+ __le32 interval;
-+ __le32 startTime;
-+} __packed;
-+
-+static inline int wsm_set_p2p_ps_modeinfo(struct xradio_common *hw_priv,
-+ struct wsm_p2p_ps_modeinfo *mi,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_P2P_PS_MODE_INFO,
-+ mi, sizeof(*mi), if_id);
-+}
-+
-+static inline int wsm_get_p2p_ps_modeinfo(struct xradio_common *hw_priv,
-+ struct wsm_p2p_ps_modeinfo *mi)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_P2P_PS_MODE_INFO,
-+ mi, sizeof(*mi), 0);
-+}
-+
-+/* UseMultiTxConfMessage */
-+
-+static inline int wsm_use_multi_tx_conf(struct xradio_common *hw_priv,
-+ bool enabled, int if_id)
-+{
-+ __le32 arg = enabled ? __cpu_to_le32(1) : 0;
-+
-+ return wsm_write_mib(hw_priv, WSM_MIB_USE_MULTI_TX_CONF,
-+ &arg, sizeof(arg), if_id);
-+}
-+
-+
-+/* 4.26 SetUpasdInformation */
-+struct wsm_uapsd_info {
-+ __le16 uapsdFlags;
-+ __le16 minAutoTriggerInterval;
-+ __le16 maxAutoTriggerInterval;
-+ __le16 autoTriggerStep;
-+};
-+
-+static inline int wsm_set_uapsd_info(struct xradio_common *hw_priv,
-+ struct wsm_uapsd_info *arg,
-+ int if_id)
-+{
-+ /* TODO:COMBO:UAPSD will be supported only on one interface */
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_UAPSD_INFORMATION,
-+ arg, sizeof(*arg), if_id);
-+}
-+
-+/* 4.22 OverrideInternalTxRate */
-+struct wsm_override_internal_txrate {
-+ u8 internalTxRate;
-+ u8 nonErpInternalTxRate;
-+ u8 reserved[2];
-+} __packed;
-+
-+static inline int
-+wsm_set_override_internal_txrate(struct xradio_common *hw_priv,
-+ struct wsm_override_internal_txrate *arg,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE,
-+ arg, sizeof(*arg), if_id);
-+}
-+#ifdef MCAST_FWDING
-+/* 4.51 SetForwardingOffload */
-+struct wsm_forwarding_offload {
-+ u8 fwenable;
-+ u8 flags;
-+ u8 reserved[2];
-+} __packed;
-+
-+static inline int wsm_set_forwarding_offlad(struct xradio_common *hw_priv,
-+ struct wsm_forwarding_offload *arg,int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_FORWARDING_OFFLOAD,
-+ arg, sizeof(*arg),if_id);
-+}
-+
-+#endif
-+/* ******************************************************************** */
-+/* WSM TX port control */
-+
-+void wsm_lock_tx(struct xradio_common *hw_priv);
-+void wsm_vif_lock_tx(struct xradio_vif *priv);
-+void wsm_lock_tx_async(struct xradio_common *hw_priv);
-+bool wsm_flush_tx(struct xradio_common *hw_priv);
-+bool wsm_vif_flush_tx(struct xradio_vif *priv);
-+void wsm_unlock_tx(struct xradio_common *hw_priv);
-+
-+/* ******************************************************************** */
-+/* WSM / BH API */
-+
-+int wsm_handle_exception(struct xradio_common *hw_priv, u8 * data, size_t len);
-+int wsm_handle_rx(struct xradio_common *hw_priv, int id, struct wsm_hdr *wsm,
-+ struct sk_buff **skb_p);
-+void wms_send_deauth_to_self(struct xradio_common *hw_priv, struct xradio_vif *priv);
-+void wms_send_disassoc_to_self(struct xradio_common *hw_priv, struct xradio_vif *priv);
-+
-+/* ******************************************************************** */
-+/* wsm_buf API */
-+
-+struct wsm_buf {
-+ u8 *begin;
-+ u8 *data;
-+ u8 *end;
-+};
-+
-+void wsm_buf_init(struct wsm_buf *buf);
-+void wsm_buf_deinit(struct wsm_buf *buf);
-+
-+/* ******************************************************************** */
-+/* wsm_cmd API */
-+
-+struct wsm_cmd {
-+ spinlock_t lock;
-+ int done;
-+ u8 *ptr;
-+ size_t len;
-+ void *arg;
-+ int ret;
-+ u16 cmd;
-+};
-+
-+/* ******************************************************************** */
-+/* WSM TX buffer access */
-+
-+int wsm_get_tx(struct xradio_common *hw_priv, u8 **data,
-+ size_t *tx_len, int *burst, int *vif_selected);
-+void wsm_txed(struct xradio_common *hw_priv, u8 *data);
-+
-+/* ******************************************************************** */
-+/* Queue mapping: WSM <---> linux */
-+/* Linux: VO VI BE BK */
-+/* WSM: BE BK VI VO */
-+
-+static inline u8 wsm_queue_id_to_linux(u8 queueId)
-+{
-+ static const u8 queue_mapping[] = {
-+ 2, 3, 1, 0
-+ };
-+ return queue_mapping[queueId];
-+}
-+
-+static inline u8 wsm_queue_id_to_wsm(u8 queueId)
-+{
-+ static const u8 queue_mapping[] = {
-+ 3, 2, 0, 1
-+ };
-+ return queue_mapping[queueId];
-+}
-+
-+#endif /* XRADIO_HWIO_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/xradio.h b/drivers/net/wireless/xradio/xradio.h
-new file mode 100644
-index 0000000..d565db0
---- /dev/null
-+++ b/drivers/net/wireless/xradio/xradio.h
-@@ -0,0 +1,577 @@
-+/*
-+ * Common define of private data for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_H
-+#define XRADIO_H
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+//Macroses for Driver parameters.
-+#define XRWL_MAX_QUEUE_SZ (128)
-+#define AC_QUEUE_NUM 4
-+
-+#define XRWL_MAX_VIFS (2)
-+#define XRWL_GENERIC_IF_ID (2)
-+#define XRWL_HOST_VIF0_11N_THROTTLE (58) //(XRWL_MAX_QUEUE_SZ/(XRWL_MAX_VIFS-1))*0.9
-+#define XRWL_HOST_VIF1_11N_THROTTLE (58) //(XRWL_MAX_QUEUE_SZ/(XRWL_MAX_VIFS-1))*0.9
-+#define XRWL_HOST_VIF0_11BG_THROTTLE (35) //XRWL_HOST_VIF0_11N_THROTTLE*0.6 = 35
-+#define XRWL_HOST_VIF1_11BG_THROTTLE (35) //XRWL_HOST_VIF0_11N_THROTTLE*0.6 = 35
-+#if 0
-+#define XRWL_FW_VIF0_THROTTLE (15)
-+#define XRWL_FW_VIF1_THROTTLE (15)
-+#endif
-+
-+#define IEEE80211_FCTL_WEP 0x4000
-+#define IEEE80211_QOS_DATAGRP 0x0080
-+#define WSM_KEY_MAX_IDX 20
-+
-+#include "queue.h"
-+#include "wsm.h"
-+#include "scan.h"
-+#include "tx.h"
-+#include "ht.h"
-+#include "pm.h"
-+#include "fwio.h"
-+
-+/* #define ROC_DEBUG */
-+/* hidden ssid is only supported when separate probe resp IE
-+ configuration is supported */
-+#ifdef PROBE_RESP_EXTRA_IE
-+#define HIDDEN_SSID 1
-+#endif
-+
-+#define XRADIO_MAX_CTRL_FRAME_LEN (0x1000)
-+
-+#define MAX_STA_IN_AP_MODE (14)
-+#define WLAN_LINK_ID_MAX (MAX_STA_IN_AP_MODE + 3)
-+
-+#define XRADIO_MAX_STA_IN_AP_MODE (5)
-+#define XRADIO_MAX_REQUEUE_ATTEMPTS (5)
-+#define XRADIO_LINK_ID_UNMAPPED (15)
-+#define XRADIO_MAX_TID (8)
-+
-+#define XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID (0x3F)
-+#define XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID (0x3F)
-+#define XRADIO_RX_BLOCK_ACK_ENABLED_FOR_BE_TID \
-+ (XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID & 0x01)
-+#define XRADIO_TX_BLOCK_ACK_DISABLED_FOR_ALL_TID (0)
-+#define XRADIO_RX_BLOCK_ACK_DISABLED_FOR_ALL_TID (0)
-+
-+#define XRADIO_BLOCK_ACK_CNT (30)
-+#define XRADIO_BLOCK_ACK_THLD (800)
-+#define XRADIO_BLOCK_ACK_HIST (3)
-+#define XRADIO_BLOCK_ACK_INTERVAL (1 * HZ / XRADIO_BLOCK_ACK_HIST)
-+#define XRWL_ALL_IFS (-1)
-+
-+#ifdef ROAM_OFFLOAD
-+#define XRADIO_SCAN_TYPE_ACTIVE 0x1000
-+#define XRADIO_SCAN_BAND_5G 0x2000
-+#endif /*ROAM_OFFLOAD*/
-+
-+#define IEEE80211_FCTL_WEP 0x4000
-+#define IEEE80211_QOS_DATAGRP 0x0080
-+
-+#ifdef MCAST_FWDING
-+#define WSM_MAX_BUF 30
-+#endif
-+
-+#define MAX_RATES_STAGE 8 //
-+#define MAX_RATES_RETRY 15
-+
-+#define XRADIO_WORKQUEUE "xradio_wq"
-+#define WIFI_CONF_PATH "/data/xr_wifi.conf"
-+
-+/* extern */ struct task_struct;
-+/* extern */ struct xradio_debug_priv;
-+/* extern */ struct xradio_debug_common;
-+/* extern */ struct firmware;
-+
-+/* Please keep order */
-+enum xradio_join_status {
-+ XRADIO_JOIN_STATUS_PASSIVE = 0,
-+ XRADIO_JOIN_STATUS_MONITOR,
-+ XRADIO_JOIN_STATUS_STA,
-+ XRADIO_JOIN_STATUS_AP,
-+};
-+
-+enum xradio_link_status {
-+ XRADIO_LINK_OFF,
-+ XRADIO_LINK_RESERVE,
-+ XRADIO_LINK_SOFT,
-+ XRADIO_LINK_HARD,
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ XRADIO_LINK_RESET,
-+ XRADIO_LINK_RESET_REMAP,
-+#endif
-+};
-+
-+enum xradio_bss_loss_status {
-+ XRADIO_BSS_LOSS_NONE,
-+ XRADIO_BSS_LOSS_CHECKING,
-+ XRADIO_BSS_LOSS_CONFIRMING,
-+ XRADIO_BSS_LOSS_CONFIRMED,
-+};
-+
-+struct xradio_link_entry {
-+ unsigned long timestamp;
-+ enum xradio_link_status status;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ enum xradio_link_status prev_status;
-+#endif
-+ u8 mac[ETH_ALEN];
-+ u8 buffered[XRADIO_MAX_TID];
-+ struct sk_buff_head rx_queue;
-+};
-+
-+#if defined(ROAM_OFFLOAD)
-+struct xradio_testframe {
-+ u8 len;
-+ u8 *data;
-+};
-+#endif
-+
-+struct xradio_common {
-+ struct xradio_debug_common *debug;
-+ struct xradio_queue tx_queue[AC_QUEUE_NUM];
-+ struct xradio_queue_stats tx_queue_stats;
-+
-+ struct ieee80211_hw *hw;
-+ struct mac_address addresses[XRWL_MAX_VIFS];
-+
-+ /*Will be a pointer to a list of VIFs - Dynamically allocated */
-+ struct ieee80211_vif *vif_list[XRWL_MAX_VIFS];
-+ atomic_t num_vifs;
-+ spinlock_t vif_list_lock;
-+ u32 if_id_slot;
-+ struct device *pdev;
-+ struct workqueue_struct *workqueue;
-+
-+ struct mutex conf_mutex;
-+
-+ struct sdio_func *sdio_func;
-+ int driver_ready;
-+
-+ /* HW/FW type (HIF_...) */
-+ int hw_type;
-+ int hw_revision;
-+ int fw_revision;
-+
-+ /* firmware/hardware info */
-+ unsigned int tx_hdr_len;
-+
-+ /* Radio data */
-+ int output_power;
-+ int noise;
-+
-+ /* calibration, output power limit and rssi<->dBm conversation data */
-+
-+ /* BBP/MAC state */
-+ const struct firmware *sdd;
-+ struct ieee80211_rate *rates;
-+ struct ieee80211_rate *mcs_rates;
-+ u8 mac_addr[ETH_ALEN];
-+ /*TODO:COMBO: To be made per VIFF after mac80211 support */
-+ struct ieee80211_channel *channel;
-+ int channel_switch_in_progress;
-+ wait_queue_head_t channel_switch_done;
-+ u8 channel_changed; //add by yangfh 2015-5-15 16:57:38.
-+ u8 long_frame_max_tx_count;
-+ u8 short_frame_max_tx_count;
-+ /* TODO:COMBO: According to Hong aggregation will happen per VIFF.
-+ * Keeping in common structure for the time being. Will be moved to VIFF
-+ * after the mechanism is clear */
-+ u8 ba_tid_mask;
-+ int ba_acc; /*TODO: Same as above */
-+ int ba_cnt; /*TODO: Same as above */
-+ int ba_cnt_rx; /*TODO: Same as above */
-+ int ba_acc_rx; /*TODO: Same as above */
-+ int ba_hist; /*TODO: Same as above */
-+ struct timer_list ba_timer;/*TODO: Same as above */
-+ spinlock_t ba_lock; /*TODO: Same as above */
-+ bool ba_ena; /*TODO: Same as above */
-+ struct work_struct ba_work; /*TODO: Same as above */
-+ struct xradio_pm_state pm_state;
-+ bool is_BT_Present;
-+ bool is_go_thru_go_neg;
-+ u8 conf_listen_interval;
-+
-+ /* BH */
-+ atomic_t bh_tx;
-+ atomic_t bh_term;
-+ atomic_t bh_suspend;
-+ struct task_struct *bh_thread;
-+ int bh_error;
-+ wait_queue_head_t bh_wq;
-+ wait_queue_head_t bh_evt_wq;
-+
-+
-+ int buf_id_tx; /* byte */
-+ int buf_id_rx; /* byte */
-+ int wsm_rx_seq; /* byte */
-+ int wsm_tx_seq; /* byte */
-+ int hw_bufs_used;
-+ int hw_bufs_used_vif[XRWL_MAX_VIFS];
-+ struct sk_buff *skb_cache;
-+ struct sk_buff *skb_reserved;
-+ int skb_resv_len;
-+ bool powersave_enabled;
-+ bool device_can_sleep;
-+ /* Keep xradio awake (WUP = 1) 1 second after each scan to avoid
-+ * FW issue with sleeping/waking up. */
-+ atomic_t recent_scan;
-+ long connet_time[XRWL_MAX_VIFS];
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+ atomic_t suspend_state;
-+#endif
-+
-+ /* WSM */
-+ struct wsm_caps wsm_caps;
-+ struct mutex wsm_cmd_mux;
-+ struct wsm_buf wsm_cmd_buf;
-+ struct wsm_cmd wsm_cmd;
-+ wait_queue_head_t wsm_cmd_wq;
-+ wait_queue_head_t wsm_startup_done;
-+ struct semaphore tx_lock_sem;
-+ atomic_t tx_lock;
-+ u32 pending_frame_id;
-+
-+ /* WSM debug */
-+ u32 query_packetID;
-+ atomic_t query_cnt;
-+ struct work_struct query_work; /* for query packet */
-+
-+ /* Scan status */
-+ struct xradio_scan scan;
-+
-+ /* TX/RX */
-+ unsigned long rx_timestamp;
-+
-+ /* WSM events */
-+ spinlock_t event_queue_lock;
-+ struct list_head event_queue;
-+ struct work_struct event_handler;
-+
-+ /* TX rate policy cache */
-+ struct tx_policy_cache tx_policy_cache;
-+ struct work_struct tx_policy_upload_work;
-+ atomic_t upload_count;
-+
-+ /* cryptographic engine information */
-+
-+ /* bit field of glowing LEDs */
-+ u16 softled_state;
-+
-+ /* statistics */
-+ struct ieee80211_low_level_stats stats;
-+
-+ struct xradio_ht_oper ht_oper;
-+ int tx_burst_idx;
-+
-+ struct ieee80211_iface_limit if_limits1[2];
-+ struct ieee80211_iface_limit if_limits2[2];
-+ struct ieee80211_iface_limit if_limits3[2];
-+ struct ieee80211_iface_combination if_combs[3];
-+
-+ struct mutex wsm_oper_lock;
-+ struct delayed_work rem_chan_timeout;
-+ atomic_t remain_on_channel;
-+ int roc_if_id;
-+ u64 roc_cookie;
-+ wait_queue_head_t offchannel_wq;
-+ u16 offchannel_done;
-+ u16 prev_channel;
-+ int if_id_selected;
-+ u32 key_map;
-+ struct wsm_add_key keys[WSM_KEY_MAX_INDEX + 1];
-+#ifdef MCAST_FWDING
-+ struct wsm_buf wsm_release_buf[WSM_MAX_BUF];
-+ u8 buf_released;
-+#endif
-+#ifdef ROAM_OFFLOAD
-+ u8 auto_scanning;
-+ u8 frame_rcvd;
-+ u8 num_scanchannels;
-+ u8 num_2g_channels;
-+ u8 num_5g_channels;
-+ struct wsm_scan_ch scan_channels[48];
-+ struct sk_buff *beacon;
-+ struct sk_buff *beacon_bkp;
-+ struct xradio_testframe testframe;
-+#endif /*ROAM_OFFLOAD*/
-+
-+ u8 connected_sta_cnt;
-+ u16 vif0_throttle;
-+ u16 vif1_throttle;
-+};
-+
-+/* Virtual Interface State. One copy per VIF */
-+struct xradio_vif {
-+ atomic_t enabled;
-+ spinlock_t vif_lock;
-+ int if_id;
-+ /*TODO: Split into Common and VIF parts */
-+ struct xradio_debug_priv *debug;
-+ /* BBP/MAC state */
-+ u8 bssid[ETH_ALEN];
-+ struct wsm_edca_params edca;
-+ struct wsm_tx_queue_params tx_queue_params;
-+ struct wsm_association_mode association_mode;
-+ struct wsm_set_bss_params bss_params;
-+ struct wsm_set_pm powersave_mode;
-+ struct wsm_set_pm firmware_ps_mode;
-+ int power_set_true;
-+ int user_power_set_true;
-+ u8 user_pm_mode;
-+ int cqm_rssi_thold;
-+ unsigned cqm_rssi_hyst;
-+ unsigned cqm_tx_failure_thold;
-+ unsigned cqm_tx_failure_count;
-+ bool cqm_use_rssi;
-+ int cqm_link_loss_count;
-+ int cqm_beacon_loss_count;
-+ int mode;
-+ bool enable_beacon;
-+ int beacon_int;
-+ size_t ssid_length;
-+ u8 ssid[IEEE80211_MAX_SSID_LEN];
-+#ifdef HIDDEN_SSID
-+ bool hidden_ssid;
-+#endif
-+ bool listening;
-+ struct wsm_rx_filter rx_filter;
-+ struct wsm_beacon_filter_table bf_table;
-+ struct wsm_beacon_filter_control bf_control;
-+ struct wsm_multicast_filter multicast_filter;
-+ bool has_multicast_subscription;
-+ struct wsm_broadcast_addr_filter broadcast_filter;
-+ bool disable_beacon_filter;
-+ struct wsm_arp_ipv4_filter filter4;
-+ struct work_struct update_filtering_work;
-+ struct work_struct set_beacon_wakeup_period_work;
-+ struct xradio_pm_state_vif pm_state_vif;
-+ /*TODO: Add support in mac80211 for psmode info per VIF */
-+ struct wsm_p2p_ps_modeinfo p2p_ps_modeinfo;
-+ struct wsm_uapsd_info uapsd_info;
-+ bool setbssparams_done;
-+ u32 listen_interval;
-+ u32 erp_info;
-+ bool powersave_enabled;
-+
-+ /* WSM Join */
-+ enum xradio_join_status join_status;
-+ u8 join_bssid[ETH_ALEN];
-+ struct work_struct join_work;
-+ struct delayed_work join_timeout;
-+ struct work_struct unjoin_work;
-+ struct work_struct offchannel_work;
-+ int join_dtim_period;
-+ atomic_t delayed_unjoin;
-+
-+ /* Security */
-+ s8 wep_default_key_id;
-+ struct work_struct wep_key_work;
-+ unsigned long rx_timestamp;
-+ u32 cipherType;
-+
-+
-+ /* AP powersave */
-+ u32 link_id_map;
-+ u32 max_sta_ap_mode;
-+ u32 link_id_after_dtim;
-+ u32 link_id_uapsd;
-+ u32 link_id_max;
-+ u32 wsm_key_max_idx;
-+ struct xradio_link_entry link_id_db[MAX_STA_IN_AP_MODE];
-+ struct work_struct link_id_work;
-+ struct delayed_work link_id_gc_work;
-+ u32 sta_asleep_mask;
-+ u32 pspoll_mask;
-+ bool aid0_bit_set;
-+ spinlock_t ps_state_lock;
-+ bool buffered_multicasts;
-+ bool tx_multicast;
-+ u8 last_tim[8]; //for softap dtim, add by yangfh
-+ struct work_struct set_tim_work;
-+ struct delayed_work set_cts_work;
-+ struct work_struct multicast_start_work;
-+ struct work_struct multicast_stop_work;
-+ struct timer_list mcast_timeout;
-+
-+ /* CQM Implementation */
-+ struct delayed_work bss_loss_work;
-+ struct delayed_work connection_loss_work;
-+ struct work_struct tx_failure_work;
-+ int delayed_link_loss;
-+ spinlock_t bss_loss_lock;
-+ int bss_loss_status;
-+ int bss_loss_confirm_id;
-+
-+ struct ieee80211_vif *vif;
-+ struct xradio_common *hw_priv;
-+ struct ieee80211_hw *hw;
-+
-+ /* ROC implementation */
-+ struct delayed_work pending_offchanneltx_work;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ /* Workaround for WFD testcase 6.1.10*/
-+ struct work_struct linkid_reset_work;
-+ u8 action_frame_sa[ETH_ALEN];
-+ u8 action_linkid;
-+#endif
-+ bool htcap;
-+#ifdef AP_HT_CAP_UPDATE
-+ u16 ht_oper;
-+ struct work_struct ht_oper_update_work;
-+#endif
-+
-+#ifdef AP_HT_COMPAT_FIX
-+ u16 ht_compat_cnt;
-+ u16 ht_compat_det;
-+#endif
-+};
-+struct xradio_sta_priv {
-+ int link_id;
-+ struct xradio_vif *priv;
-+};
-+enum xradio_data_filterid {
-+ IPV4ADDR_FILTER_ID = 0,
-+};
-+
-+/* Datastructure for LLC-SNAP HDR */
-+#define P80211_OUI_LEN 3
-+struct ieee80211_snap_hdr {
-+ u8 dsap; /* always 0xAA */
-+ u8 ssap; /* always 0xAA */
-+ u8 ctrl; /* always 0x03 */
-+ u8 oui[P80211_OUI_LEN]; /* organizational universal id */
-+} __packed;
-+
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+extern s32 TES_P2P_0002_roc_dur;
-+extern s32 TES_P2P_0002_roc_sec;
-+extern s32 TES_P2P_0002_roc_usec;
-+extern u32 TES_P2P_0002_packet_id;
-+extern u32 TES_P2P_0002_state;
-+
-+#define TES_P2P_0002_STATE_IDLE 0x00
-+#define TES_P2P_0002_STATE_SEND_RESP 0x01
-+#define TES_P2P_0002_STATE_GET_PKTID 0x02
-+#endif
-+
-+/* debug.h must be here because refer to struct xradio_vif and
-+ struct xradio_common.*/
-+#include "debug.h"
-+
-+/*******************************************************
-+ interfaces for operations of vif.
-+********************************************************/
-+static inline
-+struct xradio_common *xrwl_vifpriv_to_hwpriv(struct xradio_vif *priv)
-+{
-+ return priv->hw_priv;
-+}
-+static inline
-+struct xradio_vif *xrwl_get_vif_from_ieee80211(struct ieee80211_vif *vif)
-+{
-+ return (struct xradio_vif *)vif->drv_priv;
-+}
-+
-+static inline
-+struct xradio_vif *xrwl_hwpriv_to_vifpriv(struct xradio_common *hw_priv,
-+ int if_id)
-+{
-+ struct xradio_vif *vif;
-+
-+ if (WARN_ON((-1 == if_id) || (if_id > XRWL_MAX_VIFS)))
-+ return NULL;
-+ /* TODO:COMBO: During scanning frames can be received
-+ * on interface ID 3 */
-+ spin_lock(&hw_priv->vif_list_lock);
-+ if (!hw_priv->vif_list[if_id]) {
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ return NULL;
-+ }
-+
-+ vif = xrwl_get_vif_from_ieee80211(hw_priv->vif_list[if_id]);
-+ WARN_ON(!vif);
-+ if (vif)
-+ spin_lock(&vif->vif_lock);
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ return vif;
-+}
-+
-+static inline
-+struct xradio_vif *__xrwl_hwpriv_to_vifpriv(struct xradio_common *hw_priv,
-+ int if_id)
-+{
-+ WARN_ON((-1 == if_id) || (if_id > XRWL_MAX_VIFS));
-+ /* TODO:COMBO: During scanning frames can be received
-+ * on interface ID 3 */
-+ if (!hw_priv->vif_list[if_id]) {
-+ return NULL;
-+ }
-+
-+ return xrwl_get_vif_from_ieee80211(hw_priv->vif_list[if_id]);
-+}
-+
-+static inline
-+struct xradio_vif *xrwl_get_activevif(struct xradio_common *hw_priv)
-+{
-+ return xrwl_hwpriv_to_vifpriv(hw_priv, ffs(hw_priv->if_id_slot)-1);
-+}
-+
-+static inline bool is_hardware_xradio(struct xradio_common *hw_priv)
-+{
-+ return (hw_priv->hw_revision == XR819_HW_REV0);
-+}
-+
-+static inline int xrwl_get_nr_hw_ifaces(struct xradio_common *hw_priv)
-+{
-+ switch(hw_priv->hw_revision) {
-+ case XR819_HW_REV0:
-+ default:
-+ return 1;
-+ }
-+}
-+
-+#define xradio_for_each_vif(_hw_priv, _priv, _i) \
-+ for( \
-+ _i = 0; \
-+ (_i < XRWL_MAX_VIFS) \
-+ && ((_priv = _hw_priv->vif_list[_i] ? \
-+ xrwl_get_vif_from_ieee80211(_hw_priv->vif_list[_i]) : NULL),1); \
-+ _i++ \
-+ )
-+
-+/*******************************************************
-+ interfaces for operations of queue.
-+********************************************************/
-+static inline void xradio_tx_queues_lock(struct xradio_common *hw_priv)
-+{
-+ int i;
-+ for (i = 0; i < 4; ++i)
-+ xradio_queue_lock(&hw_priv->tx_queue[i]);
-+}
-+
-+static inline void xradio_tx_queues_unlock(struct xradio_common *hw_priv)
-+{
-+ int i;
-+ for (i = 0; i < 4; ++i)
-+ xradio_queue_unlock(&hw_priv->tx_queue[i]);
-+}
-+
-+#endif /* XRADIO_H */
diff --git a/patch/kernel/sunxi-legacy/0135-clk-sunxi-ng-enable-so-said-LDOs-for-A64-SoC-s-pll-m.patch b/patch/kernel/sunxi-legacy/0135-clk-sunxi-ng-enable-so-said-LDOs-for-A64-SoC-s-pll-m.patch
deleted file mode 100644
index 6aa68872f..000000000
--- a/patch/kernel/sunxi-legacy/0135-clk-sunxi-ng-enable-so-said-LDOs-for-A64-SoC-s-pll-m.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 734e26b5a4b061d5f0667d59ce27a4a50f6d5c25 Mon Sep 17 00:00:00 2001
-From: Icenowy Zheng
-Date: Thu, 18 Oct 2018 15:07:29 +0800
-Subject: [PATCH 135/146] clk: sunxi-ng: enable so-said LDOs for A64 SoC's
- pll-mipi clock
-
-In the user manual of A64 SoC, the bit 22 and 23 of pll-mipi control
-register is called "LDO{1,2}_EN", and according to the BSP source code
-from Allwinner , the LDOs are enabled during the clock's enabling
-process.
-
-The clock failed to generate output if the two LDOs are not enabled.
-
-Add the two bits to the clock's gate bits, so that the LDOs are enabled
-when the PLL is enabled.
-
-Fixes: c6a0637460c2 ("clk: sunxi-ng: Add A64 clocks")
-Signed-off-by: Icenowy Zheng
----
- drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
-index 90ffee824c33..a637e62ae1c4 100644
---- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
-+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
-@@ -162,7 +162,12 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
- #define SUN50I_A64_PLL_MIPI_REG 0x040
-
- static struct ccu_nkm pll_mipi_clk = {
-- .enable = BIT(31),
-+ /*
-+ * The bit 23 and 22 are called "LDO{1,2}_EN" on the SoC's
-+ * user manual, and by experiments the PLL doesn't work without
-+ * these bits toggled.
-+ */
-+ .enable = BIT(31) | BIT(23) | BIT(22),
- .lock = BIT(28),
- .n = _SUNXI_CCU_MULT(8, 4),
- .k = _SUNXI_CCU_MULT_MIN(4, 2, 2),
---
-2.17.1
-
diff --git a/patch/kernel/sunxi-legacy/board-a64-v3-13-19-arm64-dts-allwinner-a64-Olinuxino-fix-DRAM-voltage.patch b/patch/kernel/sunxi-legacy/board-a64-v3-13-19-arm64-dts-allwinner-a64-Olinuxino-fix-DRAM-voltage.patch
deleted file mode 100644
index 0c6de7fe7..000000000
--- a/patch/kernel/sunxi-legacy/board-a64-v3-13-19-arm64-dts-allwinner-a64-Olinuxino-fix-DRAM-voltage.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
-index 3f531393eaee..b3f186434f36 100644
---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
-+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
-@@ -142,10 +142,14 @@
-
- /* DCDC3 is polyphased with DCDC2 */
-
-+/*
-+ * The board uses DDR3L DRAM chips. 1.36V is the closest to the nominal
-+ * 1.35V that the PMIC can drive.
-+ */
- ®_dcdc5 {
- regulator-always-on;
-- regulator-min-microvolt = <1500000>;
-- regulator-max-microvolt = <1500000>;
-+ regulator-min-microvolt = <1360000>;
-+ regulator-max-microvolt = <1360000>;
- regulator-name = "vcc-ddr3";
- };
-
diff --git a/patch/kernel/sunxi-legacy/board-a64-v3-16-19-arm64-dts-allwinner-a64-NanoPi-A64-Fix-DCDC1-voltage.patch b/patch/kernel/sunxi-legacy/board-a64-v3-16-19-arm64-dts-allwinner-a64-NanoPi-A64-Fix-DCDC1-voltage.patch
deleted file mode 100644
index c6a9c4cae..000000000
--- a/patch/kernel/sunxi-legacy/board-a64-v3-16-19-arm64-dts-allwinner-a64-NanoPi-A64-Fix-DCDC1-voltage.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts
-index 98dbff19f5cc..5caba225b4f7 100644
---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts
-+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts
-@@ -125,9 +125,9 @@
-
- ®_dcdc1 {
- regulator-always-on;
-- regulator-min-microvolt = <3000000>;
-- regulator-max-microvolt = <3000000>;
-- regulator-name = "vcc-3v";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ regulator-name = "vcc-3v3";
- };
-
- ®_dcdc2 {
diff --git a/patch/kernel/sunxi-legacy/board-a83t-v7-4-4-ARM-dts-sun8i-h3-h5-ir-register-size-should-be-the-whole-memory-block.patch b/patch/kernel/sunxi-legacy/board-a83t-v7-4-4-ARM-dts-sun8i-h3-h5-ir-register-size-should-be-the-whole-memory-block.patch
deleted file mode 100644
index 2a0897a8c..000000000
--- a/patch/kernel/sunxi-legacy/board-a83t-v7-4-4-ARM-dts-sun8i-h3-h5-ir-register-size-should-be-the-whole-memory-block.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
-index c3bff1105e5d..2f4d93de836e 100644
---- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
-+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
-@@ -818,7 +818,7 @@
- clock-names = "apb", "ir";
- resets = <&r_ccu RST_APB0_IR>;
- interrupts = ;
-- reg = <0x01f02000 0x40>;
-+ reg = <0x01f02000 0x400>;
- status = "disabled";
- };
-
diff --git a/patch/kernel/sunxi-legacy/general-spidev-remove-warnings.patch b/patch/kernel/sunxi-legacy/general-spidev-remove-warnings.patch
deleted file mode 100644
index 25648e844..000000000
--- a/patch/kernel/sunxi-legacy/general-spidev-remove-warnings.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
-index 9e2e099b..a065943d 100644
---- a/drivers/spi/spidev.c
-+++ b/drivers/spi/spidev.c
-@@ -749,13 +749,11 @@ static int spidev_probe(struct spi_device *spi)
-
- /*
- * spidev should never be referenced in DT without a specific
-- * compatible string, it is a Linux implementation thing
-- * rather than a description of the hardware.
-+ * compatible string, but people don't care and use DT overlays
-+ * to activate SPIdev on demand
- */
- if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) {
-- dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n");
-- WARN_ON(spi->dev.of_node &&
-- !of_match_device(spidev_dt_ids, &spi->dev));
-+ dev_info(&spi->dev, "probing from DT");
- }
-
- spidev_probe_acpi(spi);
diff --git a/patch/kernel/sunxi-legacy/wifi-add-xradio.patch b/patch/kernel/sunxi-legacy/wifi-add-xradio.patch
deleted file mode 100644
index 65d8da1d0..000000000
--- a/patch/kernel/sunxi-legacy/wifi-add-xradio.patch
+++ /dev/null
@@ -1,18808 +0,0 @@
-diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
-index 3d1ffcb..bed2537 100644
---- a/drivers/net/wireless/Kconfig
-+++ b/drivers/net/wireless/Kconfig
-@@ -45,6 +45,7 @@ source "drivers/net/wireless/realtek/Kconfig"
- source "drivers/net/wireless/rsi/Kconfig"
- source "drivers/net/wireless/st/Kconfig"
- source "drivers/net/wireless/ti/Kconfig"
-+source "drivers/net/wireless/xradio/Kconfig"
- source "drivers/net/wireless/zydas/Kconfig"
- source "drivers/net/wireless/quantenna/Kconfig"
- source "drivers/net/wireless/rtl8812au/Kconfig"
-diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
-index d0fbe9c..2442af0 100644
---- a/drivers/net/wireless/Makefile
-+++ b/drivers/net/wireless/Makefile
-@@ -18,6 +18,7 @@ obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/
- obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
- obj-$(CONFIG_WLAN_VENDOR_ST) += st/
- obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
-+obj-$(CONFIG_WLAN_VENDOR_XRADIO) += xradio/
- obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
- obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/
-
-diff --git a/drivers/net/wireless/xradio/.7z b/drivers/net/wireless/xradio/.7z
-new file mode 100644
-index 0000000..4f8fc9c
-Binary files /dev/null and b/drivers/net/wireless/xradio/.7z differ
-diff --git a/drivers/net/wireless/xradio/Kconfig b/drivers/net/wireless/xradio/Kconfig
-new file mode 100644
-index 0000000..18d1e2b
---- /dev/null
-+++ b/drivers/net/wireless/xradio/Kconfig
-@@ -0,0 +1,46 @@
-+config WLAN_VENDOR_XRADIO
-+ tristate "XRADIO WLAN support"
-+ depends on MAC80211
-+ default m
-+ help
-+
-+ This is an experimental driver for the XRADIO chip-set.
-+ Enabling this option enables the generic driver without
-+ any platform support.
-+ Please select the appropriate platform below.
-+
-+if WLAN_VENDOR_XRADIO
-+
-+config XRADIO_NON_POWER_OF_TWO_BLOCKSIZES
-+ bool "Platform supports non-power-of-two SDIO transfer"
-+ depends on WLAN_VENDOR_XRADIO
-+ default y
-+ ---help---
-+ Say N here only if you are running the driver on a platform
-+ which does not have support for non-power-of-two SDIO transfer.
-+ If unsure, say Y.
-+
-+config XRADIO_5GHZ_SUPPORT
-+ bool "5GHz band support"
-+ depends on WLAN_VENDOR_XRADIO
-+ default n
-+ ---help---
-+ Say Y if your device supports 5GHz band. If unsure, say N.
-+
-+config XRADIO_WAPI_SUPPORT
-+ bool "WAPI support"
-+ depends on WLAN_VENDOR_XRADIO
-+ default n
-+ ---help---
-+ Say Y if your compat-wireless support WAPI.
-+ If unsure, say N.
-+
-+config XRADIO_USE_EXTENSIONS
-+ bool "Extensions for WFD and PS mode"
-+ depends on WLAN_VENDOR_XRADIO
-+ default y
-+ ---help---
-+ Say Y if you want to include XR extensions
-+ If unsure, say Y.
-+
-+endif
-diff --git a/drivers/net/wireless/xradio/LICENSE b/drivers/net/wireless/xradio/LICENSE
-new file mode 100644
-index 0000000..23cb790
---- /dev/null
-+++ b/drivers/net/wireless/xradio/LICENSE
-@@ -0,0 +1,339 @@
-+ GNU GENERAL PUBLIC LICENSE
-+ Version 2, June 1991
-+
-+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+
-+ Preamble
-+
-+ The licenses for most software are designed to take away your
-+freedom to share and change it. By contrast, the GNU General Public
-+License is intended to guarantee your freedom to share and change free
-+software--to make sure the software is free for all its users. This
-+General Public License applies to most of the Free Software
-+Foundation's software and to any other program whose authors commit to
-+using it. (Some other Free Software Foundation software is covered by
-+the GNU Lesser General Public License instead.) You can apply it to
-+your programs, too.
-+
-+ When we speak of free software, we are referring to freedom, not
-+price. Our General Public Licenses are designed to make sure that you
-+have the freedom to distribute copies of free software (and charge for
-+this service if you wish), that you receive source code or can get it
-+if you want it, that you can change the software or use pieces of it
-+in new free programs; and that you know you can do these things.
-+
-+ To protect your rights, we need to make restrictions that forbid
-+anyone to deny you these rights or to ask you to surrender the rights.
-+These restrictions translate to certain responsibilities for you if you
-+distribute copies of the software, or if you modify it.
-+
-+ For example, if you distribute copies of such a program, whether
-+gratis or for a fee, you must give the recipients all the rights that
-+you have. You must make sure that they, too, receive or can get the
-+source code. And you must show them these terms so they know their
-+rights.
-+
-+ We protect your rights with two steps: (1) copyright the software, and
-+(2) offer you this license which gives you legal permission to copy,
-+distribute and/or modify the software.
-+
-+ Also, for each author's protection and ours, we want to make certain
-+that everyone understands that there is no warranty for this free
-+software. If the software is modified by someone else and passed on, we
-+want its recipients to know that what they have is not the original, so
-+that any problems introduced by others will not reflect on the original
-+authors' reputations.
-+
-+ Finally, any free program is threatened constantly by software
-+patents. We wish to avoid the danger that redistributors of a free
-+program will individually obtain patent licenses, in effect making the
-+program proprietary. To prevent this, we have made it clear that any
-+patent must be licensed for everyone's free use or not licensed at all.
-+
-+ The precise terms and conditions for copying, distribution and
-+modification follow.
-+
-+ GNU GENERAL PUBLIC LICENSE
-+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-+
-+ 0. This License applies to any program or other work which contains
-+a notice placed by the copyright holder saying it may be distributed
-+under the terms of this General Public License. The "Program", below,
-+refers to any such program or work, and a "work based on the Program"
-+means either the Program or any derivative work under copyright law:
-+that is to say, a work containing the Program or a portion of it,
-+either verbatim or with modifications and/or translated into another
-+language. (Hereinafter, translation is included without limitation in
-+the term "modification".) Each licensee is addressed as "you".
-+
-+Activities other than copying, distribution and modification are not
-+covered by this License; they are outside its scope. The act of
-+running the Program is not restricted, and the output from the Program
-+is covered only if its contents constitute a work based on the
-+Program (independent of having been made by running the Program).
-+Whether that is true depends on what the Program does.
-+
-+ 1. You may copy and distribute verbatim copies of the Program's
-+source code as you receive it, in any medium, provided that you
-+conspicuously and appropriately publish on each copy an appropriate
-+copyright notice and disclaimer of warranty; keep intact all the
-+notices that refer to this License and to the absence of any warranty;
-+and give any other recipients of the Program a copy of this License
-+along with the Program.
-+
-+You may charge a fee for the physical act of transferring a copy, and
-+you may at your option offer warranty protection in exchange for a fee.
-+
-+ 2. You may modify your copy or copies of the Program or any portion
-+of it, thus forming a work based on the Program, and copy and
-+distribute such modifications or work under the terms of Section 1
-+above, provided that you also meet all of these conditions:
-+
-+ a) You must cause the modified files to carry prominent notices
-+ stating that you changed the files and the date of any change.
-+
-+ b) You must cause any work that you distribute or publish, that in
-+ whole or in part contains or is derived from the Program or any
-+ part thereof, to be licensed as a whole at no charge to all third
-+ parties under the terms of this License.
-+
-+ c) If the modified program normally reads commands interactively
-+ when run, you must cause it, when started running for such
-+ interactive use in the most ordinary way, to print or display an
-+ announcement including an appropriate copyright notice and a
-+ notice that there is no warranty (or else, saying that you provide
-+ a warranty) and that users may redistribute the program under
-+ these conditions, and telling the user how to view a copy of this
-+ License. (Exception: if the Program itself is interactive but
-+ does not normally print such an announcement, your work based on
-+ the Program is not required to print an announcement.)
-+
-+These requirements apply to the modified work as a whole. If
-+identifiable sections of that work are not derived from the Program,
-+and can be reasonably considered independent and separate works in
-+themselves, then this License, and its terms, do not apply to those
-+sections when you distribute them as separate works. But when you
-+distribute the same sections as part of a whole which is a work based
-+on the Program, the distribution of the whole must be on the terms of
-+this License, whose permissions for other licensees extend to the
-+entire whole, and thus to each and every part regardless of who wrote it.
-+
-+Thus, it is not the intent of this section to claim rights or contest
-+your rights to work written entirely by you; rather, the intent is to
-+exercise the right to control the distribution of derivative or
-+collective works based on the Program.
-+
-+In addition, mere aggregation of another work not based on the Program
-+with the Program (or with a work based on the Program) on a volume of
-+a storage or distribution medium does not bring the other work under
-+the scope of this License.
-+
-+ 3. You may copy and distribute the Program (or a work based on it,
-+under Section 2) in object code or executable form under the terms of
-+Sections 1 and 2 above provided that you also do one of the following:
-+
-+ a) Accompany it with the complete corresponding machine-readable
-+ source code, which must be distributed under the terms of Sections
-+ 1 and 2 above on a medium customarily used for software interchange; or,
-+
-+ b) Accompany it with a written offer, valid for at least three
-+ years, to give any third party, for a charge no more than your
-+ cost of physically performing source distribution, a complete
-+ machine-readable copy of the corresponding source code, to be
-+ distributed under the terms of Sections 1 and 2 above on a medium
-+ customarily used for software interchange; or,
-+
-+ c) Accompany it with the information you received as to the offer
-+ to distribute corresponding source code. (This alternative is
-+ allowed only for noncommercial distribution and only if you
-+ received the program in object code or executable form with such
-+ an offer, in accord with Subsection b above.)
-+
-+The source code for a work means the preferred form of the work for
-+making modifications to it. For an executable work, complete source
-+code means all the source code for all modules it contains, plus any
-+associated interface definition files, plus the scripts used to
-+control compilation and installation of the executable. However, as a
-+special exception, the source code distributed need not include
-+anything that is normally distributed (in either source or binary
-+form) with the major components (compiler, kernel, and so on) of the
-+operating system on which the executable runs, unless that component
-+itself accompanies the executable.
-+
-+If distribution of executable or object code is made by offering
-+access to copy from a designated place, then offering equivalent
-+access to copy the source code from the same place counts as
-+distribution of the source code, even though third parties are not
-+compelled to copy the source along with the object code.
-+
-+ 4. You may not copy, modify, sublicense, or distribute the Program
-+except as expressly provided under this License. Any attempt
-+otherwise to copy, modify, sublicense or distribute the Program is
-+void, and will automatically terminate your rights under this License.
-+However, parties who have received copies, or rights, from you under
-+this License will not have their licenses terminated so long as such
-+parties remain in full compliance.
-+
-+ 5. You are not required to accept this License, since you have not
-+signed it. However, nothing else grants you permission to modify or
-+distribute the Program or its derivative works. These actions are
-+prohibited by law if you do not accept this License. Therefore, by
-+modifying or distributing the Program (or any work based on the
-+Program), you indicate your acceptance of this License to do so, and
-+all its terms and conditions for copying, distributing or modifying
-+the Program or works based on it.
-+
-+ 6. Each time you redistribute the Program (or any work based on the
-+Program), the recipient automatically receives a license from the
-+original licensor to copy, distribute or modify the Program subject to
-+these terms and conditions. You may not impose any further
-+restrictions on the recipients' exercise of the rights granted herein.
-+You are not responsible for enforcing compliance by third parties to
-+this License.
-+
-+ 7. If, as a consequence of a court judgment or allegation of patent
-+infringement or for any other reason (not limited to patent issues),
-+conditions are imposed on you (whether by court order, agreement or
-+otherwise) that contradict the conditions of this License, they do not
-+excuse you from the conditions of this License. If you cannot
-+distribute so as to satisfy simultaneously your obligations under this
-+License and any other pertinent obligations, then as a consequence you
-+may not distribute the Program at all. For example, if a patent
-+license would not permit royalty-free redistribution of the Program by
-+all those who receive copies directly or indirectly through you, then
-+the only way you could satisfy both it and this License would be to
-+refrain entirely from distribution of the Program.
-+
-+If any portion of this section is held invalid or unenforceable under
-+any particular circumstance, the balance of the section is intended to
-+apply and the section as a whole is intended to apply in other
-+circumstances.
-+
-+It is not the purpose of this section to induce you to infringe any
-+patents or other property right claims or to contest validity of any
-+such claims; this section has the sole purpose of protecting the
-+integrity of the free software distribution system, which is
-+implemented by public license practices. Many people have made
-+generous contributions to the wide range of software distributed
-+through that system in reliance on consistent application of that
-+system; it is up to the author/donor to decide if he or she is willing
-+to distribute software through any other system and a licensee cannot
-+impose that choice.
-+
-+This section is intended to make thoroughly clear what is believed to
-+be a consequence of the rest of this License.
-+
-+ 8. If the distribution and/or use of the Program is restricted in
-+certain countries either by patents or by copyrighted interfaces, the
-+original copyright holder who places the Program under this License
-+may add an explicit geographical distribution limitation excluding
-+those countries, so that distribution is permitted only in or among
-+countries not thus excluded. In such case, this License incorporates
-+the limitation as if written in the body of this License.
-+
-+ 9. The Free Software Foundation may publish revised and/or new versions
-+of the General Public License from time to time. Such new versions will
-+be similar in spirit to the present version, but may differ in detail to
-+address new problems or concerns.
-+
-+Each version is given a distinguishing version number. If the Program
-+specifies a version number of this License which applies to it and "any
-+later version", you have the option of following the terms and conditions
-+either of that version or of any later version published by the Free
-+Software Foundation. If the Program does not specify a version number of
-+this License, you may choose any version ever published by the Free Software
-+Foundation.
-+
-+ 10. If you wish to incorporate parts of the Program into other free
-+programs whose distribution conditions are different, write to the author
-+to ask for permission. For software which is copyrighted by the Free
-+Software Foundation, write to the Free Software Foundation; we sometimes
-+make exceptions for this. Our decision will be guided by the two goals
-+of preserving the free status of all derivatives of our free software and
-+of promoting the sharing and reuse of software generally.
-+
-+ NO WARRANTY
-+
-+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-+REPAIR OR CORRECTION.
-+
-+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-+POSSIBILITY OF SUCH DAMAGES.
-+
-+ END OF TERMS AND CONDITIONS
-+
-+ How to Apply These Terms to Your New Programs
-+
-+ If you develop a new program, and you want it to be of the greatest
-+possible use to the public, the best way to achieve this is to make it
-+free software which everyone can redistribute and change under these terms.
-+
-+ To do so, attach the following notices to the program. It is safest
-+to attach them to the start of each source file to most effectively
-+convey the exclusion of warranty; and each file should have at least
-+the "copyright" line and a pointer to where the full notice is found.
-+
-+ {description}
-+ Copyright (C) {year} {fullname}
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License along
-+ with this program; if not, write to the Free Software Foundation, Inc.,
-+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-+
-+Also add information on how to contact you by electronic and paper mail.
-+
-+If the program is interactive, make it output a short notice like this
-+when it starts in an interactive mode:
-+
-+ Gnomovision version 69, Copyright (C) year name of author
-+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-+ This is free software, and you are welcome to redistribute it
-+ under certain conditions; type `show c' for details.
-+
-+The hypothetical commands `show w' and `show c' should show the appropriate
-+parts of the General Public License. Of course, the commands you use may
-+be called something other than `show w' and `show c'; they could even be
-+mouse-clicks or menu items--whatever suits your program.
-+
-+You should also get your employer (if you work as a programmer) or your
-+school, if any, to sign a "copyright disclaimer" for the program, if
-+necessary. Here is a sample; alter the names:
-+
-+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
-+
-+ {signature of Ty Coon}, 1 April 1989
-+ Ty Coon, President of Vice
-+
-+This General Public License does not permit incorporating your program into
-+proprietary programs. If your program is a subroutine library, you may
-+consider it more useful to permit linking proprietary applications with the
-+library. If this is what you want to do, use the GNU Lesser General
-+Public License instead of this License.
-diff --git a/drivers/net/wireless/xradio/Makefile b/drivers/net/wireless/xradio/Makefile
-new file mode 100644
-index 0000000..80a9a14
---- /dev/null
-+++ b/drivers/net/wireless/xradio/Makefile
-@@ -0,0 +1,54 @@
-+# Standalone Makefile - uncomment for out-of-tree compilation
-+#CONFIG_WLAN_VENDOR_XRADIO := m
-+#CONFIG_XRADIO_USE_EXTENSIONS := y
-+#CONFIG_XRADIO_WAPI_SUPPORT := n
-+
-+# Kernel part
-+
-+obj-$(CONFIG_WLAN_VENDOR_XRADIO) += xradio_wlan.o
-+
-+xradio_wlan-objs := \
-+ fwio.o \
-+ tx.o \
-+ rx.o \
-+ main.o \
-+ queue.o \
-+ hwio.o \
-+ bh.o \
-+ wsm.o \
-+ sta.o \
-+ ap.o \
-+ keys.o \
-+ scan.o \
-+ module.o \
-+ sdio.o \
-+ pm.o \
-+ ht.o \
-+ p2p.o
-+
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DMCAST_FWDING
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DXRADIO_SUSPEND_RESUME_FILTER_ENABLE
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DAP_AGGREGATE_FW_FIX
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DAP_HT_CAP_UPDATE
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DAP_HT_COMPAT_FIX
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DCONFIG_XRADIO_DUMP_ON_ERROR
-+
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DCONFIG_XRADIO_SUSPEND_POWER_OFF
-+
-+# Extra IE for probe response from upper layer is needed in P2P GO
-+# For offloading probe response to FW, the extra IE must be included
-+# in the probe response template
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DPROBE_RESP_EXTRA_IE
-+
-+# Modified by wzw
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DTES_P2P_0002_ROC_RESTART
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DTES_P2P_000B_EXTEND_INACTIVITY_CNT
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DTES_P2P_000B_DISABLE_EAPOL_FILTER
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DXRADIO_USE_LONG_DTIM_PERIOD
-+ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DXRADIO_USE_LONG_KEEP_ALIVE_PERIOD
-+
-+#ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DDEBUG
-+#ccflags-$(CONFIG_WLAN_VENDOR_XRADIO) += -DXRADIO_DISABLE_HW_CRYPTO
-+
-+ldflags-$(CONFIG_WLAN_VENDOR_XRADIO) += --strip-debug
-+
-diff --git a/drivers/net/wireless/xradio/ap.c b/drivers/net/wireless/xradio/ap.c
-new file mode 100644
-index 0000000..5276c5a
---- /dev/null
-+++ b/drivers/net/wireless/xradio/ap.c
-@@ -0,0 +1,1624 @@
-+/*
-+ * STA and AP APIs for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "xradio.h"
-+#include "sta.h"
-+#include "ap.h"
-+#include "bh.h"
-+#include "net/mac80211.h"
-+
-+#define XRADIO_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ))
-+#define XRADIO_ENABLE_ARP_FILTER_OFFLOAD 3
-+
-+#ifndef ERP_INFO_BYTE_OFFSET
-+#define ERP_INFO_BYTE_OFFSET 2
-+#endif
-+
-+static int xradio_upload_beacon(struct xradio_vif *priv);
-+#ifdef PROBE_RESP_EXTRA_IE
-+static int xradio_upload_proberesp(struct xradio_vif *priv);
-+#endif
-+static int xradio_upload_pspoll(struct xradio_vif *priv);
-+static int xradio_upload_null(struct xradio_vif *priv);
-+static int xradio_upload_qosnull(struct xradio_vif *priv);
-+static int xradio_start_ap(struct xradio_vif *priv);
-+static int xradio_update_beaconing(struct xradio_vif *priv);
-+/*
-+static int xradio_enable_beaconing(struct xradio_vif *priv,
-+ bool enable);
-+*/
-+static void __xradio_sta_notify(struct xradio_vif *priv,
-+ enum sta_notify_cmd notify_cmd,
-+ int link_id);
-+
-+/* ******************************************************************** */
-+/* AP API */
-+int xradio_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
-+{
-+ struct xradio_sta_priv *sta_priv = (struct xradio_sta_priv *)&sta->drv_priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct xradio_link_entry *entry;
-+ struct sk_buff *skb;
-+#ifdef AP_AGGREGATE_FW_FIX
-+ struct xradio_common *hw_priv = hw->priv;
-+#endif
-+
-+ if (priv->mode != NL80211_IFTYPE_AP) {
-+ return 0;
-+ }
-+
-+ sta_priv->priv = priv;
-+ sta_priv->link_id = xradio_find_link_id(priv, sta->addr);
-+ if (WARN_ON(!sta_priv->link_id)) {
-+ /* Impossible error */
-+ wiphy_debug(hw->wiphy, "No more link IDs available.\n");
-+ return -ENOENT;
-+ }
-+
-+ entry = &priv->link_id_db[sta_priv->link_id - 1];
-+ spin_lock_bh(&priv->ps_state_lock);
-+ if ((sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) ==
-+ IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) {
-+ priv->sta_asleep_mask |= BIT(sta_priv->link_id);
-+ }
-+ entry->status = XRADIO_LINK_HARD;
-+ while ((skb = skb_dequeue(&entry->rx_queue)))
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+#ifdef AP_AGGREGATE_FW_FIX
-+ hw_priv->connected_sta_cnt++;
-+ if(hw_priv->connected_sta_cnt>1) {
-+ wsm_lock_tx(hw_priv);
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
-+ XRADIO_RX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
-+ priv->if_id));
-+ wsm_unlock_tx(hw_priv);
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+int xradio_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_sta_priv *sta_priv =
-+ (struct xradio_sta_priv *)&sta->drv_priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct xradio_link_entry *entry;
-+
-+ if (priv->mode != NL80211_IFTYPE_AP || !sta_priv->link_id) {
-+ wiphy_warn(hw->wiphy, "no station to remove\n");
-+ return 0;
-+ }
-+
-+ entry = &priv->link_id_db[sta_priv->link_id - 1];
-+ spin_lock_bh(&priv->ps_state_lock);
-+ entry->status = XRADIO_LINK_RESERVE;
-+ entry->timestamp = jiffies;
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->link_id_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ flush_workqueue(hw_priv->workqueue);
-+
-+#ifdef AP_AGGREGATE_FW_FIX
-+ hw_priv->connected_sta_cnt--;
-+ if(hw_priv->connected_sta_cnt <= 1) {
-+ if ((priv->if_id != 1) ||
-+ ((priv->if_id == 1) && hw_priv->is_go_thru_go_neg)) {
-+ wsm_lock_tx(hw_priv);
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
-+ XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
-+ priv->if_id));
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+static void __xradio_sta_notify(struct xradio_vif *priv,
-+ enum sta_notify_cmd notify_cmd,
-+ int link_id)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u32 bit, prev;
-+
-+ /* Zero link id means "for all link IDs" */
-+ if (link_id)
-+ bit = BIT(link_id);
-+ else if (WARN_ON_ONCE(notify_cmd != STA_NOTIFY_AWAKE))
-+ bit = 0;
-+ else
-+ bit = priv->link_id_map;
-+ prev = priv->sta_asleep_mask & bit;
-+
-+ switch (notify_cmd) {
-+ case STA_NOTIFY_SLEEP:
-+ if (!prev) {
-+ if (priv->buffered_multicasts &&
-+ !priv->sta_asleep_mask)
-+ queue_work(hw_priv->workqueue,
-+ &priv->multicast_start_work);
-+ priv->sta_asleep_mask |= bit;
-+ }
-+ break;
-+ case STA_NOTIFY_AWAKE:
-+ if (prev) {
-+ priv->sta_asleep_mask &= ~bit;
-+ priv->pspoll_mask &= ~bit;
-+ if (priv->tx_multicast && link_id &&
-+ !priv->sta_asleep_mask)
-+ queue_work(hw_priv->workqueue,
-+ &priv->multicast_stop_work);
-+ xradio_bh_wakeup(hw_priv);
-+ }
-+ break;
-+ }
-+}
-+
-+void xradio_sta_notify(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ enum sta_notify_cmd notify_cmd,
-+ struct ieee80211_sta *sta)
-+{
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct xradio_sta_priv *sta_priv = (struct xradio_sta_priv *)&sta->drv_priv;
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ __xradio_sta_notify(priv, notify_cmd, sta_priv->link_id);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+}
-+
-+static void xradio_ps_notify(struct xradio_vif *priv,
-+ int link_id, bool ps)
-+{
-+ if (link_id > MAX_STA_IN_AP_MODE) {
-+ ap_printk(XRADIO_DBG_WARN,"link_id is invalid=%d\n", link_id);
-+ return;
-+ }
-+
-+ ap_printk(XRADIO_DBG_NIY, "%s for LinkId: %d. STAs asleep: %.8X\n",
-+ ps ? "Stop" : "Start", link_id, priv->sta_asleep_mask);
-+
-+ /* TODO:COMBO: __xradio_sta_notify changed. */
-+ __xradio_sta_notify(priv, ps ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE, link_id);
-+}
-+
-+static int xradio_set_tim_impl(struct xradio_vif *priv, bool aid0_bit_set)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct sk_buff *skb;
-+ struct wsm_update_ie update_ie = {
-+ .what = WSM_UPDATE_IE_BEACON,
-+ .count = 1,
-+ };
-+ u16 tim_offset, tim_length;
-+ ap_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+ ap_printk(XRADIO_DBG_MSG, "%s mcast: %s.\n", __func__,
-+ aid0_bit_set ? "ena" : "dis");
-+
-+ skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, &tim_offset, &tim_length);
-+ if (!skb) {
-+ __xradio_flush(hw_priv, true, priv->if_id);
-+ return -ENOENT;
-+ }
-+
-+ if (tim_offset && tim_length >= 6) {
-+ /* Ignore DTIM count from mac80211:
-+ * firmware handles DTIM internally. */
-+ skb->data[tim_offset + 2] = 0;
-+
-+ /* Set/reset aid0 bit */
-+ if (aid0_bit_set)
-+ skb->data[tim_offset + 4] |= 1;
-+ else
-+ skb->data[tim_offset + 4] &= ~1;
-+ }
-+
-+ update_ie.ies = &skb->data[tim_offset];
-+ update_ie.length = tim_length;
-+ //filter same tim info, yangfh
-+ if(memcmp(priv->last_tim, update_ie.ies, tim_length)) {
-+ WARN_ON(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
-+ memcpy(priv->last_tim, update_ie.ies, tim_length);
-+ ap_printk(XRADIO_DBG_MSG,"%02x %02x %02x %02x %02x %02x\n",
-+ update_ie.ies[0], update_ie.ies[1], update_ie.ies[2],
-+ update_ie.ies[3], update_ie.ies[4], update_ie.ies[5]);
-+ }
-+
-+ dev_kfree_skb(skb);
-+
-+ return 0;
-+}
-+
-+void xradio_set_tim_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv = container_of(work, struct xradio_vif, set_tim_work);
-+ xradio_set_tim_impl(priv, priv->aid0_bit_set);
-+}
-+
-+int xradio_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
-+ bool set)
-+{
-+ struct xradio_sta_priv *sta_priv = (struct xradio_sta_priv *)&sta->drv_priv;
-+ struct xradio_vif *priv = sta_priv->priv;
-+
-+ WARN_ON(priv->mode != NL80211_IFTYPE_AP);
-+ queue_work(priv->hw_priv->workqueue, &priv->set_tim_work);
-+ return 0;
-+}
-+
-+void xradio_set_cts_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, set_cts_work.work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u8 erp_ie[3] = {WLAN_EID_ERP_INFO, 0x1, 0};
-+ struct wsm_update_ie update_ie = {
-+ .what = WSM_UPDATE_IE_BEACON,
-+ .count = 1,
-+ .ies = erp_ie,
-+ .length = 3,
-+ };
-+ u32 erp_info;
-+ __le32 use_cts_prot;
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ erp_info = priv->erp_info;
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ use_cts_prot = (erp_info & WLAN_ERP_USE_PROTECTION)? __cpu_to_le32(1) : 0;
-+
-+ erp_ie[ERP_INFO_BYTE_OFFSET] = erp_info;
-+
-+ ap_printk(XRADIO_DBG_MSG, "ERP information 0x%x\n", erp_info);
-+
-+ /* TODO:COMBO: If 2 interfaces are on the same channel they share
-+ the same ERP values */
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_NON_ERP_PROTECTION,
-+ &use_cts_prot, sizeof(use_cts_prot), priv->if_id));
-+ /* If STA Mode update_ie is not required */
-+ if (priv->mode != NL80211_IFTYPE_STATION) {
-+ WARN_ON(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
-+ }
-+
-+ return;
-+}
-+
-+static int xradio_set_btcoexinfo(struct xradio_vif *priv)
-+{
-+ struct wsm_override_internal_txrate arg;
-+ int ret = 0;
-+
-+ if (priv->mode == NL80211_IFTYPE_STATION) {
-+ /* Plumb PSPOLL and NULL template */
-+ WARN_ON(xradio_upload_pspoll(priv));
-+ WARN_ON(xradio_upload_null(priv));
-+ } else {
-+ return 0;
-+ }
-+
-+ memset(&arg, 0, sizeof(struct wsm_override_internal_txrate));
-+
-+ if (!priv->vif->p2p) {
-+ /* STATION mode */
-+ if (priv->bss_params.operationalRateSet & ~0xF) {
-+ ap_printk(XRADIO_DBG_NIY, "STA has ERP rates\n");
-+ /* G or BG mode */
-+ arg.internalTxRate = (__ffs(
-+ priv->bss_params.operationalRateSet & ~0xF));
-+ } else {
-+ ap_printk(XRADIO_DBG_NIY, "STA has non ERP rates\n");
-+ /* B only mode */
-+ arg.internalTxRate = (__ffs(
-+ priv->association_mode.basicRateSet));
-+ }
-+ arg.nonErpInternalTxRate = (__ffs(
-+ priv->association_mode.basicRateSet));
-+ } else {
-+ /* P2P mode */
-+ arg.internalTxRate = (__ffs(
-+ priv->bss_params.operationalRateSet & ~0xF));
-+ arg.nonErpInternalTxRate = (__ffs(
-+ priv->bss_params.operationalRateSet & ~0xF));
-+ }
-+
-+ ap_printk(XRADIO_DBG_NIY, "BTCOEX_INFO" "MODE %d, internalTxRate : %x,"
-+ "nonErpInternalTxRate: %x\n", priv->mode, arg.internalTxRate,
-+ arg.nonErpInternalTxRate);
-+
-+ ret = WARN_ON(wsm_write_mib(xrwl_vifpriv_to_hwpriv(priv),
-+ WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE,
-+ &arg, sizeof(arg), priv->if_id));
-+
-+ return ret;
-+}
-+
-+void xradio_bss_info_changed(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_bss_conf *info,
-+ u32 changed)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (changed & BSS_CHANGED_BSSID) {
-+ memcpy(priv->bssid, info->bssid, ETH_ALEN);
-+ xradio_setup_mac_pvif(priv);
-+ }
-+
-+ /* TODO: BSS_CHANGED_IBSS */
-+ if (changed & BSS_CHANGED_ARP_FILTER) {
-+ struct wsm_arp_ipv4_filter filter = {0};
-+ int i;
-+ ap_printk(XRADIO_DBG_MSG, "[STA] BSS_CHANGED_ARP_FILTER cnt: %d\n",
-+ info->arp_addr_cnt);
-+
-+ if (info->arp_addr_cnt){
-+ if (vif->type == NL80211_IFTYPE_STATION)
-+ filter.enable = (u32)XRADIO_ENABLE_ARP_FILTER_OFFLOAD;
-+ else if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ filter.enable = (u32)(1<<1);
-+ else
-+ filter.enable = 0;
-+ }
-+
-+ /* Currently only one IP address is supported by firmware.
-+ * In case of more IPs arp filtering will be disabled. */
-+ if (info->arp_addr_cnt > 0 &&
-+ info->arp_addr_cnt <= WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES) {
-+ for (i = 0; i < info->arp_addr_cnt; i++) {
-+ filter.ipv4Address[i] = info->arp_addr_list[i];
-+ ap_printk(XRADIO_DBG_NIY, "[STA]addr[%d]: 0x%X\n", i, filter.ipv4Address[i]);
-+ }
-+ } else
-+ filter.enable = 0;
-+
-+ if (filter.enable)
-+ xradio_set_arpreply(dev, vif);
-+
-+ priv->filter4.enable = filter.enable;
-+ ap_printk(XRADIO_DBG_NIY, "[STA]arp ip filter enable: %d\n", __le32_to_cpu(filter.enable));
-+
-+ if (wsm_set_arp_ipv4_filter(hw_priv, &filter, priv->if_id))
-+ WARN_ON(1);
-+
-+ if (filter.enable &&
-+ (priv->join_status == XRADIO_JOIN_STATUS_STA)) {
-+ /* Firmware requires that value for this 1-byte field must
-+ * be specified in units of 500us. Values above the 128ms
-+ * threshold are not supported. */
-+ //if (info->dynamic_ps_timeout >= 0x80)
-+ // priv->powersave_mode.fastPsmIdlePeriod = 0xFF;
-+ //else
-+ // priv->powersave_mode.fastPsmIdlePeriod = info->dynamic_ps_timeout << 1;
-+
-+ priv->powersave_mode.fastPsmIdlePeriod = 200;//when connected,the dev->conf.dynamic_ps_timeout value is 0
-+ priv->powersave_mode.apPsmChangePeriod = 200; //100ms, add by yangfh
-+ ap_printk(XRADIO_DBG_NIY, "[STA]fastPsmIdle=%d, apPsmChange=%d\n",
-+ priv->powersave_mode.fastPsmIdlePeriod,
-+ priv->powersave_mode.apPsmChangePeriod);
-+
-+ if (priv->setbssparams_done) {
-+ int ret = 0;
-+ struct wsm_set_pm pm = priv->powersave_mode;
-+ if (priv->user_power_set_true)
-+ priv->powersave_mode.pmMode = priv->user_pm_mode;
-+ else if ((priv->power_set_true &&
-+ ((priv->powersave_mode.pmMode == WSM_PSM_ACTIVE) ||
-+ (priv->powersave_mode.pmMode == WSM_PSM_PS))) ||
-+ !priv->power_set_true)
-+ priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
-+
-+ ret = xradio_set_pm (priv, &priv->powersave_mode);
-+ if(ret)
-+ priv->powersave_mode = pm;
-+ } else {
-+ priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
-+ }
-+ priv->power_set_true = 0;
-+ priv->user_power_set_true = 0;
-+ }
-+ }
-+
-+ if (changed & BSS_CHANGED_BEACON) {
-+ ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_BEACON\n");
-+#ifdef HIDDEN_SSID
-+ if(priv->join_status != XRADIO_JOIN_STATUS_AP) {
-+ priv->hidden_ssid = info->hidden_ssid;
-+ priv->ssid_length = info->ssid_len;
-+ memcpy(priv->ssid, info->ssid, info->ssid_len);
-+ } else
-+ ap_printk(XRADIO_DBG_NIY, "priv->join_status=%d\n", priv->join_status);
-+#endif
-+ WARN_ON(xradio_upload_beacon(priv));
-+ WARN_ON(xradio_update_beaconing(priv));
-+ }
-+
-+ if (changed & BSS_CHANGED_BEACON_ENABLED) {
-+ ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_BEACON_ENABLED dummy\n");
-+ priv->enable_beacon = info->enable_beacon;
-+ }
-+
-+ if (changed & BSS_CHANGED_BEACON_INT) {
-+ ap_printk(XRADIO_DBG_NIY, "CHANGED_BEACON_INT\n");
-+ /* Restart AP only when connected */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(xradio_update_beaconing(priv));
-+ }
-+
-+
-+ if (changed & BSS_CHANGED_ASSOC) {
-+ wsm_lock_tx(hw_priv);
-+ priv->wep_default_key_id = -1;
-+ wsm_unlock_tx(hw_priv);
-+
-+ if (!info->assoc /* && !info->ibss_joined */) {
-+ priv->cqm_link_loss_count = XRADIO_LINK_LOSS_THOLD_DEF;
-+ priv->cqm_beacon_loss_count = XRADIO_BSS_LOSS_THOLD_DEF;
-+ priv->cqm_tx_failure_thold = 0;
-+ }
-+ priv->cqm_tx_failure_count = 0;
-+ }
-+
-+ if (changed &
-+ (BSS_CHANGED_ASSOC |
-+ BSS_CHANGED_BASIC_RATES |
-+ BSS_CHANGED_ERP_PREAMBLE |
-+ BSS_CHANGED_HT |
-+ BSS_CHANGED_ERP_SLOT)) {
-+ int is_combo = 0;
-+ int i;
-+ struct xradio_vif *tmp_priv;
-+ ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_ASSOC.\n");
-+ if (info->assoc) { /* TODO: ibss_joined */
-+ struct ieee80211_sta *sta = NULL;
-+ if (info->dtim_period)
-+ priv->join_dtim_period = info->dtim_period;
-+ priv->beacon_int = info->beacon_int;
-+
-+ /* Associated: kill join timeout */
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+
-+ rcu_read_lock();
-+ if (info->bssid)
-+ sta = ieee80211_find_sta(vif, info->bssid);
-+ if (sta) {
-+ /* TODO:COMBO:Change this once
-+ * mac80211 changes are available */
-+ BUG_ON(!hw_priv->channel);
-+ hw_priv->ht_oper.ht_cap = sta->ht_cap;
-+ priv->bss_params.operationalRateSet =__cpu_to_le32(
-+ xradio_rate_mask_to_wsm(hw_priv, sta->supp_rates[hw_priv->channel->band]));
-+ /* TODO by Icenowy: I think this may lead to some problems. */
-+// hw_priv->ht_oper.channel_type = info->channel_type;
-+ hw_priv->ht_oper.operation_mode = info->ht_operation_mode;
-+ } else {
-+ memset(&hw_priv->ht_oper, 0, sizeof(hw_priv->ht_oper));
-+ priv->bss_params.operationalRateSet = -1;
-+ }
-+ rcu_read_unlock();
-+ priv->htcap = (sta && xradio_is_ht(&hw_priv->ht_oper));
-+ xradio_for_each_vif(hw_priv, tmp_priv, i) {
-+ if (!tmp_priv)
-+ continue;
-+ if (tmp_priv->join_status >= XRADIO_JOIN_STATUS_STA)
-+ is_combo++;
-+ }
-+
-+ if (is_combo > 1) {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ ap_printk(XRADIO_DBG_WARN, "%sASSOC is_combo %d\n",
-+ (priv->join_status == XRADIO_JOIN_STATUS_STA)?"[STA] ":"",
-+ hw_priv->vif0_throttle);
-+ } else if ((priv->join_status == XRADIO_JOIN_STATUS_STA) && priv->htcap) {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11N_THROTTLE;
-+ ap_printk(XRADIO_DBG_WARN, "[STA] ASSOC HTCAP 11N %d\n",hw_priv->vif0_throttle);
-+ } else {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ ap_printk(XRADIO_DBG_WARN, "ASSOC not_combo 11BG %d\n",hw_priv->vif0_throttle);
-+ }
-+
-+ if (sta) {
-+ __le32 val = 0;
-+ if (hw_priv->ht_oper.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) {
-+ ap_printk(XRADIO_DBG_NIY,"[STA] Non-GF STA present\n");
-+ /* Non Green field capable STA */
-+ val = __cpu_to_le32(BIT(1));
-+ }
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MID_ID_SET_HT_PROTECTION,
-+ &val, sizeof(val), priv->if_id));
-+ }
-+
-+ priv->association_mode.greenfieldMode = xradio_ht_greenfield(&hw_priv->ht_oper);
-+ priv->association_mode.flags =
-+ WSM_ASSOCIATION_MODE_SNOOP_ASSOC_FRAMES |
-+ WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE |
-+ WSM_ASSOCIATION_MODE_USE_HT_MODE |
-+ WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET |
-+ WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING;
-+
-+ priv->association_mode.preambleType =
-+ (info->use_short_preamble ? WSM_JOIN_PREAMBLE_SHORT : WSM_JOIN_PREAMBLE_LONG);
-+ priv->association_mode.basicRateSet = __cpu_to_le32(
-+ xradio_rate_mask_to_wsm(hw_priv,info->basic_rates));
-+ priv->association_mode.mpduStartSpacing =
-+ xradio_ht_ampdu_density(&hw_priv->ht_oper);
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //priv->cqm_beacon_loss_count = info->cqm_beacon_miss_thold;
-+ //priv->cqm_tx_failure_thold = info->cqm_tx_fail_thold;
-+ //priv->cqm_tx_failure_count = 0;
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+
-+ priv->bss_params.beaconLostCount = (priv->cqm_beacon_loss_count ?
-+ priv->cqm_beacon_loss_count : priv->cqm_link_loss_count);
-+
-+ priv->bss_params.aid = info->aid;
-+
-+ if (priv->join_dtim_period < 1)
-+ priv->join_dtim_period = 1;
-+
-+ ap_printk(XRADIO_DBG_MSG, "[STA] DTIM %d, interval: %d\n",
-+ priv->join_dtim_period, priv->beacon_int);
-+ ap_printk(XRADIO_DBG_MSG, "[STA] Preamble: %d, " \
-+ "Greenfield: %d, Aid: %d, Rates: 0x%.8X, Basic: 0x%.8X\n",
-+ priv->association_mode.preambleType,
-+ priv->association_mode.greenfieldMode,
-+ priv->bss_params.aid,
-+ priv->bss_params.operationalRateSet,
-+ priv->association_mode.basicRateSet);
-+ WARN_ON(wsm_set_association_mode(hw_priv, &priv->association_mode, priv->if_id));
-+ WARN_ON(wsm_keep_alive_period(hw_priv, XRADIO_KEEP_ALIVE_PERIOD /* sec */,
-+ priv->if_id));
-+ WARN_ON(wsm_set_bss_params(hw_priv, &priv->bss_params, priv->if_id));
-+ priv->setbssparams_done = true;
-+#ifdef XRADIO_USE_LONG_DTIM_PERIOD
-+{
-+ int join_dtim_period_extend;
-+ if (priv->join_dtim_period <= 3) {
-+ join_dtim_period_extend = priv->join_dtim_period * 3;
-+ } else if (priv->join_dtim_period <= 5) {
-+ join_dtim_period_extend = priv->join_dtim_period * 2;
-+ } else {
-+ join_dtim_period_extend = priv->join_dtim_period;
-+ }
-+ WARN_ON(wsm_set_beacon_wakeup_period(hw_priv,
-+ ((priv->beacon_int * join_dtim_period_extend) > MAX_BEACON_SKIP_TIME_MS
-+ ? 1 : join_dtim_period_extend) , 0, priv->if_id));
-+}
-+#else
-+ WARN_ON(wsm_set_beacon_wakeup_period(hw_priv,
-+ ((priv->beacon_int * priv->join_dtim_period) > MAX_BEACON_SKIP_TIME_MS
-+ ? 1 : priv->join_dtim_period) , 0, priv->if_id));
-+#endif
-+ if (priv->htcap) {
-+ wsm_lock_tx(hw_priv);
-+ /* Statically enabling block ack for TX/RX */
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv, hw_priv->ba_tid_mask,
-+ hw_priv->ba_tid_mask, priv->if_id));
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ /*set ps active,avoid that when connecting process,the device sleeps,then can't receive pkts.*/
-+ if (changed & BSS_CHANGED_ASSOC)
-+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+ if (priv->vif->p2p) {
-+ ap_printk(XRADIO_DBG_NIY, "[STA] Setting p2p powersave configuration.\n");
-+ WARN_ON(wsm_set_p2p_ps_modeinfo(hw_priv, &priv->p2p_ps_modeinfo, priv->if_id));
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //xradio_notify_noa(priv, XRADIO_NOA_NOTIFICATION_DELAY);
-+#endif
-+ }
-+
-+ if (priv->mode == NL80211_IFTYPE_STATION)
-+ WARN_ON(xradio_upload_qosnull(priv));
-+
-+ if (hw_priv->is_BT_Present)
-+ WARN_ON(xradio_set_btcoexinfo(priv));
-+#if 0
-+ /* It's better to override internal TX rete; otherwise
-+ * device sends RTS at too high rate. However device
-+ * can't receive CTS at 1 and 2 Mbps. Well, 5.5 is a
-+ * good choice for RTS/CTS, but that means PS poll
-+ * will be sent at the same rate - impact on link
-+ * budget. Not sure what is better.. */
-+
-+ /* Update: internal rate selection algorythm is not
-+ * bad: if device is not receiving CTS at high rate,
-+ * it drops RTS rate.
-+ * So, conclusion: if-0 the code. Keep code just for
-+ * information:
-+ * Do not touch WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE! */
-+
-+ /* ~3 is a bug in device: RTS/CTS is not working at
-+ * low rates */
-+ __le32 internal_tx_rate = __cpu_to_le32(
-+ __ffs(priv->association_mode.basicRateSet & ~3));
-+ WARN_ON(wsm_write_mib(priv, WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE,
-+ &internal_tx_rate,sizeof(internal_tx_rate)));
-+#endif
-+ } else {
-+ memset(&priv->association_mode, 0, sizeof(priv->association_mode));
-+ memset(&priv->bss_params, 0, sizeof(priv->bss_params));
-+ }
-+ }
-+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT)) {
-+ u32 prev_erp_info = priv->erp_info;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ if (info->use_cts_prot)
-+ priv->erp_info |= WLAN_ERP_USE_PROTECTION;
-+ else if (!(prev_erp_info & WLAN_ERP_NON_ERP_PRESENT))
-+ priv->erp_info &= ~WLAN_ERP_USE_PROTECTION;
-+
-+ if (prev_erp_info != priv->erp_info)
-+ queue_delayed_work(hw_priv->workqueue, &priv->set_cts_work, 0*HZ);
-+ }
-+ }
-+
-+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_SLOT)) {
-+ __le32 slot_time = info->use_short_slot ? __cpu_to_le32(9) : __cpu_to_le32(20);
-+ ap_printk(XRADIO_DBG_MSG, "[STA] Slot time :%d us.\n", __le32_to_cpu(slot_time));
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_SLOT_TIME, &slot_time,
-+ sizeof(slot_time), priv->if_id));
-+ }
-+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_CQM)) {
-+ struct wsm_rcpi_rssi_threshold threshold = {
-+ .rollingAverageCount = 8,
-+ };
-+
-+#if 0
-+ /* For verification purposes */
-+ info->cqm_rssi_thold = -50;
-+ info->cqm_rssi_hyst = 4;
-+#endif /* 0 */
-+
-+ ap_printk(XRADIO_DBG_NIY, "[CQM] RSSI threshold subscribe: %d(+-%d)\n",
-+ info->cqm_rssi_thold, info->cqm_rssi_hyst);
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ priv->cqm_rssi_thold = info->cqm_rssi_thold;
-+ priv->cqm_rssi_hyst = info->cqm_rssi_hyst;
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+
-+ if (info->cqm_rssi_thold || info->cqm_rssi_hyst) {
-+ /* RSSI subscription enabled */
-+ /* TODO: It's not a correct way of setting threshold.
-+ * Upper and lower must be set equal here and adjusted
-+ * in callback. However current implementation is much
-+ * more relaible and stable. */
-+ if (priv->cqm_use_rssi) {
-+ threshold.upperThreshold = info->cqm_rssi_thold + info->cqm_rssi_hyst;
-+ threshold.lowerThreshold = info->cqm_rssi_thold;
-+ } else {
-+ /* convert RSSI to RCPI, RCPI = (RSSI + 110) * 2 */
-+ threshold.upperThreshold = (info->cqm_rssi_thold + info->cqm_rssi_hyst + 110)<<1;
-+ threshold.lowerThreshold = (info->cqm_rssi_thold + 110)<<1;
-+ }
-+ threshold.rssiRcpiMode |= WSM_RCPI_RSSI_THRESHOLD_ENABLE;
-+ } else {
-+ /* There is a bug in FW, see sta.c. We have to enable
-+ * dummy subscription to get correct RSSI values. */
-+ threshold.rssiRcpiMode |= WSM_RCPI_RSSI_THRESHOLD_ENABLE |
-+ WSM_RCPI_RSSI_DONT_USE_UPPER |
-+ WSM_RCPI_RSSI_DONT_USE_LOWER;
-+ }
-+ WARN_ON(wsm_set_rcpi_rssi_threshold(hw_priv, &threshold, priv->if_id));
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //priv->cqm_tx_failure_thold = info->cqm_tx_fail_thold;
-+ //priv->cqm_tx_failure_count = 0;
-+
-+ //if (priv->cqm_beacon_loss_count != info->cqm_beacon_miss_thold) {
-+ // priv->cqm_beacon_loss_count = info->cqm_beacon_miss_thold;
-+ // priv->bss_params.beaconLostCount = (priv->cqm_beacon_loss_count?
-+ // priv->cqm_beacon_loss_count : priv->cqm_link_loss_count);
-+ /* Make sure we are associated before sending
-+ * set_bss_params to firmware */
-+ if (priv->bss_params.aid) {
-+ WARN_ON(wsm_set_bss_params(hw_priv, &priv->bss_params, priv->if_id));
-+ priv->setbssparams_done = true;
-+ }
-+ //}
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ }
-+ /*
-+ * in linux3.4 mac,the enum ieee80211_bss_change variable doesn't have
-+ * BSS_CHANGED_PS and BSS_CHANGED_RETRY_LIMITS enum value.
-+ */
-+#if 0
-+ if (changed & BSS_CHANGED_PS) {
-+ if (info->ps_enabled == false)
-+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
-+ else if (info->dynamic_ps_timeout <= 0)
-+ priv->powersave_mode.pmMode = WSM_PSM_PS;
-+ else
-+ priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
-+
-+ ap_printk(XRADIO_DBG_MSG, "[STA] Aid: %d, Joined: %s, Powersave: %s\n",
-+ priv->bss_params.aid,
-+ priv->join_status == XRADIO_JOIN_STATUS_STA ? "yes" : "no",
-+ (priv->powersave_mode.pmMode == WSM_PSM_ACTIVE ? "WSM_PSM_ACTIVE" :
-+ priv->powersave_mode.pmMode == WSM_PSM_PS ? "WSM_PSM_PS" :
-+ priv->powersave_mode.pmMode == WSM_PSM_FAST_PS ? "WSM_PSM_FAST_PS" :
-+ "UNKNOWN"));
-+
-+ /* Firmware requires that value for this 1-byte field must
-+ * be specified in units of 500us. Values above the 128ms
-+ * threshold are not supported. */
-+ if (info->dynamic_ps_timeout >= 0x80)
-+ priv->powersave_mode.fastPsmIdlePeriod = 0xFF;
-+ else
-+ priv->powersave_mode.fastPsmIdlePeriod = info->dynamic_ps_timeout << 1;
-+ ap_printk(XRADIO_DBG_NIY, "[STA]CHANGED_PS fastPsmIdle=%d, apPsmChange=%d\n",
-+ priv->powersave_mode.fastPsmIdlePeriod,
-+ priv->powersave_mode.apPsmChangePeriod);
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA && priv->bss_params.aid &&
-+ priv->setbssparams_done && priv->filter4.enable)
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+ else
-+ priv->power_set_true = 1;
-+ }
-+
-+ if (changed & BSS_CHANGED_RETRY_LIMITS) {
-+ ap_printk(XRADIO_DBG_NIY, "Retry limits: %d (long), %d (short).\n",
-+ info->retry_long, info->retry_short);
-+ spin_lock_bh(&hw_priv->tx_policy_cache.lock);
-+ /*TODO:COMBO: for now it's still handled per hw and kept
-+ * in xradio_common */
-+ hw_priv->long_frame_max_tx_count = info->retry_long;
-+ hw_priv->short_frame_max_tx_count =
-+ (info->retry_short < 0x0F ? info->retry_short : 0x0F);
-+ hw_priv->hw->max_rate_tries = hw_priv->short_frame_max_tx_count;
-+ spin_unlock_bh(&hw_priv->tx_policy_cache.lock);
-+ /* TBD: I think we don't need tx_policy_force_upload().
-+ * Outdated policies will leave cache in a normal way. */
-+ /* WARN_ON(tx_policy_force_upload(priv)); */
-+ }
-+#endif
-+ /*in linux3.4 mac,the enum ieee80211_bss_change variable doesn't have BSS_CHANGED_P2P_PS enum value*/
-+#if 0
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ if (changed & BSS_CHANGED_P2P_PS) {
-+ struct wsm_p2p_ps_modeinfo *modeinfo;
-+ modeinfo = &priv->p2p_ps_modeinfo;
-+ ap_printk(XRADIO_DBG_NIY, "[AP] BSS_CHANGED_P2P_PS\n");
-+ ap_printk(XRADIO_DBG_NIY, "[AP] Legacy PS: %d for AID %d in %d mode.\n",
-+ info->p2p_ps.legacy_ps, priv->bss_params.aid, priv->join_status);
-+
-+ if (info->p2p_ps.legacy_ps >= 0) {
-+ if (info->p2p_ps.legacy_ps > 0)
-+ priv->powersave_mode.pmMode = WSM_PSM_PS;
-+ else
-+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
-+
-+ if(info->p2p_ps.ctwindow && info->p2p_ps.opp_ps)
-+ priv->powersave_mode.pmMode = WSM_PSM_PS;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA)
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+ }
-+
-+ ap_printk(XRADIO_DBG_MSG, "[AP] CTWindow: %d\n", info->p2p_ps.ctwindow);
-+ if (info->p2p_ps.ctwindow >= 128)
-+ modeinfo->oppPsCTWindow = 127;
-+ else if (info->p2p_ps.ctwindow >= 0)
-+ modeinfo->oppPsCTWindow = info->p2p_ps.ctwindow;
-+
-+ ap_printk(XRADIO_DBG_MSG, "[AP] Opportunistic: %d\n", info->p2p_ps.opp_ps);
-+ switch (info->p2p_ps.opp_ps) {
-+ case 0:
-+ modeinfo->oppPsCTWindow &= ~(BIT(7));
-+ break;
-+ case 1:
-+ modeinfo->oppPsCTWindow |= BIT(7);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ ap_printk(XRADIO_DBG_MSG, "[AP] NOA: %d, %d, %d, %d\n",
-+ info->p2p_ps.count, info->p2p_ps.start,
-+ info->p2p_ps.duration, info->p2p_ps.interval);
-+ /* Notice of Absence */
-+ modeinfo->count = info->p2p_ps.count;
-+
-+ if (info->p2p_ps.count) {
-+ /* In case P2P_GO we need some extra time to be sure
-+ * we will update beacon/probe_resp IEs correctly */
-+#define NOA_DELAY_START_MS 300
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ modeinfo->startTime = __cpu_to_le32(info->p2p_ps.start + NOA_DELAY_START_MS);
-+ else
-+ modeinfo->startTime = __cpu_to_le32(info->p2p_ps.start);
-+ modeinfo->duration = __cpu_to_le32(info->p2p_ps.duration);
-+ modeinfo->interval = __cpu_to_le32(info->p2p_ps.interval);
-+ modeinfo->dtimCount = 1;
-+ modeinfo->reserved = 0;
-+ } else {
-+ modeinfo->dtimCount = 0;
-+ modeinfo->startTime = 0;
-+ modeinfo->reserved = 0;
-+ modeinfo->duration = 0;
-+ modeinfo->interval = 0;
-+ }
-+
-+#if defined(CONFIG_XRADIO_DEBUG)
-+ print_hex_dump_bytes("p2p_set_ps_modeinfo: ", DUMP_PREFIX_NONE,
-+ (u8 *)modeinfo, sizeof(*modeinfo));
-+#endif /* CONFIG_XRADIO_DEBUG */
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA ||
-+ priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ WARN_ON(wsm_set_p2p_ps_modeinfo(hw_priv, modeinfo, priv->if_id));
-+ }
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ /* Temporary solution while firmware don't support NOA change
-+ * notification yet */
-+ xradio_notify_noa(priv, 10);
-+#endif
-+ }
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+#endif
-+ mutex_unlock(&hw_priv->conf_mutex);
-+}
-+
-+void xradio_multicast_start_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, multicast_start_work);
-+ long tmo = priv->join_dtim_period * (priv->beacon_int + 20) * HZ / 1024;
-+
-+ cancel_work_sync(&priv->multicast_stop_work);
-+ if (!priv->aid0_bit_set) {
-+ wsm_lock_tx(priv->hw_priv);
-+ xradio_set_tim_impl(priv, true);
-+ priv->aid0_bit_set = true;
-+ mod_timer(&priv->mcast_timeout, jiffies + tmo);
-+ wsm_unlock_tx(priv->hw_priv);
-+ }
-+}
-+
-+void xradio_multicast_stop_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, multicast_stop_work);
-+
-+ if (priv->aid0_bit_set) {
-+ del_timer_sync(&priv->mcast_timeout);
-+ wsm_lock_tx(priv->hw_priv);
-+ priv->aid0_bit_set = false;
-+ xradio_set_tim_impl(priv, false);
-+ wsm_unlock_tx(priv->hw_priv);
-+ }
-+}
-+
-+void xradio_mcast_timeout(struct timer_list *t)
-+{
-+ struct xradio_vif *priv = from_timer(priv, t, mcast_timeout);
-+
-+ ap_printk(XRADIO_DBG_WARN, "Multicast delivery timeout.\n");
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->tx_multicast = priv->aid0_bit_set && priv->buffered_multicasts;
-+ if (priv->tx_multicast)
-+ xradio_bh_wakeup(xrwl_vifpriv_to_hwpriv(priv));
-+ spin_unlock_bh(&priv->ps_state_lock);
-+}
-+
-+int xradio_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_ampdu_params *params)
-+{
-+ /* Aggregation is implemented fully in firmware,
-+ * including block ack negotiation.
-+ * In case of AMPDU aggregation in RX direction
-+ * re-ordering of packets takes place on host. mac80211
-+ * needs the ADDBA Request to setup reodering.mac80211 also
-+ * sends ADDBA Response which is discarded in the driver as
-+ * FW generates the ADDBA Response on its own.*/
-+ int ret;
-+
-+ switch (params->action) {
-+ case IEEE80211_AMPDU_RX_START:
-+ case IEEE80211_AMPDU_RX_STOP:
-+ /* Just return OK to mac80211 */
-+ ret = 0;
-+ break;
-+ default:
-+ ret = -ENOTSUPP;
-+ }
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+/* WSM callback */
-+void xradio_suspend_resume(struct xradio_vif *priv, struct wsm_suspend_resume *arg)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+#if 0
-+ ap_printk(XRADIO_DBG_MSG, "[AP] %s: %s\n",
-+ arg->stop ? "stop" : "start",
-+ arg->multicast ? "broadcast" : "unicast");
-+#endif
-+ if (arg->multicast) {
-+ bool cancel_tmo = false;
-+ spin_lock_bh(&priv->ps_state_lock);
-+ if (arg->stop) {
-+ priv->tx_multicast = false;
-+ } else {
-+ /* Firmware sends this indication every DTIM if there
-+ * is a STA in powersave connected. There is no reason
-+ * to suspend, following wakeup will consume much more
-+ * power than it could be saved. */
-+ xradio_pm_stay_awake(&hw_priv->pm_state, (priv->join_dtim_period *
-+ (priv->beacon_int + 20) * HZ / 1024));
-+ priv->tx_multicast = priv->aid0_bit_set && priv->buffered_multicasts;
-+ if (priv->tx_multicast) {
-+ cancel_tmo = true;
-+ xradio_bh_wakeup(hw_priv);
-+ }
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ if (cancel_tmo)
-+ del_timer_sync(&priv->mcast_timeout);
-+ } else {
-+ spin_lock_bh(&priv->ps_state_lock);
-+ xradio_ps_notify(priv, arg->link_id, arg->stop);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ if (!arg->stop)
-+ xradio_bh_wakeup(hw_priv);
-+ }
-+ return;
-+}
-+
-+/* ******************************************************************** */
-+/* AP privates */
-+
-+static int xradio_upload_beacon(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_BEACON,
-+ };
-+ struct ieee80211_mgmt *mgmt;
-+ u8 *erp_inf, *ies, *ht_oper;
-+ u32 ies_len;
-+
-+ if (priv->vif->p2p || hw_priv->channel->band == NL80211_BAND_5GHZ)
-+ frame.rate = WSM_TRANSMIT_RATE_6;
-+
-+ frame.skb = ieee80211_beacon_get(priv->hw, priv->vif);
-+ if (WARN_ON(!frame.skb))
-+ return -ENOMEM;
-+
-+ mgmt = (void *)frame.skb->data;
-+ ies = mgmt->u.beacon.variable;
-+ ies_len = frame.skb->len - (u32)(ies - (u8 *)mgmt);
-+
-+ ht_oper = (u8 *)cfg80211_find_ie( WLAN_EID_HT_OPERATION, ies, ies_len);
-+ if (ht_oper) {
-+ /* Enable RIFS*/
-+ ht_oper[3] |= 8;
-+ }
-+
-+ erp_inf = (u8 *)cfg80211_find_ie(WLAN_EID_ERP_INFO, ies, ies_len);
-+ if (erp_inf) {
-+ if (erp_inf[ERP_INFO_BYTE_OFFSET]
-+ & WLAN_ERP_BARKER_PREAMBLE)
-+ priv->erp_info |= WLAN_ERP_BARKER_PREAMBLE;
-+ else
-+ priv->erp_info &= ~WLAN_ERP_BARKER_PREAMBLE;
-+
-+ if (erp_inf[ERP_INFO_BYTE_OFFSET]
-+ & WLAN_ERP_NON_ERP_PRESENT) {
-+ priv->erp_info |= WLAN_ERP_USE_PROTECTION;
-+ priv->erp_info |= WLAN_ERP_NON_ERP_PRESENT;
-+ } else {
-+ priv->erp_info &= ~WLAN_ERP_USE_PROTECTION;
-+ priv->erp_info &= ~WLAN_ERP_NON_ERP_PRESENT;
-+ }
-+ }
-+
-+#ifdef HIDDEN_SSID
-+ if (priv->hidden_ssid) {
-+ u8 *ssid_ie;
-+ u8 ssid_len;
-+
-+ ap_printk(XRADIO_DBG_NIY, "%s: hidden_ssid set\n", __func__);
-+ ssid_ie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
-+ WARN_ON(!ssid_ie);
-+ ssid_len = ssid_ie[1];
-+ if (ssid_len) {
-+ ap_printk(XRADIO_DBG_MSG, "hidden_ssid with zero content ssid\n");
-+ ssid_ie[1] = 0;
-+ memmove(ssid_ie + 2, ssid_ie + 2 + ssid_len,
-+ (ies + ies_len -
-+ (ssid_ie + 2 + ssid_len)));
-+ frame.skb->len -= ssid_len;
-+ } else {
-+ ap_printk(XRADIO_DBG_WARN, "hidden ssid with ssid len 0 not supported");
-+ dev_kfree_skb(frame.skb);
-+ return -1;
-+ }
-+ }
-+#endif
-+
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ if (!ret) {
-+#ifdef PROBE_RESP_EXTRA_IE
-+ ret = xradio_upload_proberesp(priv);
-+#else
-+ /* TODO: Distille probe resp; remove TIM
-+ * and other beacon-specific IEs */
-+ *(__le16 *)frame.skb->data = __cpu_to_le16(
-+ IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
-+ frame.frame_type = WSM_FRAME_TYPE_PROBE_RESPONSE;
-+ /* TODO: Ideally probe response template should separately
-+ configured by supplicant through openmac. This is a
-+ temporary work-around known to fail p2p group info
-+ attribute related tests
-+ */
-+ if (0 /* priv->vif->p2p */)
-+ ret = wsm_set_probe_responder(priv, true);
-+ else {
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ WARN_ON(wsm_set_probe_responder(priv, false));
-+ }
-+#endif
-+ }
-+ dev_kfree_skb(frame.skb);
-+
-+ return ret;
-+}
-+
-+#ifdef PROBE_RESP_EXTRA_IE
-+static int xradio_upload_proberesp(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PROBE_RESPONSE,
-+ };
-+#ifdef HIDDEN_SSID
-+ u8 *ssid_ie;
-+#endif
-+
-+ if (priv->vif->p2p || hw_priv->channel->band == NL80211_BAND_5GHZ)
-+ frame.rate = WSM_TRANSMIT_RATE_6;
-+
-+ frame.skb = ieee80211_proberesp_get(priv->hw, priv->vif);
-+ if (WARN_ON(!frame.skb))
-+ return -ENOMEM;
-+
-+#ifdef HIDDEN_SSID
-+ if (priv->hidden_ssid) {
-+ int offset;
-+ u8 ssid_len;
-+ /* we are assuming beacon from upper layer will always contain
-+ zero filled ssid for hidden ap. The beacon shall never have
-+ ssid len = 0.
-+ */
-+
-+ offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
-+ ssid_ie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, frame.skb->data + offset,
-+ frame.skb->len - offset);
-+ ssid_len = ssid_ie[1];
-+ if (ssid_len && (ssid_len == priv->ssid_length)) {
-+ memcpy(ssid_ie + 2, priv->ssid, ssid_len);
-+ } else {
-+ ap_printk(XRADIO_DBG_ERROR, "%s: hidden ssid with mismatched ssid_len %d\n",
-+ __func__, ssid_len);
-+ dev_kfree_skb(frame.skb);
-+ return -1;
-+ }
-+ }
-+#endif
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ WARN_ON(wsm_set_probe_responder(priv, false));
-+
-+ dev_kfree_skb(frame.skb);
-+
-+ return ret;
-+}
-+#endif
-+
-+static int xradio_upload_pspoll(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PS_POLL,
-+ .rate = 0xFF,
-+ };
-+
-+ frame.skb = ieee80211_pspoll_get(priv->hw, priv->vif);
-+ if (WARN_ON(!frame.skb))
-+ return -ENOMEM;
-+ ret = wsm_set_template_frame(xrwl_vifpriv_to_hwpriv(priv), &frame, priv->if_id);
-+ dev_kfree_skb(frame.skb);
-+ return ret;
-+}
-+
-+static int xradio_upload_null(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_NULL,
-+ .rate = 0xFF,
-+ };
-+
-+ frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false);
-+ if (WARN_ON(!frame.skb))
-+ return -ENOMEM;
-+
-+ ret = wsm_set_template_frame(xrwl_vifpriv_to_hwpriv(priv), &frame, priv->if_id);
-+ dev_kfree_skb(frame.skb);
-+ return ret;
-+}
-+
-+static int xradio_upload_qosnull(struct xradio_vif *priv)
-+{
-+ struct ieee80211_qos_hdr* qos_null_template;
-+ struct sk_buff* skb;
-+ int ret = 0;
-+ struct xradio_common *hw_priv =xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_QOS_NULL,
-+ .rate = 0xFF,
-+ };
-+ if (!hw_priv)
-+ ap_printk(XRADIO_DBG_ERROR,"%s: Cannot find xradio_common pointer!\n",__FUNCTION__);
-+ /*set qos template*/
-+ skb = dev_alloc_skb(hw_priv->hw->extra_tx_headroom + sizeof(struct ieee80211_qos_hdr));
-+ if (!skb) {
-+ ap_printk(XRADIO_DBG_ERROR,"%s: failed to allocate buffer for qos nullfunc template!\n",__FUNCTION__);
-+ return -1;
-+ }
-+ skb_reserve(skb, hw_priv->hw->extra_tx_headroom);
-+ qos_null_template = (struct ieee80211_qos_hdr *)skb_put(skb,sizeof(struct ieee80211_qos_hdr));
-+ memset(qos_null_template, 0, sizeof(struct ieee80211_qos_hdr));
-+ memcpy(qos_null_template->addr1, priv->vif->bss_conf.bssid, ETH_ALEN);
-+ memcpy(qos_null_template->addr2, priv->vif->addr, ETH_ALEN);
-+ memcpy(qos_null_template->addr3, priv->vif->bss_conf.bssid, ETH_ALEN);
-+ qos_null_template->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
-+ IEEE80211_STYPE_QOS_NULLFUNC |
-+ IEEE80211_FCTL_TODS);
-+ frame.skb = skb;
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ dev_kfree_skb(frame.skb);
-+ return ret;
-+}
-+
-+/* This API is nolonegr present in WSC */
-+#if 0
-+static int xradio_enable_beaconing(struct xradio_vif *priv,
-+ bool enable)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_beacon_transmit transmit = {
-+ .enableBeaconing = enable,
-+ };
-+
-+ return wsm_beacon_transmit(hw_priv, &transmit, priv->if_id);
-+}
-+#endif
-+
-+static int xradio_start_ap(struct xradio_vif *priv)
-+{
-+ int ret;
-+#ifndef HIDDEN_SSID
-+ const u8 *ssidie;
-+ struct sk_buff *skb;
-+ int offset;
-+#endif
-+ struct ieee80211_bss_conf *conf = &priv->vif->bss_conf;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_start start = {
-+ .mode = priv->vif->p2p ? WSM_START_MODE_P2P_GO : WSM_START_MODE_AP,
-+ /* TODO:COMBO:Change once mac80211 support is available */
-+ .band = (hw_priv->channel->band == NL80211_BAND_5GHZ) ?
-+ WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G,
-+ .channelNumber = hw_priv->channel->hw_value,
-+ .beaconInterval = conf->beacon_int,
-+ .DTIMPeriod = conf->dtim_period,
-+ .preambleType = conf->use_short_preamble ?
-+ WSM_JOIN_PREAMBLE_SHORT :WSM_JOIN_PREAMBLE_LONG,
-+ .probeDelay = 100,
-+ .basicRateSet = xradio_rate_mask_to_wsm(hw_priv, conf->basic_rates),
-+ };
-+
-+#ifdef TES_P2P_000B_EXTEND_INACTIVITY_CNT
-+ ///w, TES_P2P_000B WorkAround:
-+ ///w, when inactivity count of a peer device is zero,
-+ ///w, which will reset while receiving a peer device frame,
-+ ///w, firmware will disconnect with it.
-+ ///w, due to some reason, such as scan/phy error, we miss these frame.
-+ ///w, then we can't keep connection with peer device.
-+ ///w, we set the min_inactivity value to large as WorkAround.
-+ //min_inactivity be modified to 20, yangfh.
-+ struct wsm_inactivity inactivity = {
-+ .min_inactivity = 20,
-+ .max_inactivity = 10,
-+ };
-+#else
-+ struct wsm_inactivity inactivity = {
-+ .min_inactivity = 9,
-+ .max_inactivity = 1,
-+ };
-+#endif
-+
-+ ap_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+
-+ if (priv->if_id)
-+ start.mode |= WSM_FLAG_MAC_INSTANCE_1;
-+ else
-+ start.mode &= ~WSM_FLAG_MAC_INSTANCE_1;
-+
-+ hw_priv->connected_sta_cnt = 0;
-+
-+#ifndef HIDDEN_SSID
-+ /* Get SSID */
-+ skb = ieee80211_beacon_get(priv->hw, priv->vif);
-+ if (WARN_ON(!skb)) {
-+ ap_printk(XRADIO_DBG_ERROR,"%s, ieee80211_beacon_get failed\n", __func__);
-+ return -ENOMEM;
-+ }
-+
-+ offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
-+ ssidie = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, skb->len - offset);
-+
-+ memset(priv->ssid, 0, sizeof(priv->ssid));
-+ if (ssidie) {
-+ priv->ssid_length = ssidie[1];
-+ if (WARN_ON(priv->ssid_length > sizeof(priv->ssid)))
-+ priv->ssid_length = sizeof(priv->ssid);
-+ memcpy(priv->ssid, &ssidie[2], priv->ssid_length);
-+ } else {
-+ priv->ssid_length = 0;
-+ }
-+ dev_kfree_skb(skb);
-+#endif
-+
-+ priv->beacon_int = conf->beacon_int;
-+ priv->join_dtim_period = conf->dtim_period;
-+ memset(&priv->last_tim[0], 0, sizeof(priv->last_tim)); //yangfh
-+
-+ start.ssidLength = priv->ssid_length;
-+ memcpy(&start.ssid[0], priv->ssid, start.ssidLength);
-+
-+ memset(&priv->link_id_db, 0, sizeof(priv->link_id_db));
-+
-+ ap_printk(XRADIO_DBG_NIY, "[AP] ch: %d(%d), bcn: %d(%d),"
-+ "bss_rate: 0x%.8X, ssid: %.*s.\n",
-+ start.channelNumber, start.band,
-+ start.beaconInterval, start.DTIMPeriod,
-+ start.basicRateSet, start.ssidLength, start.ssid);
-+ ret = WARN_ON(wsm_start(hw_priv, &start, priv->if_id));
-+
-+ if (!ret && priv->vif->p2p) {
-+ ap_printk(XRADIO_DBG_NIY,"[AP] Setting p2p powersave configuration.\n");
-+ WARN_ON(wsm_set_p2p_ps_modeinfo(hw_priv,
-+ &priv->p2p_ps_modeinfo, priv->if_id));
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //xradio_notify_noa(priv, XRADIO_NOA_NOTIFICATION_DELAY);
-+#endif
-+ }
-+
-+ /*Set Inactivity time*/
-+ if(!(strstr(&start.ssid[0], "6.1.12"))) {
-+ wsm_set_inactivity(hw_priv, &inactivity, priv->if_id);
-+ }
-+ if (!ret) {
-+#ifndef AP_AGGREGATE_FW_FIX
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
-+ XRADIO_RX_BLOCK_ACK_DISABLED_FOR_ALL_TID, priv->if_id));
-+#else
-+ if ((priv->if_id ==1) && !hw_priv->is_go_thru_go_neg)
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID, //modified for WFD by yangfh
-+ XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID, priv->if_id));
-+ else
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
-+ XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID, priv->if_id));
-+#endif
-+ priv->join_status = XRADIO_JOIN_STATUS_AP;
-+ /* xradio_update_filtering(priv); */
-+ }
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ ap_printk(XRADIO_DBG_WARN, "vif%d, AP/GO mode THROTTLE=%d\n", priv->if_id,
-+ priv->if_id==0?hw_priv->vif0_throttle:hw_priv->vif1_throttle);
-+ return ret;
-+}
-+
-+static int xradio_update_beaconing(struct xradio_vif *priv)
-+{
-+ struct ieee80211_bss_conf *conf = &priv->vif->bss_conf;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_reset reset = {
-+ .link_id = 0,
-+ .reset_statistics = true,
-+ };
-+ ap_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+
-+ if (priv->mode == NL80211_IFTYPE_AP) {
-+ /* TODO: check if changed channel, band */
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP ||
-+ priv->beacon_int != conf->beacon_int) {
-+ ap_printk(XRADIO_DBG_WARN, "ap restarting!\n");
-+ wsm_lock_tx(hw_priv);
-+ if (priv->join_status != XRADIO_JOIN_STATUS_PASSIVE)
-+ WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+ WARN_ON(xradio_start_ap(priv));
-+ wsm_unlock_tx(hw_priv);
-+ } else
-+ ap_printk(XRADIO_DBG_NIY, "ap started join_status: %d\n", priv->join_status);
-+ }
-+ return 0;
-+}
-+
-+int xradio_find_link_id(struct xradio_vif *priv, const u8 *mac)
-+{
-+ int i, ret = 0;
-+ spin_lock_bh(&priv->ps_state_lock);
-+ for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
-+ if (!memcmp(mac, priv->link_id_db[i].mac, ETH_ALEN) &&
-+ priv->link_id_db[i].status) {
-+ priv->link_id_db[i].timestamp = jiffies;
-+ ret = i + 1;
-+ break;
-+ }
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ return ret;
-+}
-+
-+int xradio_alloc_link_id(struct xradio_vif *priv, const u8 *mac)
-+{
-+ int i, ret = 0;
-+ unsigned long max_inactivity = 0;
-+ unsigned long now = jiffies;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
-+ if (!priv->link_id_db[i].status) {
-+ ret = i + 1;
-+ break;
-+ } else if (priv->link_id_db[i].status != XRADIO_LINK_HARD &&
-+ !hw_priv->tx_queue_stats.link_map_cache[i + 1]) {
-+ unsigned long inactivity = now - priv->link_id_db[i].timestamp;
-+ if (inactivity < max_inactivity)
-+ continue;
-+ max_inactivity = inactivity;
-+ ret = i + 1;
-+ }
-+ }
-+ if (ret) {
-+ struct xradio_link_entry *entry = &priv->link_id_db[ret - 1];
-+ ap_printk(XRADIO_DBG_NIY, "STA added, link_id: %d\n", ret);
-+ entry->status = XRADIO_LINK_RESERVE;
-+ memcpy(&entry->mac, mac, ETH_ALEN);
-+ memset(&entry->buffered, 0, XRADIO_MAX_TID);
-+ skb_queue_head_init(&entry->rx_queue);
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->link_id_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ } else {
-+ ap_printk(XRADIO_DBG_WARN, "Early: no more link IDs available.\n");
-+ }
-+
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ return ret;
-+}
-+
-+void xradio_link_id_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv = container_of(work, struct xradio_vif, link_id_work);
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+ wsm_flush_tx(hw_priv);
-+ xradio_link_id_gc_work(&priv->link_id_gc_work.work);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_link_id_gc_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, link_id_gc_work.work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_map_link map_link = {
-+ .link_id = 0,
-+ };
-+ unsigned long now = jiffies;
-+ unsigned long next_gc = -1;
-+ long ttl;
-+ bool need_reset;
-+ u32 mask;
-+ int i;
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP)
-+ return;
-+
-+ wsm_lock_tx(hw_priv);
-+ spin_lock_bh(&priv->ps_state_lock);
-+ for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
-+ need_reset = false;
-+ mask = BIT(i + 1);
-+ if (priv->link_id_db[i].status == XRADIO_LINK_RESERVE ||
-+ (priv->link_id_db[i].status == XRADIO_LINK_HARD &&
-+ !(priv->link_id_map & mask))) {
-+ if (priv->link_id_map & mask) {
-+ priv->sta_asleep_mask &= ~mask;
-+ priv->pspoll_mask &= ~mask;
-+ need_reset = true;
-+ }
-+ priv->link_id_map |= mask;
-+ if (priv->link_id_db[i].status != XRADIO_LINK_HARD)
-+ priv->link_id_db[i].status = XRADIO_LINK_SOFT;
-+ memcpy(map_link.mac_addr, priv->link_id_db[i].mac, ETH_ALEN);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ if (need_reset) {
-+ WARN_ON(xrwl_unmap_link(priv, i + 1));
-+ }
-+ map_link.link_id = i + 1;
-+ WARN_ON(wsm_map_link(hw_priv, &map_link, priv->if_id));
-+ next_gc = min(next_gc, XRADIO_LINK_ID_GC_TIMEOUT);
-+ spin_lock_bh(&priv->ps_state_lock);
-+ } else if (priv->link_id_db[i].status == XRADIO_LINK_SOFT) {
-+ ttl = priv->link_id_db[i].timestamp - now + XRADIO_LINK_ID_GC_TIMEOUT;
-+ if (ttl <= 0) {
-+ need_reset = true;
-+ priv->link_id_db[i].status = XRADIO_LINK_OFF;
-+ priv->link_id_map &= ~mask;
-+ priv->sta_asleep_mask &= ~mask;
-+ priv->pspoll_mask &= ~mask;
-+ memset(map_link.mac_addr, 0, ETH_ALEN);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ WARN_ON(xrwl_unmap_link(priv, i + 1));
-+ spin_lock_bh(&priv->ps_state_lock);
-+ } else {
-+ next_gc = min_t(unsigned long, next_gc, ttl);
-+ }
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ } else if (priv->link_id_db[i].status == XRADIO_LINK_RESET ||
-+ priv->link_id_db[i].status == XRADIO_LINK_RESET_REMAP) {
-+ int status = priv->link_id_db[i].status;
-+ priv->link_id_db[i].status = XRADIO_LINK_OFF;
-+ priv->link_id_db[i].timestamp = now;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ WARN_ON(xrwl_unmap_link(priv, i + 1));
-+ if (status == XRADIO_LINK_RESET_REMAP) {
-+ memcpy(map_link.mac_addr, priv->link_id_db[i].mac, ETH_ALEN);
-+ map_link.link_id = i + 1;
-+ WARN_ON(wsm_map_link(hw_priv, &map_link, priv->if_id));
-+ next_gc = min(next_gc, XRADIO_LINK_ID_GC_TIMEOUT);
-+ priv->link_id_db[i].status = priv->link_id_db[i].prev_status;
-+ }
-+ spin_lock_bh(&priv->ps_state_lock);
-+#endif
-+ }
-+ if (need_reset) {
-+ skb_queue_purge(&priv->link_id_db[i].rx_queue);
-+ ap_printk(XRADIO_DBG_NIY, "STA removed, link_id: %d\n", i + 1);
-+ }
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ if (next_gc != -1)
-+ queue_delayed_work(hw_priv->workqueue, &priv->link_id_gc_work, next_gc);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+#if 0
-+void xradio_notify_noa(struct xradio_vif *priv, int delay)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct cfg80211_p2p_ps p2p_ps = {0};
-+ struct wsm_p2p_ps_modeinfo *modeinfo;
-+ modeinfo = &priv->p2p_ps_modeinfo;
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP)
-+ return;
-+
-+ if (delay)
-+ msleep(delay);
-+
-+ if (!WARN_ON(wsm_get_p2p_ps_modeinfo(hw_priv, modeinfo))) {
-+#if defined(CONFIG_XRADIO_DEBUG)
-+ print_hex_dump_bytes("[AP] p2p_get_ps_modeinfo: ", DUMP_PREFIX_NONE,
-+ (u8 *)modeinfo, sizeof(*modeinfo));
-+#endif /* CONFIG_XRADIO_DEBUG */
-+ p2p_ps.opp_ps = !!(modeinfo->oppPsCTWindow & BIT(7));
-+ p2p_ps.ctwindow = modeinfo->oppPsCTWindow & (~BIT(7));
-+ p2p_ps.count = modeinfo->count;
-+ p2p_ps.start = __le32_to_cpu(modeinfo->startTime);
-+ p2p_ps.duration = __le32_to_cpu(modeinfo->duration);
-+ p2p_ps.interval = __le32_to_cpu(modeinfo->interval);
-+ p2p_ps.index = modeinfo->reserved;
-+
-+ ieee80211_p2p_noa_notify(priv->vif, &p2p_ps, GFP_KERNEL);
-+ }
-+}
-+#endif
-+#endif
-+int xrwl_unmap_link(struct xradio_vif *priv, int link_id)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int ret = 0;
-+
-+ if (is_hardware_xradio(hw_priv)) {
-+ struct wsm_map_link maplink = {
-+ .link_id = link_id,
-+ .unmap = true,
-+ };
-+ if (link_id)
-+ memcpy(&maplink.mac_addr[0], priv->link_id_db[link_id - 1].mac, ETH_ALEN);
-+ return wsm_map_link(hw_priv, &maplink, priv->if_id);
-+ } else {
-+ struct wsm_reset reset = {
-+ .link_id = link_id,
-+ .reset_statistics = true,
-+ };
-+ ret = wsm_reset(hw_priv, &reset, priv->if_id);
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ return ret;
-+ }
-+}
-+#ifdef AP_HT_CAP_UPDATE
-+void xradio_ht_oper_update_work(struct work_struct *work)
-+{
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+ u8 *ht_oper, *ies;
-+ u32 ies_len;
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, ht_oper_update_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_update_ie update_ie = {
-+ .what = WSM_UPDATE_IE_BEACON,
-+ .count = 1,
-+ };
-+
-+ skb = ieee80211_beacon_get(priv->hw, priv->vif);
-+ if (WARN_ON(!skb))
-+ return;
-+
-+ mgmt = (void *)skb->data;
-+ ies = mgmt->u.beacon.variable;
-+ ies_len = skb->len - (u32)(ies - (u8 *)mgmt);
-+ ht_oper= (u8 *)cfg80211_find_ie( WLAN_EID_HT_OPERATION, ies, ies_len);
-+ if(ht_oper && priv->ht_oper == HT_INFO_MASK) {
-+ ht_oper[HT_INFO_OFFSET] |= 0x11;
-+ update_ie.ies = ht_oper;
-+ update_ie.length = HT_INFO_IE_LEN;
-+ WARN_ON(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
-+ }
-+ dev_kfree_skb(skb);
-+}
-+#endif
-diff --git a/drivers/net/wireless/xradio/ap.h b/drivers/net/wireless/xradio/ap.h
-new file mode 100644
-index 0000000..9d55fb8
---- /dev/null
-+++ b/drivers/net/wireless/xradio/ap.h
-@@ -0,0 +1,63 @@
-+/*
-+ * STA and AP APIs for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef AP_H_INCLUDED
-+#define AP_H_INCLUDED
-+
-+#define XRADIO_NOA_NOTIFICATION_DELAY 10
-+
-+#ifdef AP_HT_CAP_UPDATE
-+#define HT_INFO_OFFSET 4
-+#define HT_INFO_MASK 0x0011
-+#define HT_INFO_IE_LEN 22
-+#endif
-+
-+int xradio_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
-+ bool set);
-+int xradio_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta);
-+int xradio_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta);
-+void xradio_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
-+ enum sta_notify_cmd notify_cmd,
-+ struct ieee80211_sta *sta);
-+void xradio_bss_info_changed(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_bss_conf *info,
-+ u32 changed);
-+int xradio_ampdu_action(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_ampdu_params *params);
-+/* enum ieee80211_ampdu_mlme_action action,
-+ struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-+ u8 buf_size);*/
-+
-+void xradio_suspend_resume(struct xradio_vif *priv,
-+ struct wsm_suspend_resume *arg);
-+void xradio_set_tim_work(struct work_struct *work);
-+void xradio_set_cts_work(struct work_struct *work);
-+void xradio_multicast_start_work(struct work_struct *work);
-+void xradio_multicast_stop_work(struct work_struct *work);
-+void xradio_mcast_timeout(struct timer_list *t);
-+int xradio_find_link_id(struct xradio_vif *priv, const u8 *mac);
-+int xradio_alloc_link_id(struct xradio_vif *priv, const u8 *mac);
-+void xradio_link_id_work(struct work_struct *work);
-+void xradio_link_id_gc_work(struct work_struct *work);
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+/*in linux3.4 mac,it does't have the noa pass*/
-+//void xradio_notify_noa(struct xradio_vif *priv, int delay);
-+#endif
-+int xrwl_unmap_link(struct xradio_vif *priv, int link_id);
-+#ifdef AP_HT_CAP_UPDATE
-+void xradio_ht_oper_update_work(struct work_struct *work);
-+#endif
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/bh.c b/drivers/net/wireless/xradio/bh.c
-new file mode 100644
-index 0000000..5b53778
---- /dev/null
-+++ b/drivers/net/wireless/xradio/bh.c
-@@ -0,0 +1,836 @@
-+/*
-+ * Data Transmission thread implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "bh.h"
-+#include "hwio.h"
-+#include "wsm.h"
-+#include "sdio.h"
-+
-+/* TODO: Verify these numbers with WSM specification. */
-+#define DOWNLOAD_BLOCK_SIZE_WR (0x1000 - 4)
-+/* an SPI message cannot be bigger than (2"12-1)*2 bytes
-+ * "*2" to cvt to bytes */
-+#define MAX_SZ_RD_WR_BUFFERS (DOWNLOAD_BLOCK_SIZE_WR*2)
-+#define PIGGYBACK_CTRL_REG (2)
-+#define EFFECTIVE_BUF_SIZE (MAX_SZ_RD_WR_BUFFERS - PIGGYBACK_CTRL_REG)
-+
-+/* Suspend state privates */
-+enum xradio_bh_pm_state {
-+ XRADIO_BH_RESUMED = 0,
-+ XRADIO_BH_SUSPEND,
-+ XRADIO_BH_SUSPENDED,
-+ XRADIO_BH_RESUME,
-+};
-+typedef int (*xradio_wsm_handler)(struct xradio_common *hw_priv, u8 *data, size_t size);
-+
-+#ifdef MCAST_FWDING
-+int wsm_release_buffer_to_fw(struct xradio_vif *priv, int count);
-+#endif
-+static int xradio_bh(void *arg);
-+
-+int xradio_register_bh(struct xradio_common *hw_priv)
-+{
-+ int ret = 0;
-+
-+ atomic_set(&hw_priv->bh_tx, 0);
-+ atomic_set(&hw_priv->bh_term, 0);
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_RESUMED);
-+ hw_priv->buf_id_tx = 0;
-+ hw_priv->buf_id_rx = 0;
-+ init_waitqueue_head(&hw_priv->bh_wq);
-+ init_waitqueue_head(&hw_priv->bh_evt_wq);
-+
-+ hw_priv->bh_thread = kthread_run(&xradio_bh, hw_priv, XRADIO_BH_THREAD);
-+ if (IS_ERR(hw_priv->bh_thread)) {
-+ ret = PTR_ERR(hw_priv->bh_thread);
-+ hw_priv->bh_thread = NULL;
-+ }
-+
-+ return ret;
-+}
-+
-+void xradio_unregister_bh(struct xradio_common *hw_priv)
-+{
-+ struct task_struct *thread = hw_priv->bh_thread;
-+
-+ if (WARN_ON(!thread))
-+ return;
-+
-+ hw_priv->bh_thread = NULL;
-+ kthread_stop(thread);
-+#ifdef HAS_PUT_TASK_STRUCT
-+ put_task_struct(thread);
-+#endif
-+ dev_dbg(hw_priv->pdev, "Unregister success.\n");
-+}
-+
-+void xradio_irq_handler(struct xradio_common *hw_priv)
-+{
-+ xradio_bh_wakeup(hw_priv);
-+}
-+
-+void xradio_bh_wakeup(struct xradio_common *hw_priv)
-+{
-+ atomic_set(&hw_priv->bh_tx, 1);
-+ wake_up(&hw_priv->bh_wq);
-+}
-+
-+int xradio_bh_suspend(struct xradio_common *hw_priv)
-+{
-+#ifdef MCAST_FWDING
-+ int i =0;
-+ struct xradio_vif *priv = NULL;
-+#endif
-+
-+ if (hw_priv->bh_error) {
-+ return -EINVAL;
-+ }
-+
-+#ifdef MCAST_FWDING
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ if ( (priv->multicast_filter.enable)
-+ && (priv->join_status == XRADIO_JOIN_STATUS_AP) ) {
-+ wsm_release_buffer_to_fw(priv,
-+ (hw_priv->wsm_caps.numInpChBufs - 1));
-+ break;
-+ }
-+ }
-+#endif
-+
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_SUSPEND);
-+ wake_up(&hw_priv->bh_wq);
-+ return wait_event_timeout(hw_priv->bh_evt_wq, (hw_priv->bh_error ||
-+ XRADIO_BH_SUSPENDED == atomic_read(&hw_priv->bh_suspend)),
-+ 1 * HZ)? 0 : -ETIMEDOUT;
-+}
-+
-+int xradio_bh_resume(struct xradio_common *hw_priv)
-+{
-+#ifdef MCAST_FWDING
-+ int ret;
-+ int i =0;
-+ struct xradio_vif *priv =NULL;
-+#endif
-+
-+
-+ if (hw_priv->bh_error) {
-+ return -EINVAL;
-+ }
-+
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_RESUME);
-+ wake_up(&hw_priv->bh_wq);
-+
-+#ifdef MCAST_FWDING
-+ ret = wait_event_timeout(hw_priv->bh_evt_wq, (hw_priv->bh_error ||
-+ XRADIO_BH_RESUMED == atomic_read(&hw_priv->bh_suspend))
-+ ,1 * HZ)? 0 : -ETIMEDOUT;
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ if ((priv->join_status == XRADIO_JOIN_STATUS_AP) &&
-+ (priv->multicast_filter.enable)) {
-+ u8 count = 0;
-+ WARN_ON(wsm_request_buffer_request(priv, &count));
-+ dev_dbg(hw_priv->pdev, "Reclaim Buff %d \n",count);
-+ break;
-+ }
-+ }
-+
-+ return ret;
-+#else
-+ return wait_event_timeout(hw_priv->bh_evt_wq,hw_priv->bh_error ||
-+ (XRADIO_BH_RESUMED == atomic_read(&hw_priv->bh_suspend)),
-+ 1 * HZ) ? 0 : -ETIMEDOUT;
-+#endif
-+
-+}
-+
-+static inline void wsm_alloc_tx_buffer(struct xradio_common *hw_priv)
-+{
-+ ++hw_priv->hw_bufs_used;
-+}
-+
-+int wsm_release_tx_buffer(struct xradio_common *hw_priv, int count)
-+{
-+ int ret = 0;
-+ int hw_bufs_used = hw_priv->hw_bufs_used;
-+
-+ hw_priv->hw_bufs_used -= count;
-+ if (WARN_ON(hw_priv->hw_bufs_used < 0)) {
-+ /* Tx data patch stops when all but one hw buffers are used.
-+ So, re-start tx path in case we find hw_bufs_used equals
-+ numInputChBufs - 1.
-+ */
-+ dev_err(hw_priv->pdev, "hw_bufs_used=%d, count=%d.\n",
-+ hw_priv->hw_bufs_used, count);
-+ ret = -1;
-+ } else if (hw_bufs_used >= (hw_priv->wsm_caps.numInpChBufs - 1))
-+ ret = 1;
-+ if (!hw_priv->hw_bufs_used)
-+ wake_up(&hw_priv->bh_evt_wq);
-+ return ret;
-+}
-+
-+int wsm_release_vif_tx_buffer(struct xradio_common *hw_priv, int if_id, int count)
-+{
-+ int ret = 0;
-+
-+ hw_priv->hw_bufs_used_vif[if_id] -= count;
-+ if (!hw_priv->hw_bufs_used_vif[if_id])
-+ wake_up(&hw_priv->bh_evt_wq);
-+
-+ if (WARN_ON(hw_priv->hw_bufs_used_vif[if_id] < 0))
-+ ret = -1;
-+ return ret;
-+}
-+#ifdef MCAST_FWDING
-+int wsm_release_buffer_to_fw(struct xradio_vif *priv, int count)
-+{
-+ int i;
-+ u8 flags;
-+ struct wsm_buf *buf;
-+ size_t buf_len;
-+ struct wsm_hdr *wsm;
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP) {
-+ return 0;
-+ }
-+ dev_dbg(hw_priv->pdev, "Rel buffer to FW %d, %d\n", count, hw_priv->hw_bufs_used);
-+
-+ for (i = 0; i < count; i++) {
-+ if ((hw_priv->hw_bufs_used + 1) < hw_priv->wsm_caps.numInpChBufs) {
-+ flags = i ? 0: 0x1;
-+
-+ wsm_alloc_tx_buffer(hw_priv);
-+ buf = &hw_priv->wsm_release_buf[i];
-+ buf_len = buf->data - buf->begin;
-+
-+ /* Add sequence number */
-+ wsm = (struct wsm_hdr *)buf->begin;
-+ BUG_ON(buf_len < sizeof(*wsm));
-+
-+ wsm->id &= __cpu_to_le32(~WSM_TX_SEQ(WSM_TX_SEQ_MAX));
-+ wsm->id |= cpu_to_le32(WSM_TX_SEQ(hw_priv->wsm_tx_seq));
-+
-+ dev_dbg(hw_priv->pdev, "REL %d\n", hw_priv->wsm_tx_seq);
-+ if (WARN_ON(xradio_data_write(hw_priv, buf->begin, buf_len))) {
-+ break;
-+ }
-+ hw_priv->buf_released = 1;
-+ hw_priv->wsm_tx_seq = (hw_priv->wsm_tx_seq + 1) & WSM_TX_SEQ_MAX;
-+ } else
-+ break;
-+ }
-+
-+ if (i == count) {
-+ return 0;
-+ }
-+
-+ /* Should not be here */
-+ dev_dbg(hw_priv->pdev, "Error, Less HW buf %d,%d.\n",
-+ hw_priv->hw_bufs_used, hw_priv->wsm_caps.numInpChBufs);
-+ WARN_ON(1);
-+ return -1;
-+}
-+#endif
-+
-+/* reserve a packet for the case dev_alloc_skb failed in bh.*/
-+int xradio_init_resv_skb(struct xradio_common *hw_priv)
-+{
-+ int len = (SDIO_BLOCK_SIZE<<2) + WSM_TX_EXTRA_HEADROOM + \
-+ 8 + 12; /* TKIP IV + ICV and MIC */
-+
-+ hw_priv->skb_reserved = dev_alloc_skb(len);
-+ if (hw_priv->skb_reserved) {
-+ hw_priv->skb_resv_len = len;
-+ } else {
-+ dev_warn(hw_priv->pdev, "xr_alloc_skb failed(%d)\n", len);
-+ }
-+ return 0;
-+}
-+
-+void xradio_deinit_resv_skb(struct xradio_common *hw_priv)
-+{
-+ if (hw_priv->skb_reserved) {
-+ dev_kfree_skb(hw_priv->skb_reserved);
-+ hw_priv->skb_reserved = NULL;
-+ hw_priv->skb_resv_len = 0;
-+ }
-+}
-+
-+int xradio_realloc_resv_skb(struct xradio_common *hw_priv,
-+ struct sk_buff *skb)
-+{
-+ if (!hw_priv->skb_reserved && hw_priv->skb_resv_len) {
-+ hw_priv->skb_reserved = dev_alloc_skb(hw_priv->skb_resv_len);
-+ if (!hw_priv->skb_reserved) {
-+ hw_priv->skb_reserved = skb;
-+ dev_warn(hw_priv->pdev, "xr_alloc_skb failed(%d)\n",
-+ hw_priv->skb_resv_len);
-+ return -1;
-+ }
-+ }
-+ return 0; /* realloc sbk success, deliver to upper.*/
-+}
-+
-+static inline struct sk_buff *xradio_get_resv_skb(struct xradio_common *hw_priv,
-+ size_t len)
-+{ struct sk_buff *skb = NULL;
-+ if (hw_priv->skb_reserved && len <= hw_priv->skb_resv_len) {
-+ skb = hw_priv->skb_reserved;
-+ hw_priv->skb_reserved = NULL;
-+ }
-+ return skb;
-+}
-+
-+static inline int xradio_put_resv_skb(struct xradio_common *hw_priv,
-+ struct sk_buff *skb)
-+{
-+ if (!hw_priv->skb_reserved && hw_priv->skb_resv_len) {
-+ hw_priv->skb_reserved = skb;
-+ return 0;
-+ }
-+ return 1; /* sbk not put to reserve*/
-+}
-+
-+static struct sk_buff *xradio_get_skb(struct xradio_common *hw_priv, size_t len)
-+{
-+ struct sk_buff *skb = NULL;
-+ size_t alloc_len = (len > SDIO_BLOCK_SIZE) ? len : SDIO_BLOCK_SIZE;
-+
-+ /* TKIP IV + TKIP ICV and MIC - Piggyback.*/
-+ alloc_len += WSM_TX_EXTRA_HEADROOM + 8 + 12- 2;
-+ if (len > SDIO_BLOCK_SIZE || !hw_priv->skb_cache) {
-+ skb = dev_alloc_skb(alloc_len);
-+ /* In AP mode RXed SKB can be looped back as a broadcast.
-+ * Here we reserve enough space for headers. */
-+ if (skb) {
-+ skb_reserve(skb, WSM_TX_EXTRA_HEADROOM + 8 /* TKIP IV */
-+ - WSM_RX_EXTRA_HEADROOM);
-+ } else {
-+ skb = xradio_get_resv_skb(hw_priv, alloc_len);
-+ if (skb) {
-+ dev_dbg(hw_priv->pdev, "get skb_reserved(%d)!\n", alloc_len);
-+ skb_reserve(skb, WSM_TX_EXTRA_HEADROOM + 8 /* TKIP IV */
-+ - WSM_RX_EXTRA_HEADROOM);
-+ } else {
-+ dev_dbg(hw_priv->pdev, "xr_alloc_skb failed(%d)!\n", alloc_len);
-+ }
-+ }
-+ } else {
-+ skb = hw_priv->skb_cache;
-+ hw_priv->skb_cache = NULL;
-+ }
-+ return skb;
-+}
-+
-+static void xradio_put_skb(struct xradio_common *hw_priv, struct sk_buff *skb)
-+{
-+ if (hw_priv->skb_cache)
-+ dev_kfree_skb(skb);
-+ else
-+ hw_priv->skb_cache = skb;
-+}
-+
-+static int xradio_bh_read_ctrl_reg(struct xradio_common *hw_priv,
-+ u16 *ctrl_reg)
-+{
-+ int ret;
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONTROL_REG_ID, ctrl_reg);
-+ if (ret) {
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONTROL_REG_ID, ctrl_reg);
-+ if (ret) {
-+ hw_priv->bh_error = 1;
-+ dev_err(hw_priv->pdev, "Failed to read control register.\n");
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+static int xradio_device_wakeup(struct xradio_common *hw_priv)
-+{
-+ u16 ctrl_reg;
-+ int ret, i=0;
-+
-+ /* To force the device to be always-on, the host sets WLAN_UP to 1 */
-+ ret = xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, HIF_CTRL_WUP_BIT);
-+ if (WARN_ON(ret))
-+ return ret;
-+
-+ ret = xradio_bh_read_ctrl_reg(hw_priv, &ctrl_reg);
-+ if (WARN_ON(ret))
-+ return ret;
-+
-+ /* If the device returns WLAN_RDY as 1, the device is active and will
-+ * remain active. */
-+ while (!(ctrl_reg & HIF_CTRL_RDY_BIT) && i < 500) {
-+ ret = xradio_bh_read_ctrl_reg(hw_priv, &ctrl_reg);
-+ msleep(1);
-+ i++;
-+ }
-+ if (unlikely(i >= 500)) {
-+ dev_err(hw_priv->pdev, "Device cannot wakeup.\n");
-+ return -1;
-+ } else if (unlikely(i >= 50))
-+ dev_warn(hw_priv->pdev, "Device wakeup time=%dms.\n", i);
-+ dev_dbg(hw_priv->pdev, "Device awake, t=%dms.\n", i);
-+ return 1;
-+}
-+
-+/* Must be called from BH thraed. */
-+void xradio_enable_powersave(struct xradio_vif *priv,
-+ bool enable)
-+{
-+ priv->powersave_enabled = enable;
-+}
-+
-+static void xradio_bh_rx_dump(struct device *dev, u8 *data, size_t len){
-+#ifdef DEBUG
-+ static const char *msgnames[0xffff] = {
-+ // 0x4?? is a sync response to a command
-+ [0x0404] = "tx confirm",
-+ [0x0406] = "mib confirm",
-+ [0x0407] = "scan started",
-+ [0x0409] = "configuration confirm",
-+ [0x040a] = "reset confirm",
-+ [0x040b] = "join confirm",
-+ [0x040c] = "key added",
-+ [0x040d] = "key removed",
-+ [0x0410] = "pm confirm",
-+ [0x0411] = "set bss params",
-+ [0x0412] = "tx queue params",
-+ [0x0413] = "edca confirm",
-+ [0x0417] = "start confirm",
-+ [0x041b] = "update ie confirm",
-+ [0x041c] = "map link confirm",
-+ // 0x8?? seem to be async responses or events
-+ [0x0801] = "firmware startup complete",
-+ [0x0804] = "rx",
-+ [0x0805] = "event",
-+ [0x0806] = "scan complete",
-+ [0x0810] = "set pm indication"
-+ };
-+
-+ u16 msgid, ifid;
-+ u16 *p = (u16 *)data;
-+ msgid = (*(p + 1)) & 0xC3F;
-+ ifid = (*(p + 1)) >> 6;
-+ ifid &= 0xF;
-+ const char *msgname = msgnames[msgid];
-+ if(msgid == 0x804 && ifid == 2){
-+ msgname = "scan result";
-+ }
-+
-+ dev_dbg(dev, "vif %d: sdio rx, msgid %s(0x%.4X) len %d\n",
-+ ifid, msgname, msgid, *p);
-+// print_hex_dump_bytes("<-- ", DUMP_PREFIX_NONE,
-+// data, min(len, (size_t) 64));
-+#endif
-+}
-+
-+#define READLEN(ctrl) ((ctrl & HIF_CTRL_NEXT_LEN_MASK) << 1) //read_len=ctrl_reg*2.
-+
-+static int xradio_bh_rx_availlen(struct xradio_common *hw_priv){
-+ u16 ctrl_reg = 0;
-+ if (xradio_bh_read_ctrl_reg(hw_priv, &ctrl_reg)) {
-+ return -EIO;
-+ }
-+ return READLEN(ctrl_reg);
-+}
-+
-+static int xradio_bh_rx(struct xradio_common *hw_priv, u16* nextlen) {
-+ size_t read_len = 0;
-+ struct sk_buff *skb_rx = NULL;
-+ struct wsm_hdr *wsm;
-+ size_t wsm_len;
-+ int wsm_id;
-+ u8 wsm_seq;
-+ size_t alloc_len;
-+ u8 *data;
-+ int ret;
-+
-+ read_len = *nextlen > 0 ? *nextlen : xradio_bh_rx_availlen(hw_priv);
-+ if(read_len <= 0)
-+ return read_len;
-+
-+ if (read_len < sizeof(struct wsm_hdr) || (read_len > EFFECTIVE_BUF_SIZE)) {
-+ dev_err(hw_priv->pdev, "Invalid read len: %d", read_len);
-+ return -1;
-+ }
-+
-+ /* Add SIZE of PIGGYBACK reg (CONTROL Reg)
-+ * to the NEXT Message length + 2 Bytes for SKB */
-+ read_len = read_len + 2;
-+
-+ alloc_len = sdio_align_len(hw_priv, read_len);
-+ /* Check if not exceeding XRADIO capabilities */
-+ if (WARN_ON_ONCE(alloc_len > EFFECTIVE_BUF_SIZE)) {
-+ dev_err(hw_priv->pdev, "Read aligned len: %d\n", alloc_len);
-+ }
-+
-+ /* Get skb buffer. */
-+ skb_rx = xradio_get_skb(hw_priv, alloc_len);
-+ if (!skb_rx) {
-+ dev_err(hw_priv->pdev, "xradio_get_skb failed.\n");
-+ return -ENOMEM;
-+ }
-+ skb_trim(skb_rx, 0);
-+ skb_put(skb_rx, read_len);
-+ data = skb_rx->data;
-+ if (!data) {
-+ dev_err(hw_priv->pdev, "skb data is NULL.\n");
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ /* Read data from device. */
-+ if (xradio_data_read(hw_priv, data, alloc_len)) {
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ /* the ctrl register is appened to the end of the wsm frame
-+ * so we can use this to avoid reading the control register
-+ * again for the next read .. but if this is invalid we'll
-+ * do an invalid read and the firmware will crash so this
-+ * probably needs some sort of validation */
-+ *nextlen = READLEN(__le16_to_cpu(((__le16 *) data)[(alloc_len >> 1) - 1]));
-+
-+ /* check wsm length. */
-+ wsm = (struct wsm_hdr *) data;
-+ wsm_len = __le32_to_cpu(wsm->len);
-+
-+ if (WARN_ON(wsm_len > read_len)) {
-+ dev_err(hw_priv->pdev, "wsm is bigger than data read, read %d but frame is %d\n",
-+ read_len, wsm_len);
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ /* dump rx data. */
-+ xradio_bh_rx_dump(hw_priv->pdev, data, wsm_len);
-+
-+ /* extract wsm id and seq. */
-+ wsm_id = __le32_to_cpu(wsm->id) & 0xFFF;
-+ wsm_seq = (__le32_to_cpu(wsm->id) >> 13) & 7;
-+ skb_trim(skb_rx, wsm_len);
-+
-+ /* process exceptions. */
-+ if (wsm_id == 0) {
-+ printk("wtf?\n");
-+ ret = 0;
-+ goto out;
-+ } else if (unlikely(wsm_id == 0x0800)) {
-+ dev_err(hw_priv->pdev, "firmware exception!\n");
-+ wsm_handle_exception(hw_priv, &data[sizeof(*wsm)],
-+ wsm_len - sizeof(*wsm));
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ hw_priv->wsm_rx_seq = (wsm_seq + 1) & 7;
-+
-+ /* Process tx frames confirm. */
-+ if (wsm_id & 0x0400) {
-+ if (wsm_release_tx_buffer(hw_priv, 1) < 0) {
-+ dev_err(hw_priv->pdev, "tx buffer < 0.\n");
-+ ret = -1;
-+ goto out;
-+ }
-+ }
-+
-+ /* WSM processing frames. */
-+ if (wsm_handle_rx(hw_priv, wsm_id, wsm, &skb_rx)) {
-+ dev_err(hw_priv->pdev, "wsm_handle_rx failed.\n");
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ ret = 1;
-+
-+out:
-+ /* Reclaim the SKB buffer */
-+ if (skb_rx) {
-+ if (xradio_put_resv_skb(hw_priv, skb_rx))
-+ xradio_put_skb(hw_priv, skb_rx);
-+ }
-+
-+ return ret;
-+}
-+
-+static void xradio_bh_tx_dump(struct device *dev, u8 *data, size_t len){
-+#ifdef DEBUG
-+ static const char *msgnames[0xffff] = {
-+ [0x0004] = "tx",
-+ [0x0006] = "MIB",
-+ [0x0007] = "start scan",
-+ [0x0009] = "configure",
-+ [0x000A] = "reset",
-+ [0x000B] = "join",
-+ [0x000C] = "add key",
-+ [0x000D] = "remove key",
-+ [0x0010] = "set pm",
-+ [0x0011] = "set bss params",
-+ [0x0012] = "set tx queue params",
-+ [0x0013] = "set edca",
-+ [0x0017] = "start",
-+ [0x001b] = "update ie",
-+ [0x001c] = "map link",
-+ };
-+ static const char *mibnames[0xffff] = {
-+ [0x0003] = "DOT11_SLOT_TIME",
-+ [0x1002] = "TEMPLATE_FRAME",
-+ [0x1003] = "RX_FILTER",
-+ [0x1004] = "BEACON_FILTER_TABLE",
-+ [0x1005] = "BEACON_FILTER_ENABLE",
-+ [0x1006] = "OPERATIONAL POWER MODE",
-+ [0x1007] = "BEACON_WAKEUP_PERIOD",
-+ [0x1009] = "RCPI_RSSI_THRESHOLD",
-+ [0x1010] = "SET_ASSOCIATION_MODE",
-+ [0x100e] = "BLOCK_ACK_POLICY",
-+ [0x100f] = "OVERRIDE_INTERNAL_TX_RATE",
-+ [0x1013] = "SET_UAPSD_INFORMATION",
-+ [0x1016] = "SET_TX_RATE_RETRY_POLICY",
-+ [0x1020] = "PROTECTED_MGMT_POLICY",
-+ [0x1021] = "SET_HT_PROTECTION",
-+ [0x1024] = "USE_MULTI_TX_CONF",
-+ [0x1025] = "KEEP_ALIVE_PERIOD",
-+ [0x1026] = "DISABLE_BSSID_FILTER",
-+ [0x1035] = "SET_INACTIVITY",
-+ };
-+
-+ u16 msgid, ifid, mib;
-+ u16 *p = (u16 *)data;
-+ msgid = (*(p + 1)) & 0x3F;
-+ ifid = (*(p + 1)) >> 6;
-+ ifid &= 0xF;
-+ mib = *(p + 2);
-+
-+ WARN_ON(msgnames[msgid] == NULL);
-+
-+ if (msgid == 0x0006) {
-+ dev_dbg(dev, "vif %d: sdio tx, msgid %s(0x%.4X) len %d MIB %s(0x%.4X)\n",
-+ ifid, msgnames[msgid], msgid,*p, mibnames[mib], mib);
-+ } else {
-+ dev_dbg(dev, "vif %d: sdio tx, msgid %s(0x%.4X) len %d\n", ifid, msgnames[msgid], msgid, *p);
-+ }
-+
-+// print_hex_dump_bytes("--> ", DUMP_PREFIX_NONE, data,
-+// min(len, (size_t) 64));
-+#endif
-+}
-+
-+static int xradio_bh_tx(struct xradio_common *hw_priv){
-+ int txavailable;
-+ int txburst;
-+ int vif_selected;
-+ struct wsm_hdr *wsm;
-+ size_t tx_len;
-+ int ret;
-+ u8 *data;
-+
-+ BUG_ON(hw_priv->hw_bufs_used > hw_priv->wsm_caps.numInpChBufs);
-+ txavailable = hw_priv->wsm_caps.numInpChBufs - hw_priv->hw_bufs_used;
-+ if (txavailable) {
-+ /* Wake up the devices */
-+ if (hw_priv->device_can_sleep) {
-+ ret = xradio_device_wakeup(hw_priv);
-+ if (WARN_ON(ret < 0)) {
-+ return -1;
-+ } else if (ret) {
-+ hw_priv->device_can_sleep = false;
-+ } else { /* Wait for "awake" interrupt */
-+ dev_dbg(hw_priv->pdev,
-+ "need to wait for device to wake before doing tx\n");
-+ return 0;
-+ }
-+ }
-+ /* Increase Tx buffer*/
-+ wsm_alloc_tx_buffer(hw_priv);
-+
-+ /* Get data to send and send it. */
-+ ret = wsm_get_tx(hw_priv, &data, &tx_len, &txburst, &vif_selected);
-+ if (ret <= 0) {
-+ wsm_release_tx_buffer(hw_priv, 1);
-+ if (WARN_ON(ret < 0)) {
-+ dev_err(hw_priv->pdev, "wsm_get_tx=%d.\n", ret);
-+ return -ENOMEM;
-+ } else {
-+ return 0;
-+ }
-+ } else {
-+ wsm = (struct wsm_hdr *) data;
-+ BUG_ON(tx_len < sizeof(*wsm));
-+ BUG_ON(__le32_to_cpu(wsm->len) != tx_len);
-+
-+ /* Align tx length and check it. */
-+ if (tx_len <= 8)
-+ tx_len = 16;
-+ tx_len = sdio_align_len(hw_priv, tx_len);
-+
-+ /* Check if not exceeding XRADIO capabilities */
-+ if (tx_len > EFFECTIVE_BUF_SIZE) {
-+ dev_warn(hw_priv->pdev, "Write aligned len: %d\n", tx_len);
-+ }
-+
-+ /* Make sequence number. */
-+ wsm->id &= __cpu_to_le32(~WSM_TX_SEQ(WSM_TX_SEQ_MAX));
-+ wsm->id |= cpu_to_le32(WSM_TX_SEQ(hw_priv->wsm_tx_seq));
-+
-+ /* Send the data to devices. */
-+ if (WARN_ON(xradio_data_write(hw_priv, data, tx_len))) {
-+ wsm_release_tx_buffer(hw_priv, 1);
-+ dev_err(hw_priv->pdev, "xradio_data_write failed\n");
-+ return -EIO;
-+ }
-+
-+ xradio_bh_tx_dump(hw_priv->pdev, data, tx_len);
-+
-+ /* Process after data have sent. */
-+ if (vif_selected != -1) {
-+ hw_priv->hw_bufs_used_vif[vif_selected]++;
-+ }
-+ wsm_txed(hw_priv, data);
-+ hw_priv->wsm_tx_seq = (hw_priv->wsm_tx_seq + 1) & WSM_TX_SEQ_MAX;
-+
-+ return 1;
-+ }
-+ } else
-+ return 0;
-+}
-+
-+static int xradio_bh_exchange(struct xradio_common *hw_priv) {
-+ int rxdone;
-+ int txdone;
-+ u16 nextlen = 0;
-+
-+ /* query stuck frames in firmware. */
-+ if (atomic_xchg(&hw_priv->query_cnt, 0)) {
-+ if (schedule_work(&hw_priv->query_work) <= 0)
-+ atomic_add(1, &hw_priv->query_cnt);
-+ }
-+
-+ /* keep doing tx and rx until they both stop or we are told
-+ * to terminate */
-+ do {
-+ txdone = xradio_bh_tx(hw_priv);
-+ if (txdone < 0) {
-+ break;
-+ }
-+ rxdone = xradio_bh_rx(hw_priv, &nextlen);
-+ if (rxdone < 0) {
-+ break;
-+ }
-+ } while ((txdone > 0 || rxdone > 0) && !kthread_should_stop());
-+ return 0;
-+}
-+
-+static int xradio_bh(void *arg)
-+{
-+ struct xradio_common *hw_priv = arg;
-+ int term, suspend;
-+ int wake = 0;
-+ long timeout;
-+ long status;
-+
-+ for (;;) {
-+ timeout = HZ / 30;
-+
-+ // wait for something to happen or a timeout
-+ status = wait_event_interruptible_timeout(hw_priv->bh_wq, ( {
-+ wake = atomic_xchg(&hw_priv->bh_tx, 0);
-+ term = kthread_should_stop();
-+ suspend = atomic_read(&hw_priv->bh_suspend);
-+ (wake || term || suspend);}), timeout);
-+
-+ if (wake) {
-+ if(xradio_bh_exchange(hw_priv) < 0){
-+ break;
-+ }
-+ } else if (term) {
-+ dev_dbg(hw_priv->pdev, "xradio_bh exit!\n");
-+ break;
-+ } else if (status < 0) {
-+ dev_err(hw_priv->pdev, "bh_error=%d, status=%ld\n",
-+ hw_priv->bh_error, status);
-+ break;
-+ } else if (!status) {
-+ /* check if there is data waiting but we missed the interrupt*/
-+ if (xradio_bh_rx_availlen(hw_priv) > 0) {
-+ dev_warn(hw_priv->pdev, "missed interrupt\n");
-+ if(xradio_bh_exchange(hw_priv) < 0){
-+ break;
-+ }
-+ }
-+ /* There are some frames to be confirmed. */
-+ else if (hw_priv->hw_bufs_used) {
-+ long timeout = 0;
-+ bool pending = 0;
-+ dev_dbg(hw_priv->pdev, "Need confirm:%d!\n",
-+ hw_priv->hw_bufs_used);
-+ /* Check if frame transmission is timed out. */
-+ pending = xradio_query_txpkt_timeout(hw_priv, XRWL_ALL_IFS,
-+ hw_priv->pending_frame_id, &timeout);
-+ /* There are some frames confirm time out. */
-+ if (pending && timeout < 0) {
-+ dev_err(hw_priv->pdev, "query_txpkt_timeout:%ld!\n",
-+ timeout);
-+ break;
-+ }
-+ } //else if (!txpending){
-+ //if (hw_priv->powersave_enabled && !hw_priv->device_can_sleep && !atomic_read(&hw_priv->recent_scan)) {
-+ // /* Device is idle, we can go to sleep. */
-+ // dev_dbg(hw_priv->pdev, "Device idle(timeout), can sleep.\n");
-+ // WARN_ON(xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, 0));
-+ // hw_priv->device_can_sleep = true;
-+ //}
-+ //continue;
-+ //}
-+ } else if (suspend) {
-+ dev_dbg(hw_priv->pdev, "Host suspend request.\n");
-+ /* Check powersave setting again. */
-+ if (hw_priv->powersave_enabled) {
-+ dev_dbg(hw_priv->pdev,
-+ "Device idle(host suspend), can sleep.\n");
-+ WARN_ON(xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, 0));
-+ hw_priv->device_can_sleep = true;
-+ }
-+
-+ /* bh thread go to suspend. */
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_SUSPENDED);
-+ wake_up(&hw_priv->bh_evt_wq);
-+ status = wait_event_interruptible(hw_priv->bh_wq,
-+ XRADIO_BH_RESUME == atomic_read(&hw_priv->bh_suspend));
-+
-+ if (status < 0) {
-+ dev_err(hw_priv->pdev, "Failed to wait for resume: %ld.\n",
-+ status);
-+ break;
-+ }
-+ dev_dbg(hw_priv->pdev, "Host resume.\n");
-+ atomic_set(&hw_priv->bh_suspend, XRADIO_BH_RESUMED);
-+ wake_up(&hw_priv->bh_evt_wq);
-+ }
-+ } /* for (;;)*/
-+
-+ dev_err(hw_priv->pdev, "bh thread exiting\n");
-+
-+ return 0;
-+}
-diff --git a/drivers/net/wireless/xradio/bh.h b/drivers/net/wireless/xradio/bh.h
-new file mode 100644
-index 0000000..ca9187e
---- /dev/null
-+++ b/drivers/net/wireless/xradio/bh.h
-@@ -0,0 +1,36 @@
-+/*
-+ * Data Transmission thread for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_BH_H
-+#define XRADIO_BH_H
-+
-+#define XRADIO_BH_THREAD "xradio_bh"
-+
-+/* extern */ struct xradio_common;
-+
-+#define SDIO_BLOCK_SIZE (528)
-+
-+int xradio_register_bh(struct xradio_common *hw_priv);
-+void xradio_unregister_bh(struct xradio_common *hw_priv);
-+void xradio_irq_handler(struct xradio_common *hw_priv);
-+void xradio_bh_wakeup(struct xradio_common *hw_priv);
-+int xradio_bh_suspend(struct xradio_common *hw_priv);
-+int xradio_bh_resume(struct xradio_common *hw_priv);
-+/* Must be called from BH thread. */
-+void xradio_enable_powersave(struct xradio_vif *priv, bool enable);
-+int wsm_release_tx_buffer(struct xradio_common *hw_priv, int count);
-+int wsm_release_vif_tx_buffer(struct xradio_common *hw_priv, int if_id,
-+ int count);
-+int xradio_init_resv_skb(struct xradio_common *hw_priv);
-+void xradio_deinit_resv_skb(struct xradio_common *hw_priv);
-+int xradio_realloc_resv_skb(struct xradio_common *hw_priv,
-+ struct sk_buff *skb);
-+#endif /* XRADIO_BH_H */
-diff --git a/drivers/net/wireless/xradio/common.h b/drivers/net/wireless/xradio/common.h
-new file mode 100644
-index 0000000..1ce23de
---- /dev/null
-+++ b/drivers/net/wireless/xradio/common.h
-@@ -0,0 +1,101 @@
-+/*
-+ * Common interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_COMMON_H
-+#define XRADIO_COMMON_H
-+
-+/*******************************************************
-+ interfaces for parse frame protocol info.
-+********************************************************/
-+#define LLC_LEN 8
-+#define LLC_TYPE_OFF 6 //Ether type offset
-+#define IP_PROTO_OFF 9 //protocol offset
-+#define IP_S_ADD_OFF 12
-+#define IP_D_ADD_OFF 16
-+#define UDP_LEN 8
-+//DHCP
-+#define DHCP_BOOTP_C 68
-+#define DHCP_BOOTP_S 67
-+#define UDP_BOOTP_LEN 236 //exclude "Options:64"
-+#define BOOTP_OPS_LEN 64
-+#define DHCP_MAGIC 0x63825363
-+#define DHCP_DISCOVER 0x01
-+#define DHCP_OFFER 0x02
-+#define DHCP_REQUEST 0x03
-+#define DHCP_DECLINE 0x04
-+#define DHCP_ACK 0x05
-+#define DHCP_NACK 0x06
-+#define DHCP_RELEASE 0x07
-+
-+//LLC layer.
-+static inline bool is_SNAP(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data) == 0xAAAA && llc_data[2] == 0x03); //0xAA, 0xAA, 0x03.
-+}
-+
-+static inline bool is_STP(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data) == 0xAAAA && llc_data[2] == 0x03); //0x42, 0x42, 0x03.
-+}
-+
-+//IP/IPV6/ARP layer...
-+static inline bool is_ip(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data+LLC_TYPE_OFF) == cpu_to_be16(ETH_P_IP)); //0x0800
-+}
-+static inline bool is_ipv6(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data+LLC_TYPE_OFF) == cpu_to_be16(ETH_P_IPV6)); //0x08dd
-+}
-+static inline bool is_arp(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data+LLC_TYPE_OFF) == cpu_to_be16(ETH_P_ARP)); //0x0806
-+}
-+static inline bool is_8021x(u8* llc_data)
-+{
-+ return (bool)(*(u16*)(llc_data+LLC_TYPE_OFF) == cpu_to_be16(ETH_P_PAE)); //0x888E
-+}
-+
-+//TCP/UDP layer...
-+static inline bool is_tcp(u8* llc_data)
-+{
-+ return (bool)(llc_data[LLC_LEN+IP_PROTO_OFF] == IPPROTO_TCP); //
-+}
-+
-+static inline bool is_udp(u8* llc_data)
-+{
-+ return (bool)(llc_data[LLC_LEN+IP_PROTO_OFF] == IPPROTO_UDP); //
-+}
-+
-+static inline bool is_icmp(u8* llc_data)
-+{
-+ return (bool)(llc_data[LLC_LEN+IP_PROTO_OFF] == IPPROTO_ICMP); //
-+}
-+
-+static inline bool is_igmp(u8* llc_data)
-+{
-+ return (bool)(llc_data[LLC_LEN+IP_PROTO_OFF] == IPPROTO_IGMP); //
-+}
-+
-+static inline bool is_dhcp(u8* llc_data)
-+{
-+ u8* ip_hdr = llc_data+LLC_LEN;
-+ if(!is_ip(llc_data))
-+ return (bool)0;
-+ if(ip_hdr[IP_PROTO_OFF] == IPPROTO_UDP) {
-+ u8* udp_hdr = ip_hdr+((ip_hdr[0]&0xf)<<2); //ihl:words
-+ return (bool)((((udp_hdr[0]<<8)|udp_hdr[1]) == DHCP_BOOTP_C) || //DHCP client
-+ (((udp_hdr[0]<<8)|udp_hdr[1]) == DHCP_BOOTP_S)); //DHCP server
-+ }
-+ return (bool)0;
-+}
-+
-+#endif //XRADIO_COMMON_H
-diff --git a/drivers/net/wireless/xradio/debug.h b/drivers/net/wireless/xradio/debug.h
-new file mode 100644
-index 0000000..30a59f3
---- /dev/null
-+++ b/drivers/net/wireless/xradio/debug.h
-@@ -0,0 +1,22 @@
-+/*
-+ * DebugFS code for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef XRADIO_DEBUG_H_INCLUDED
-+#define XRADIO_DEBUG_H_INCLUDED
-+
-+#define xradio_dbg(level, ...)
-+#define txrx_printk(level, ...)
-+#define wsm_printk(level, ...)
-+#define sta_printk(level, ...)
-+#define scan_printk(level, ...)
-+#define ap_printk(level, ...)
-+#define pm_printk(level, ...)
-+
-+#endif /* XRADIO_DEBUG_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/fwio.c b/drivers/net/wireless/xradio/fwio.c
-new file mode 100644
-index 0000000..cfb45eb
---- /dev/null
-+++ b/drivers/net/wireless/xradio/fwio.c
-@@ -0,0 +1,560 @@
-+/*
-+ * Firmware I/O implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "fwio.h"
-+#include "hwio.h"
-+#include "bh.h"
-+#include "sdio.h"
-+
-+/* Macroses are local. */
-+#define APB_WRITE(reg, val) \
-+ do { \
-+ ret = xradio_apb_write_32(hw_priv, APB_ADDR(reg), (val)); \
-+ if (ret < 0) { \
-+ dev_err(hw_priv->pdev, \
-+ "%s: can't write %s at line %d.\n", \
-+ __func__, #reg, __LINE__); \
-+ goto error; \
-+ } \
-+ } while (0)
-+#define APB_READ(reg, val) \
-+ do { \
-+ ret = xradio_apb_read_32(hw_priv, APB_ADDR(reg), &(val)); \
-+ if (ret < 0) { \
-+ dev_err(hw_priv->pdev, \
-+ "%s: can't read %s at line %d.\n", \
-+ __func__, #reg, __LINE__); \
-+ goto error; \
-+ } \
-+ } while (0)
-+#define REG_WRITE(reg, val) \
-+ do { \
-+ ret = xradio_reg_write_32(hw_priv, (reg), (val)); \
-+ if (ret < 0) { \
-+ dev_err(hw_priv->pdev, \
-+ "%s: can't write %s at line %d.\n", \
-+ __func__, #reg, __LINE__); \
-+ goto error; \
-+ } \
-+ } while (0)
-+#define REG_READ(reg, val) \
-+ do { \
-+ ret = xradio_reg_read_32(hw_priv, (reg), &(val)); \
-+ if (ret < 0) { \
-+ dev_err(hw_priv->pdev, \
-+ "%s: can't read %s at line %d.\n", \
-+ __func__, #reg, __LINE__); \
-+ goto error; \
-+ } \
-+ } while (0)
-+
-+
-+static int xradio_get_hw_type(u32 config_reg_val, int *major_revision)
-+{
-+ int hw_type = -1;
-+ u32 hif_type = (config_reg_val >> 24) & 0x4;
-+ //u32 hif_vers = (config_reg_val >> 31) & 0x1;
-+
-+ /* Check if we have XRADIO*/
-+ if (hif_type == 0x4) {
-+ *major_revision = 0x4;
-+ hw_type = HIF_HW_TYPE_XRADIO;
-+ } else {
-+ //hw type unknown.
-+ *major_revision = 0x0;
-+ }
-+ return hw_type;
-+}
-+
-+/*
-+ * This function is called to Parse the SDD file
-+ * to extract some informations
-+ */
-+static int xradio_parse_sdd(struct xradio_common *hw_priv, u32 *dpll)
-+{
-+ int ret = 0;
-+ const char *sdd_path = NULL;
-+ struct xradio_sdd *pElement = NULL;
-+ int parsedLength = 0;
-+
-+ BUG_ON(hw_priv->sdd != NULL);
-+
-+ /* select and load sdd file depend on hardware version. */
-+ switch (hw_priv->hw_revision) {
-+ case XR819_HW_REV0:
-+ sdd_path = XR819_SDD_FILE;
-+ break;
-+ default:
-+ dev_dbg(hw_priv->pdev, "unknown hardware version.\n");
-+ return ret;
-+ }
-+
-+ ret = request_firmware(&hw_priv->sdd, sdd_path, hw_priv->pdev);
-+ if (unlikely(ret)) {
-+ dev_dbg(hw_priv->pdev, "can't load sdd file %s.\n",
-+ sdd_path);
-+ return ret;
-+ }
-+
-+ //parse SDD config.
-+ hw_priv->is_BT_Present = false;
-+ pElement = (struct xradio_sdd *)hw_priv->sdd->data;
-+ parsedLength += (FIELD_OFFSET(struct xradio_sdd, data) + pElement->length);
-+ pElement = FIND_NEXT_ELT(pElement);
-+
-+ while (parsedLength < hw_priv->sdd->size) {
-+ switch (pElement->id) {
-+ case SDD_PTA_CFG_ELT_ID:
-+ hw_priv->conf_listen_interval = (*((u16 *)pElement->data+1) >> 7) & 0x1F;
-+ hw_priv->is_BT_Present = true;
-+ xradio_dbg(XRADIO_DBG_NIY, "PTA element found.Listen Interval %d\n",
-+ hw_priv->conf_listen_interval);
-+ break;
-+ case SDD_REFERENCE_FREQUENCY_ELT_ID:
-+ switch(*((uint16_t*)pElement->data)) {
-+ case 0x32C8:
-+ *dpll = 0x1D89D241;
-+ break;
-+ case 0x3E80:
-+ *dpll = 0x1E1;
-+ break;
-+ case 0x41A0:
-+ *dpll = 0x124931C1;
-+ break;
-+ case 0x4B00:
-+ *dpll = 0x191;
-+ break;
-+ case 0x5DC0:
-+ *dpll = 0x141;
-+ break;
-+ case 0x6590:
-+ *dpll = 0x0EC4F121;
-+ break;
-+ case 0x8340:
-+ *dpll = 0x92490E1;
-+ break;
-+ case 0x9600:
-+ *dpll = 0x100010C1;
-+ break;
-+ case 0x9C40:
-+ *dpll = 0xC1;
-+ break;
-+ case 0xBB80:
-+ *dpll = 0xA1;
-+ break;
-+ case 0xCB20:
-+ *dpll = 0x7627091;
-+ break;
-+ default:
-+ *dpll = DPLL_INIT_VAL_XRADIO;
-+ xradio_dbg(XRADIO_DBG_WARN, "Unknown Reference clock frequency."
-+ "Use default DPLL value=0x%08x.", DPLL_INIT_VAL_XRADIO);
-+ break;
-+ }
-+ default:
-+ break;
-+ }
-+ parsedLength += (FIELD_OFFSET(struct xradio_sdd, data) + pElement->length);
-+ pElement = FIND_NEXT_ELT(pElement);
-+ }
-+
-+ dev_dbg(hw_priv->pdev, "sdd size=%d parse len=%d.\n",
-+ hw_priv->sdd->size, parsedLength);
-+
-+ //
-+ if (hw_priv->is_BT_Present == false) {
-+ hw_priv->conf_listen_interval = 0;
-+ xradio_dbg(XRADIO_DBG_NIY, "PTA element NOT found.\n");
-+ }
-+ return ret;
-+}
-+
-+static int xradio_firmware(struct xradio_common *hw_priv)
-+{
-+ int ret, block, num_blocks;
-+ unsigned i;
-+ u32 val32;
-+ u32 put = 0, get = 0;
-+ u8 *buf = NULL;
-+ const char *fw_path;
-+ const struct firmware *firmware = NULL;
-+
-+ switch (hw_priv->hw_revision) {
-+ case XR819_HW_REV0:
-+ fw_path = XR819_FIRMWARE;
-+ break;
-+ default:
-+ dev_dbg(hw_priv->pdev, "invalid silicon revision %d.\n",
-+ hw_priv->hw_revision);
-+ return -EINVAL;
-+ }
-+ /* Initialize common registers */
-+ APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, DOWNLOAD_ARE_YOU_HERE);
-+ APB_WRITE(DOWNLOAD_PUT_REG, 0);
-+ APB_WRITE(DOWNLOAD_GET_REG, 0);
-+ APB_WRITE(DOWNLOAD_STATUS_REG, DOWNLOAD_PENDING);
-+ APB_WRITE(DOWNLOAD_FLAGS_REG, 0);
-+
-+ /* Release CPU from RESET */
-+ REG_READ(HIF_CONFIG_REG_ID, val32);
-+ val32 &= ~HIF_CONFIG_CPU_RESET_BIT;
-+ REG_WRITE(HIF_CONFIG_REG_ID, val32);
-+
-+ /* Enable Clock */
-+ val32 &= ~HIF_CONFIG_CPU_CLK_DIS_BIT;
-+ REG_WRITE(HIF_CONFIG_REG_ID, val32);
-+
-+ /* Load a firmware file */
-+ ret = request_firmware(&firmware, fw_path, hw_priv->pdev);
-+ if (ret) {
-+ dev_dbg(hw_priv->pdev, "can't load firmware file %s.\n",
-+ fw_path);
-+ goto error;
-+ }
-+ BUG_ON(!firmware->data);
-+
-+ buf = kmalloc(DOWNLOAD_BLOCK_SIZE, GFP_KERNEL);
-+ if (!buf) {
-+ dev_dbg(hw_priv->pdev, "can't allocate firmware buffer.\n");
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ /* Check if the bootloader is ready */
-+ for (i = 0; i < 100; i++/*= 1 + i / 2*/) {
-+ APB_READ(DOWNLOAD_IMAGE_SIZE_REG, val32);
-+ if (val32 == DOWNLOAD_I_AM_HERE)
-+ break;
-+ mdelay(10);
-+ } /* End of for loop */
-+ if (val32 != DOWNLOAD_I_AM_HERE) {
-+ dev_dbg(hw_priv->pdev, "bootloader is not ready.\n");
-+ ret = -ETIMEDOUT;
-+ goto error;
-+ }
-+
-+ /* Calculcate number of download blocks */
-+ num_blocks = (firmware->size - 1) / DOWNLOAD_BLOCK_SIZE + 1;
-+
-+ /* Updating the length in Download Ctrl Area */
-+ val32 = firmware->size; /* Explicit cast from size_t to u32 */
-+ APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, val32);
-+
-+ /* Firmware downloading loop */
-+ for (block = 0; block < num_blocks ; block++) {
-+ size_t tx_size;
-+ size_t block_size;
-+
-+ /* check the download status */
-+ APB_READ(DOWNLOAD_STATUS_REG, val32);
-+ if (val32 != DOWNLOAD_PENDING) {
-+ dev_dbg(hw_priv->pdev, "bootloader reported error %d.\n",
-+ val32);
-+ ret = -EIO;
-+ goto error;
-+ }
-+
-+ /* loop until put - get <= 24K */
-+ for (i = 0; i < 100; i++) {
-+ APB_READ(DOWNLOAD_GET_REG, get);
-+ if ((put - get) <= (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE))
-+ break;
-+ mdelay(i);
-+ }
-+
-+ if ((put - get) > (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) {
-+ dev_dbg(hw_priv->pdev, "Timeout waiting for FIFO.\n");
-+ ret = -ETIMEDOUT;
-+ goto error;
-+ }
-+
-+ /* calculate the block size */
-+ tx_size = block_size = min((size_t)(firmware->size - put), (size_t)DOWNLOAD_BLOCK_SIZE);
-+ memcpy(buf, &firmware->data[put], block_size);
-+
-+ if (block_size < DOWNLOAD_BLOCK_SIZE) {
-+ memset(&buf[block_size], 0, DOWNLOAD_BLOCK_SIZE - block_size);
-+ tx_size = DOWNLOAD_BLOCK_SIZE;
-+ }
-+
-+ /* send the block to sram */
-+ ret = xradio_apb_write(hw_priv, APB_ADDR(DOWNLOAD_FIFO_OFFSET + (put & (DOWNLOAD_FIFO_SIZE - 1))),
-+ buf, tx_size);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "%s: can't write block at line %d.\n", __func__, __LINE__);
-+ goto error;
-+ }
-+
-+ /* update the put register */
-+ put += block_size;
-+ APB_WRITE(DOWNLOAD_PUT_REG, put);
-+ } /* End of firmware download loop */
-+
-+ /* Wait for the download completion */
-+ for (i = 0; i < 300; i += 1 + i / 2) {
-+ APB_READ(DOWNLOAD_STATUS_REG, val32);
-+ if (val32 != DOWNLOAD_PENDING)
-+ break;
-+ mdelay(i);
-+ }
-+ if (val32 != DOWNLOAD_SUCCESS) {
-+ dev_dbg(hw_priv->pdev, "wait for download completion failed. " \
-+ "Read: 0x%.8X\n", val32);
-+ ret = -ETIMEDOUT;
-+ goto error;
-+ } else {
-+ dev_dbg(hw_priv->pdev, "Firmware completed.\n");
-+ ret = 0;
-+ }
-+
-+error:
-+ if(buf)
-+ kfree(buf);
-+ if (firmware) {
-+ release_firmware(firmware);
-+ }
-+ return ret;
-+}
-+
-+static int xradio_bootloader(struct xradio_common *hw_priv)
-+{
-+ const char *bl_path = XR819_BOOTLOADER;
-+ u32 addr = AHB_MEMORY_ADDRESS;
-+ int ret;
-+ u32 i;
-+ u32 *data;
-+ const struct firmware *bootloader;
-+
-+ /* Load a bootloader file */
-+ ret = request_firmware(&bootloader, bl_path, hw_priv->pdev);
-+ if (ret) {
-+ dev_dbg(hw_priv->pdev, "can't load bootloader file %s.\n",
-+ bl_path);
-+ goto error;
-+ }
-+
-+ /* Down bootloader. */
-+ data = (u32 *)bootloader->data;
-+ for(i = 0; i < (bootloader->size)/4; i++, addr+=4) {
-+ REG_WRITE(HIF_SRAM_BASE_ADDR_REG_ID, addr);
-+ REG_WRITE(HIF_AHB_DPORT_REG_ID,data[i]);
-+ }
-+ dev_dbg(hw_priv->pdev, "Bootloader complete\n");
-+
-+error:
-+ if(bootloader) {
-+ release_firmware(bootloader);
-+ }
-+ return ret;
-+}
-+
-+bool test_retry = false;
-+int xradio_load_firmware(struct xradio_common *hw_priv)
-+{
-+ int ret;
-+ int i;
-+ u32 val32;
-+ u16 val16;
-+ u32 dpll = 0;
-+ int major_revision;
-+
-+ /* Read CONFIG Register Value - We will read 32 bits */
-+ ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't read config register, err=%d.\n",
-+ ret);
-+ return ret;
-+ }
-+
-+ //check hardware type and revision.
-+ hw_priv->hw_type = xradio_get_hw_type(val32, &major_revision);
-+ switch (hw_priv->hw_type) {
-+ case HIF_HW_TYPE_XRADIO:
-+ dev_dbg(hw_priv->pdev, "HW_TYPE_XRADIO detected.\n");
-+ break;
-+ default:
-+ dev_dbg(hw_priv->pdev, "Unknown hardware: %d.\n",
-+ hw_priv->hw_type);
-+ return -ENOTSUPP;
-+ }
-+ if (major_revision == 4) {
-+ hw_priv->hw_revision = XR819_HW_REV0;
-+ dev_dbg(hw_priv->pdev, "XRADIO_HW_REV 1.0 detected.\n");
-+ } else {
-+ dev_dbg(hw_priv->pdev, "Unsupported major revision %d.\n",
-+ major_revision);
-+ return -ENOTSUPP;
-+ }
-+
-+ //load sdd file, and get config from it.
-+ ret = xradio_parse_sdd(hw_priv, &dpll);
-+ if (ret < 0) {
-+ return ret;
-+ }
-+
-+ //set dpll initial value and check.
-+ ret = xradio_reg_write_32(hw_priv, HIF_TSET_GEN_R_W_REG_ID, dpll);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't write DPLL register.\n");
-+ goto out;
-+ }
-+ msleep(5);
-+ ret = xradio_reg_read_32(hw_priv, HIF_TSET_GEN_R_W_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't read DPLL register.\n");
-+ goto out;
-+ }
-+ if (val32 != dpll) {
-+ dev_dbg(hw_priv->pdev, "unable to initialise " \
-+ "DPLL register. Wrote 0x%.8X, read 0x%.8X.\n",
-+ dpll, val32);
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ /* Set wakeup bit in device */
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONTROL_REG_ID, &val16);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "set_wakeup: can't read control register.\n");
-+ goto out;
-+ }
-+ ret = xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, val16 | HIF_CTRL_WUP_BIT);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "set_wakeup: can't write control register.\n");
-+ goto out;
-+ }
-+
-+ /* Wait for wakeup */
-+ for (i = 0 ; i < 300 ; i += 1 + i / 2) {
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONTROL_REG_ID, &val16);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "Wait_for_wakeup: "
-+ "can't read control register.\n");
-+ goto out;
-+ }
-+ if (val16 & HIF_CTRL_RDY_BIT) {
-+ break;
-+ }
-+ msleep(i);
-+ }
-+ if ((val16 & HIF_CTRL_RDY_BIT) == 0) {
-+ dev_dbg(hw_priv->pdev, "Wait for wakeup:"
-+ "device is not responding.\n");
-+ ret = -ETIMEDOUT;
-+ goto out;
-+ } else {
-+ dev_dbg(hw_priv->pdev, "WLAN device is ready.\n");
-+ }
-+
-+ /* Checking for access mode and download firmware. */
-+ ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "check_access_mode: "
-+ "can't read config register.\n");
-+ goto out;
-+ }
-+ if (val32 & HIF_CONFIG_ACCESS_MODE_BIT) {
-+ /* Down bootloader. */
-+ ret = xradio_bootloader(hw_priv);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't download bootloader.\n");
-+ goto out;
-+ }
-+ /* Down firmware. */
-+ ret = xradio_firmware(hw_priv);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "can't download firmware.\n");
-+ goto out;
-+ }
-+ } else {
-+ dev_dbg(hw_priv->pdev, "check_access_mode: "
-+ "device is already in QUEUE mode.\n");
-+ /* TODO: verify this branch. Do we need something to do? */
-+ }
-+
-+ if (HIF_HW_TYPE_XRADIO == hw_priv->hw_type) {
-+ /* If device is XRADIO the IRQ enable/disable bits
-+ * are in CONFIG register */
-+ ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "enable_irq: can't read " \
-+ "config register.\n");
-+ goto unsubscribe;
-+ }
-+ ret = xradio_reg_write_32(hw_priv, HIF_CONFIG_REG_ID,
-+ val32 | HIF_CONF_IRQ_RDY_ENABLE);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "enable_irq: can't write " \
-+ "config register.\n");
-+ goto unsubscribe;
-+ }
-+ } else {
-+ /* If device is XRADIO the IRQ enable/disable bits
-+ * are in CONTROL register */
-+ /* Enable device interrupts - Both DATA_RDY and WLAN_RDY */
-+ ret = xradio_reg_read_16(hw_priv, HIF_CONFIG_REG_ID, &val16);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "enable_irq: can't read " \
-+ "control register.\n");
-+ goto unsubscribe;
-+ }
-+ ret = xradio_reg_write_16(hw_priv, HIF_CONFIG_REG_ID,
-+ val16 | HIF_CTRL_IRQ_RDY_ENABLE);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "enable_irq: can't write " \
-+ "control register.\n");
-+ goto unsubscribe;
-+ }
-+
-+ }
-+
-+ /* Configure device for MESSSAGE MODE */
-+ ret = xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "set_mode: can't read config register.\n");
-+ goto unsubscribe;
-+ }
-+ ret = xradio_reg_write_32(hw_priv, HIF_CONFIG_REG_ID,
-+ val32 & ~HIF_CONFIG_ACCESS_MODE_BIT);
-+ if (ret < 0) {
-+ dev_dbg(hw_priv->pdev, "set_mode: can't write config register.\n");
-+ goto unsubscribe;
-+ }
-+
-+ /* Unless we read the CONFIG Register we are
-+ * not able to get an interrupt */
-+ mdelay(10);
-+ xradio_reg_read_32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ return 0;
-+
-+unsubscribe:
-+out:
-+ if (hw_priv->sdd) {
-+ release_firmware(hw_priv->sdd);
-+ hw_priv->sdd = NULL;
-+ }
-+ return ret;
-+}
-+
-+int xradio_dev_deinit(struct xradio_common *hw_priv)
-+{
-+ if (hw_priv->sdd) {
-+ release_firmware(hw_priv->sdd);
-+ hw_priv->sdd = NULL;
-+ }
-+ return 0;
-+}
-diff --git a/drivers/net/wireless/xradio/fwio.h b/drivers/net/wireless/xradio/fwio.h
-new file mode 100644
-index 0000000..b5efeb1
---- /dev/null
-+++ b/drivers/net/wireless/xradio/fwio.h
-@@ -0,0 +1,33 @@
-+/*
-+ * Firmware APIs for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef FWIO_H_INCLUDED
-+#define FWIO_H_INCLUDED
-+
-+#define XR819_HW_REV0 (8190)
-+#define XR819_BOOTLOADER ("xr819/boot_xr819.bin")
-+#define XR819_FIRMWARE ("xr819/fw_xr819.bin")
-+#define XR819_SDD_FILE ("xr819/sdd_xr819.bin")
-+
-+#define SDD_PTA_CFG_ELT_ID 0xEB
-+#define SDD_REFERENCE_FREQUENCY_ELT_ID 0xC5
-+#define FIELD_OFFSET(type, field) ((u8 *)&((type *)0)->field - (u8 *)0)
-+#define FIND_NEXT_ELT(e) (struct xradio_sdd *)((u8 *)&e->data + e->length)
-+struct xradio_sdd {
-+ u8 id;
-+ u8 length;
-+ u8 data[];
-+};
-+
-+struct xradio_common;
-+int xradio_load_firmware(struct xradio_common *hw_priv);
-+int xradio_dev_deinit(struct xradio_common *hw_priv);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/ht.c b/drivers/net/wireless/xradio/ht.c
-new file mode 100644
-index 0000000..a9b3630
---- /dev/null
-+++ b/drivers/net/wireless/xradio/ht.c
-@@ -0,0 +1,86 @@
-+#include
-+
-+#include "xradio.h"
-+#include "sta.h"
-+
-+#define AG_RATE_INDEX 6 //11a/g rate for important short frames in 5G.
-+
-+#ifdef AP_HT_COMPAT_FIX
-+#define AP_COMPAT_THRESHOLD 2000
-+#define AP_COMPAT_MIN_CNT 200
-+u8 ap_compat_bssid[ETH_ALEN] = {0};
-+int xradio_apcompat_detect(struct xradio_vif *priv, u8 rx_rate)
-+{
-+ if (rx_rate < AG_RATE_INDEX) {
-+ priv->ht_compat_cnt++;
-+ txrx_printk(XRADIO_DBG_MSG,"%s:rate=%d.\n", __func__, rx_rate);
-+ } else {
-+ priv->ht_compat_det |= 1;
-+ priv->ht_compat_cnt = 0;
-+ txrx_printk(XRADIO_DBG_NIY,"%s:HT compat detect\n", __func__);
-+ return 0;
-+ }
-+
-+ /* Enhance compatibility with some illegal APs.*/
-+ if (priv->ht_compat_cnt > AP_COMPAT_THRESHOLD ||
-+ (priv->ht_compat_cnt > AP_COMPAT_MIN_CNT &&
-+ priv->bssid[0] == 0xC8 &&
-+ priv->bssid[1] == 0x3A &&
-+ priv->bssid[2] == 0x35)) {
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ memcpy(ap_compat_bssid, priv->bssid, ETH_ALEN);
-+ wms_send_disassoc_to_self(hw_priv, priv);
-+ txrx_printk(XRADIO_DBG_WARN, "%s:SSID=%s, BSSID=" \
-+ "%02x:%02x:%02x:%02x:%02x:%02x\n", __func__, priv->ssid,
-+ ap_compat_bssid[0], ap_compat_bssid[1],
-+ ap_compat_bssid[2], ap_compat_bssid[3],
-+ ap_compat_bssid[4], ap_compat_bssid[5]);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void xradio_remove_ht_ie(struct xradio_vif *priv, struct sk_buff *skb)
-+{
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-+ u8 *ies = NULL;
-+ size_t ies_len = 0;
-+ u8 *ht_ie = NULL;
-+
-+ if (!mgmt || memcmp(ap_compat_bssid, mgmt->bssid, ETH_ALEN))
-+ return;
-+
-+ if (ieee80211_is_probe_resp(mgmt->frame_control))
-+ ies = mgmt->u.probe_resp.variable;
-+ else if (ieee80211_is_beacon(mgmt->frame_control))
-+ ies = mgmt->u.beacon.variable;
-+ else if (ieee80211_is_assoc_resp(mgmt->frame_control))
-+ ies = mgmt->u.assoc_resp.variable;
-+ else if (ieee80211_is_assoc_req(mgmt->frame_control))
-+ ies = mgmt->u.assoc_req.variable;
-+ else
-+ return;
-+
-+ ies_len = skb->len - (ies - (u8 *)(skb->data));
-+ ht_ie = (u8 *)xradio_get_ie(ies, ies_len, WLAN_EID_HT_CAPABILITY);
-+ if (ht_ie) {
-+ u8 ht_len = *(ht_ie + 1) + 2;
-+ u8 move_len = (ies + ies_len) - (ht_ie + ht_len);
-+ memmove(ht_ie, (ht_ie + ht_len), move_len);
-+ skb_trim(skb, skb->len - ht_len);
-+ ies_len = skb->len - (ies - (u8 *)(skb->data));
-+ ht_ie = (u8 *)xradio_get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
-+ if (ht_ie) {
-+ ht_len = *(ht_ie + 1) + 2;
-+ move_len = (ies + ies_len) - (ht_ie + ht_len);
-+ memmove(ht_ie, (ht_ie + ht_len), move_len);
-+ skb_trim(skb, skb->len - ht_len);
-+ }
-+ }
-+ txrx_printk(XRADIO_DBG_WARN, "%s: BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
-+ __func__,
-+ mgmt->bssid[0], mgmt->bssid[1],
-+ mgmt->bssid[2], mgmt->bssid[3],
-+ mgmt->bssid[4], mgmt->bssid[5]);
-+}
-+#endif //AP_HT_COMPAT_FIX
-\ No newline at end of file
-diff --git a/drivers/net/wireless/xradio/ht.h b/drivers/net/wireless/xradio/ht.h
-new file mode 100644
-index 0000000..346b425
---- /dev/null
-+++ b/drivers/net/wireless/xradio/ht.h
-@@ -0,0 +1,44 @@
-+/*
-+ * HT-related code for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef XRADIO_HT_H_INCLUDED
-+#define XRADIO_HT_H_INCLUDED
-+
-+#include
-+
-+struct xradio_ht_oper {
-+ struct ieee80211_sta_ht_cap ht_cap;
-+ enum nl80211_channel_type channel_type;
-+ u16 operation_mode;
-+};
-+
-+static inline int xradio_is_ht(const struct xradio_ht_oper *ht_oper)
-+{
-+ return ht_oper->channel_type != NL80211_CHAN_NO_HT;
-+}
-+
-+static inline int xradio_ht_greenfield(const struct xradio_ht_oper *ht_oper)
-+{
-+ return (xradio_is_ht(ht_oper) &&
-+ (ht_oper->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
-+ !(ht_oper->operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT));
-+}
-+
-+static inline int xradio_ht_ampdu_density(const struct xradio_ht_oper *ht_oper)
-+{
-+ if (!xradio_is_ht(ht_oper))
-+ return 0;
-+ return ht_oper->ht_cap.ampdu_density;
-+}
-+
-+int xradio_apcompat_detect(struct xradio_vif *priv, u8 rx_rate);
-+void xradio_remove_ht_ie(struct xradio_vif *priv, struct sk_buff *skb);
-+
-+#endif /* XRADIO_HT_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/hwio.c b/drivers/net/wireless/xradio/hwio.c
-new file mode 100644
-index 0000000..b813333
---- /dev/null
-+++ b/drivers/net/wireless/xradio/hwio.c
-@@ -0,0 +1,280 @@
-+/*
-+ * Hardware I/O implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+
-+#include "xradio.h"
-+#include "hwio.h"
-+#include "sdio.h"
-+
-+#define CHECK_ADDR_LEN 1
-+
-+ /* Sdio addr is 4*spi_addr */
-+#define SPI_REG_ADDR_TO_SDIO(spi_reg_addr) ((spi_reg_addr) << 2)
-+#define SDIO_ADDR17BIT(buf_id, mpf, rfu, reg_id_ofs) \
-+ ((((buf_id) & 0x1F) << 7) \
-+ | (((mpf) & 1) << 6) \
-+ | (((rfu) & 1) << 5) \
-+ | (((reg_id_ofs) & 0x1F) << 0))
-+#define MAX_RETRY 3
-+
-+
-+static int __xradio_read(struct xradio_common *hw_priv, u16 addr,
-+ void *buf, size_t buf_len, int buf_id)
-+{
-+ u16 addr_sdio;
-+ u32 sdio_reg_addr_17bit ;
-+
-+#if (CHECK_ADDR_LEN)
-+ /* Check if buffer is aligned to 4 byte boundary */
-+ if (WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
-+ dev_dbg(hw_priv->pdev, "buffer is not aligned.\n");
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ /* Convert to SDIO Register Address */
-+ addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
-+ sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
-+ return sdio_data_read(hw_priv,
-+ sdio_reg_addr_17bit,
-+ buf, buf_len);
-+}
-+
-+static int __xradio_write(struct xradio_common *hw_priv, u16 addr,
-+ const void *buf, size_t buf_len, int buf_id)
-+{
-+ u16 addr_sdio;
-+ u32 sdio_reg_addr_17bit ;
-+
-+#if (CHECK_ADDR_LEN)
-+ /* Check if buffer is aligned to 4 byte boundary */
-+ if (WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
-+ dev_err(hw_priv->pdev, "buffer is not aligned.\n");
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ /* Convert to SDIO Register Address */
-+ addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
-+ sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
-+
-+ return sdio_data_write(hw_priv,
-+ sdio_reg_addr_17bit,
-+ buf, buf_len);
-+}
-+
-+static inline int __xradio_read_reg32(struct xradio_common *hw_priv,
-+ u16 addr, u32 *val)
-+{
-+ return __xradio_read(hw_priv, addr, val, sizeof(val), 0);
-+}
-+
-+static inline int __xradio_write_reg32(struct xradio_common *hw_priv,
-+ u16 addr, u32 val)
-+{
-+ return __xradio_write(hw_priv, addr, &val, sizeof(val), 0);
-+}
-+
-+int xradio_reg_read(struct xradio_common *hw_priv, u16 addr,
-+ void *buf, size_t buf_len)
-+{
-+ int ret;
-+ sdio_lock(hw_priv);
-+ ret = __xradio_read(hw_priv, addr, buf, buf_len, 0);
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_reg_write(struct xradio_common *hw_priv, u16 addr,
-+ const void *buf, size_t buf_len)
-+{
-+ int ret;
-+ sdio_lock(hw_priv);
-+ ret = __xradio_write(hw_priv, addr, buf, buf_len, 0);
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_data_read(struct xradio_common *hw_priv, void *buf, size_t buf_len)
-+{
-+ int ret, retry = 1;
-+ sdio_lock(hw_priv);
-+ {
-+ int buf_id_rx = hw_priv->buf_id_rx;
-+ while (retry <= MAX_RETRY) {
-+ ret = __xradio_read(hw_priv, HIF_IN_OUT_QUEUE_REG_ID, buf,
-+ buf_len, buf_id_rx + 1);
-+ if (!ret) {
-+ buf_id_rx = (buf_id_rx + 1) & 3;
-+ hw_priv->buf_id_rx = buf_id_rx;
-+ break;
-+ } else {
-+ //~dgp this retrying stuff is silly as it can crash the fw if there is nothing to read
-+ dev_err(hw_priv->pdev, "data read error :%d - attempt %d of %d\n", ret, retry, MAX_RETRY);
-+ retry++;
-+ mdelay(1);
-+ }
-+ }
-+ }
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_data_write(struct xradio_common *hw_priv, const void *buf,
-+ size_t buf_len)
-+{
-+ int ret, retry = 1;
-+ sdio_lock(hw_priv);
-+ {
-+ int buf_id_tx = hw_priv->buf_id_tx;
-+ while (retry <= MAX_RETRY) {
-+ ret = __xradio_write(hw_priv, HIF_IN_OUT_QUEUE_REG_ID, buf,
-+ buf_len, buf_id_tx);
-+ if (!ret) {
-+ buf_id_tx = (buf_id_tx + 1) & 31;
-+ hw_priv->buf_id_tx = buf_id_tx;
-+ break;
-+ } else {
-+ dev_err(hw_priv->pdev, "data write error :%d - attempt %d - %d\n", ret, retry, MAX_RETRY);
-+ retry++;
-+ mdelay(1);
-+ }
-+ }
-+ }
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_indirect_read(struct xradio_common *hw_priv, u32 addr, void *buf,
-+ size_t buf_len, u32 prefetch, u16 port_addr)
-+{
-+ u32 val32 = 0;
-+ int i, ret;
-+
-+ if ((buf_len / 2) >= 0x1000) {
-+ dev_err(hw_priv->pdev, "Can't read more than 0xfff words.\n");
-+ return -EINVAL;
-+ goto out;
-+ }
-+
-+ sdio_lock(hw_priv);
-+ /* Write address */
-+ ret = __xradio_write_reg32(hw_priv, HIF_SRAM_BASE_ADDR_REG_ID, addr);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write address register.\n");
-+ goto out;
-+ }
-+
-+ /* Read CONFIG Register Value - We will read 32 bits */
-+ ret = __xradio_read_reg32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't read config register.\n");
-+ goto out;
-+ }
-+
-+ /* Set PREFETCH bit */
-+ ret = __xradio_write_reg32(hw_priv, HIF_CONFIG_REG_ID, val32 | prefetch);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write prefetch bit.\n");
-+ goto out;
-+ }
-+
-+ /* Check for PRE-FETCH bit to be cleared */
-+ for (i = 0; i < 20; i++) {
-+ ret = __xradio_read_reg32(hw_priv, HIF_CONFIG_REG_ID, &val32);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't check prefetch bit.\n");
-+ goto out;
-+ }
-+ if (!(val32 & prefetch))
-+ break;
-+ mdelay(i);
-+ }
-+
-+ if (val32 & prefetch) {
-+ dev_err(hw_priv->pdev, "Prefetch bit is not cleared.\n");
-+ goto out;
-+ }
-+
-+ /* Read data port */
-+ ret = __xradio_read(hw_priv, port_addr, buf, buf_len, 0);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't read data port.\n");
-+ goto out;
-+ }
-+
-+out:
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_apb_write(struct xradio_common *hw_priv, u32 addr, const void *buf,
-+ size_t buf_len)
-+{
-+ int ret;
-+
-+ if ((buf_len / 2) >= 0x1000) {
-+ dev_err(hw_priv->pdev, "Can't wrire more than 0xfff words.\n");
-+ return -EINVAL;
-+ }
-+
-+ sdio_lock(hw_priv);
-+
-+ /* Write address */
-+ ret = __xradio_write_reg32(hw_priv, HIF_SRAM_BASE_ADDR_REG_ID, addr);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write address register.\n");
-+ goto out;
-+ }
-+
-+ /* Write data port */
-+ ret = __xradio_write(hw_priv, HIF_SRAM_DPORT_REG_ID, buf, buf_len, 0);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write data port.\n");
-+ goto out;
-+ }
-+
-+out:
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-+
-+int xradio_ahb_write(struct xradio_common *hw_priv, u32 addr, const void *buf,
-+ size_t buf_len)
-+{
-+ int ret;
-+
-+ if ((buf_len / 2) >= 0x1000) {
-+ dev_err(hw_priv->pdev, "Can't wrire more than 0xfff words.\n");
-+ return -EINVAL;
-+ }
-+
-+ sdio_lock(hw_priv);
-+
-+ /* Write address */
-+ ret = __xradio_write_reg32(hw_priv, HIF_SRAM_BASE_ADDR_REG_ID, addr);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write address register.\n");
-+ goto out;
-+ }
-+
-+ /* Write data port */
-+ ret = __xradio_write(hw_priv, HIF_AHB_DPORT_REG_ID, buf, buf_len, 0);
-+ if (ret < 0) {
-+ dev_err(hw_priv->pdev, "Can't write data port.\n");
-+ goto out;
-+ }
-+
-+out:
-+ sdio_unlock(hw_priv);
-+ return ret;
-+}
-diff --git a/drivers/net/wireless/xradio/hwio.h b/drivers/net/wireless/xradio/hwio.h
-new file mode 100644
-index 0000000..531c2b8
---- /dev/null
-+++ b/drivers/net/wireless/xradio/hwio.h
-@@ -0,0 +1,229 @@
-+/*
-+ * hardware interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_HWIO_H_INCLUDED
-+#define XRADIO_HWIO_H_INCLUDED
-+
-+/* extern */ struct xradio_common;
-+
-+/* DPLL initial values */
-+#define DPLL_INIT_VAL_XRADIO (0x0EC4F121)
-+
-+/* Hardware Type Definitions */
-+#define HIF_HW_TYPE_XRADIO (1)
-+
-+
-+/* boot loader start address in SRAM */
-+#define DOWNLOAD_BOOT_LOADER_OFFSET (0x00000000)
-+/* 32K, 0x4000 to 0xDFFF */
-+#define DOWNLOAD_FIFO_OFFSET (0x00004000)
-+/* 32K */
-+#define DOWNLOAD_FIFO_SIZE (0x00008000)
-+/* 128 bytes, 0xFF80 to 0xFFFF */
-+#define DOWNLOAD_CTRL_OFFSET (0x0000FF80)
-+#define DOWNLOAD_CTRL_DATA_DWORDS (32-6)
-+
-+/* Download control area */
-+struct download_cntl_t {
-+ /* size of whole firmware file (including Cheksum), host init */
-+ u32 ImageSize;
-+ /* downloading flags */
-+ u32 Flags;
-+ /* No. of bytes put into the download, init & updated by host */
-+ u32 Put;
-+ /* last traced program counter, last ARM reg_pc */
-+ u32 TracePc;
-+ /* No. of bytes read from the download, host init, device updates */
-+ u32 Get;
-+ /* r0, boot losader status, host init to pending, device updates */
-+ u32 Status;
-+ /* Extra debug info, r1 to r14 if status=r0=DOWNLOAD_EXCEPTION */
-+ u32 DebugData[DOWNLOAD_CTRL_DATA_DWORDS];
-+};
-+
-+#define DOWNLOAD_IMAGE_SIZE_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, ImageSize))
-+#define DOWNLOAD_FLAGS_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, Flags))
-+#define DOWNLOAD_PUT_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, Put))
-+#define DOWNLOAD_TRACE_PC_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, TracePc))
-+#define DOWNLOAD_GET_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, Get))
-+#define DOWNLOAD_STATUS_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, Status))
-+#define DOWNLOAD_DEBUG_DATA_REG \
-+ (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, DebugData))
-+
-+#define DOWNLOAD_DEBUG_DATA_LEN (108)
-+#define DOWNLOAD_BLOCK_SIZE (1024)
-+
-+/* For boot loader detection */
-+#define DOWNLOAD_ARE_YOU_HERE (0x87654321)
-+#define DOWNLOAD_I_AM_HERE (0x12345678)
-+
-+/* Download error code */
-+#define DOWNLOAD_PENDING (0xFFFFFFFF)
-+#define DOWNLOAD_SUCCESS (0)
-+#define DOWNLOAD_EXCEPTION (1)
-+#define DOWNLOAD_ERR_MEM_1 (2)
-+#define DOWNLOAD_ERR_MEM_2 (3)
-+#define DOWNLOAD_ERR_SOFTWARE (4)
-+#define DOWNLOAD_ERR_FILE_SIZE (5)
-+#define DOWNLOAD_ERR_CHECKSUM (6)
-+#define DOWNLOAD_ERR_OVERFLOW (7)
-+#define DOWNLOAD_ERR_IMAGE (8)
-+#define DOWNLOAD_ERR_HOST (9)
-+#define DOWNLOAD_ERR_ABORT (10)
-+
-+#define SYS_BASE_ADDR_SILICON (0)
-+#define AHB_MEMORY_ADDRESS (SYS_BASE_ADDR_SILICON + 0x08000000)
-+#define PAC_BASE_ADDRESS_SILICON (SYS_BASE_ADDR_SILICON + 0x09000000)
-+#define PAC_SHARED_MEMORY_SILICON (PAC_BASE_ADDRESS_SILICON)
-+#define APB_ADDR(addr) (PAC_SHARED_MEMORY_SILICON + (addr))
-+
-+/* ***************************************************************
-+*Device register definitions
-+*************************************************************** */
-+/* WBF - SPI Register Addresses */
-+#define HIF_ADDR_ID_BASE (0x0000)
-+/* 16/32 bits */
-+#define HIF_CONFIG_REG_ID (0x0000)
-+/* 16/32 bits */
-+#define HIF_CONTROL_REG_ID (0x0001)
-+/* 16 bits, Q mode W/R */
-+#define HIF_IN_OUT_QUEUE_REG_ID (0x0002)
-+/* 32 bits, AHB bus R/W */
-+#define HIF_AHB_DPORT_REG_ID (0x0003)
-+/* 16/32 bits */
-+#define HIF_SRAM_BASE_ADDR_REG_ID (0x0004)
-+/* 32 bits, APB bus R/W */
-+#define HIF_SRAM_DPORT_REG_ID (0x0005)
-+/* 32 bits, t_settle/general */
-+#define HIF_TSET_GEN_R_W_REG_ID (0x0006)
-+/* 16 bits, Q mode read, no length */
-+#define HIF_FRAME_OUT_REG_ID (0x0007)
-+#define HIF_ADDR_ID_MAX (HIF_FRAME_OUT_REG_ID)
-+
-+/* WBF - Control register bit set */
-+/* next o/p length, bit 11 to 0 */
-+#define HIF_CTRL_NEXT_LEN_MASK (0x0FFF)
-+#define HIF_CTRL_WUP_BIT (BIT(12))
-+#define HIF_CTRL_RDY_BIT (BIT(13))
-+#define HIF_CTRL_IRQ_ENABLE (BIT(14))
-+#define HIF_CTRL_RDY_ENABLE (BIT(15))
-+#define HIF_CTRL_IRQ_RDY_ENABLE (BIT(14)|BIT(15))
-+
-+/* SPI Config register bit set */
-+#define HIF_CONFIG_FRAME_BIT (BIT(2))
-+#define HIF_CONFIG_WORD_MODE_BITS (BIT(3)|BIT(4))
-+#define HIF_CONFIG_WORD_MODE_1 (BIT(3))
-+#define HIF_CONFIG_WORD_MODE_2 (BIT(4))
-+#define HIF_CONFIG_ERROR_0_BIT (BIT(5))
-+#define HIF_CONFIG_ERROR_1_BIT (BIT(6))
-+#define HIF_CONFIG_ERROR_2_BIT (BIT(7))
-+/* TBD: Sure??? */
-+#define HIF_CONFIG_CSN_FRAME_BIT (BIT(7))
-+#define HIF_CONFIG_ERROR_3_BIT (BIT(8))
-+#define HIF_CONFIG_ERROR_4_BIT (BIT(9))
-+/* QueueM */
-+#define HIF_CONFIG_ACCESS_MODE_BIT (BIT(10))
-+/* AHB bus */
-+#define HIF_CONFIG_AHB_PFETCH_BIT (BIT(11))
-+#define HIF_CONFIG_CPU_CLK_DIS_BIT (BIT(12))
-+/* APB bus */
-+#define HIF_CONFIG_PFETCH_BIT (BIT(13))
-+/* cpu reset */
-+#define HIF_CONFIG_CPU_RESET_BIT (BIT(14))
-+#define HIF_CONFIG_CLEAR_INT_BIT (BIT(15))
-+
-+/* For XRADIO the IRQ Enable and Ready Bits are in CONFIG register */
-+#define HIF_CONF_IRQ_RDY_ENABLE (BIT(16)|BIT(17))
-+
-+int xradio_data_read(struct xradio_common *hw_priv, void *buf, size_t buf_len);
-+int xradio_data_write(struct xradio_common *hw_priv, const void *buf, size_t buf_len);
-+int xradio_reg_read(struct xradio_common *hw_priv, u16 addr, void *buf, size_t buf_len);
-+int xradio_reg_write(struct xradio_common *hw_priv, u16 addr, const void *buf, size_t buf_len);
-+int xradio_indirect_read(struct xradio_common *hw_priv, u32 addr, void *buf,
-+ size_t buf_len, u32 prefetch, u16 port_addr);
-+int xradio_apb_write(struct xradio_common *hw_priv, u32 addr, const void *buf, size_t buf_len);
-+int xradio_ahb_write(struct xradio_common *hw_priv, u32 addr, const void *buf, size_t buf_len);
-+
-+
-+static inline int xradio_reg_read_16(struct xradio_common *hw_priv,
-+ u16 addr, u16 *val)
-+{
-+ int ret = 0;
-+ u32 bigVal = 0;
-+ ret = xradio_reg_read(hw_priv, addr, &bigVal, sizeof(bigVal));
-+ *val = (u16)bigVal;
-+ return ret;
-+}
-+
-+static inline int xradio_reg_write_16(struct xradio_common *hw_priv,
-+ u16 addr, u16 val)
-+{
-+ u32 bigVal = (u32)val;
-+ return xradio_reg_write(hw_priv, addr, &bigVal, sizeof(bigVal));
-+}
-+
-+static inline int xradio_reg_read_32(struct xradio_common *hw_priv,
-+ u16 addr, u32 *val)
-+{
-+ return xradio_reg_read(hw_priv, addr, val, sizeof(val));
-+}
-+
-+static inline int xradio_reg_write_32(struct xradio_common *hw_priv,
-+ u16 addr, u32 val)
-+{
-+ return xradio_reg_write(hw_priv, addr, &val, sizeof(val));
-+}
-+
-+static inline int xradio_apb_read(struct xradio_common *hw_priv, u32 addr,
-+ void *buf, size_t buf_len)
-+{
-+ return xradio_indirect_read(hw_priv, addr, buf, buf_len, HIF_CONFIG_PFETCH_BIT,
-+ HIF_SRAM_DPORT_REG_ID);
-+}
-+
-+static inline int xradio_ahb_read(struct xradio_common *hw_priv, u32 addr,
-+ void *buf, size_t buf_len)
-+{
-+ return xradio_indirect_read(hw_priv, addr, buf, buf_len, HIF_CONFIG_AHB_PFETCH_BIT,
-+ HIF_AHB_DPORT_REG_ID);
-+}
-+
-+static inline int xradio_apb_read_32(struct xradio_common *hw_priv,
-+ u32 addr, u32 *val)
-+{
-+ return xradio_apb_read(hw_priv, addr, val, sizeof(val));
-+}
-+
-+static inline int xradio_apb_write_32(struct xradio_common *hw_priv,
-+ u32 addr, u32 val)
-+{
-+ return xradio_apb_write(hw_priv, addr, &val, sizeof(val));
-+}
-+
-+static inline int xradio_ahb_read_32(struct xradio_common *hw_priv,
-+ u32 addr, u32 *val)
-+{
-+ return xradio_ahb_read(hw_priv, addr, val, sizeof(val));
-+}
-+
-+static inline int xradio_ahb_write_32(struct xradio_common *hw_priv,
-+ u32 addr, u32 val)
-+{
-+ return xradio_ahb_write(hw_priv, addr, &val, sizeof(val));
-+}
-+
-+#endif /* XRADIO_HWIO_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/keys.c b/drivers/net/wireless/xradio/keys.c
-new file mode 100644
-index 0000000..20050e1
---- /dev/null
-+++ b/drivers/net/wireless/xradio/keys.c
-@@ -0,0 +1,193 @@
-+#include
-+
-+#include "xradio.h"
-+#include "sta.h"
-+#include "keys.h"
-+
-+int xradio_alloc_key(struct xradio_common *hw_priv)
-+{
-+ int idx;
-+
-+ idx = ffs(~hw_priv->key_map) - 1;
-+ if (idx < 0 || idx > WSM_KEY_MAX_INDEX)
-+ return -1;
-+
-+ hw_priv->key_map |= BIT(idx);
-+ hw_priv->keys[idx].entryIndex = idx;
-+ return idx;
-+}
-+
-+void xradio_free_key(struct xradio_common *hw_priv, int idx)
-+{
-+ BUG_ON(!(hw_priv->key_map & BIT(idx)));
-+ memset(&hw_priv->keys[idx], 0, sizeof(hw_priv->keys[idx]));
-+ hw_priv->key_map &= ~BIT(idx);
-+}
-+
-+void xradio_free_keys(struct xradio_common *hw_priv)
-+{
-+ memset(&hw_priv->keys, 0, sizeof(hw_priv->keys));
-+ hw_priv->key_map = 0;
-+}
-+
-+int xradio_upload_keys(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int idx, ret = 0;
-+
-+
-+ for (idx = 0; idx <= WSM_KEY_MAX_IDX; ++idx)
-+ if (hw_priv->key_map & BIT(idx)) {
-+ ret = wsm_add_key(hw_priv, &hw_priv->keys[idx], priv->if_id);
-+ if (ret < 0)
-+ break;
-+ }
-+ return ret;
-+}
-+
-+int xradio_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
-+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-+ struct ieee80211_key_conf *key)
-+{
-+#ifdef XRADIO_DISABLE_HW_CRYPTO
-+ wiphy_info(dev->wiphy, "hw crypto is disabled, ignoring key request\n");
-+ return -EOPNOTSUPP;
-+#else
-+ int ret = -EOPNOTSUPP;
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+
-+ wiphy_dbg(dev->wiphy, "vif %d: set_key cmd %d\n", priv->if_id, (int) cmd);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ if (cmd == SET_KEY) {
-+ u8 *peer_addr = NULL;
-+ int pairwise = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? 1 : 0;
-+ int idx = xradio_alloc_key(hw_priv);
-+ struct wsm_add_key *wsm_key = &hw_priv->keys[idx];
-+
-+ if (idx < 0) {
-+ wiphy_err(dev->wiphy, "xradio_alloc_key failed!\n");
-+ ret = -EINVAL;
-+ goto finally;
-+ }
-+
-+ BUG_ON(pairwise && !sta);
-+ if (sta)
-+ peer_addr = sta->addr;
-+
-+ key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
-+
-+ priv->cipherType = key->cipher;
-+ switch (key->cipher) {
-+ case WLAN_CIPHER_SUITE_WEP40:
-+ case WLAN_CIPHER_SUITE_WEP104:
-+ if (key->keylen > 16) {
-+ xradio_free_key(hw_priv, idx);
-+ wiphy_err(dev->wiphy, "keylen too long=%d!\n", key->keylen);
-+ ret = -EINVAL;
-+ goto finally;
-+ }
-+
-+ if (pairwise) {
-+ wsm_key->type = WSM_KEY_TYPE_WEP_PAIRWISE;
-+ memcpy(wsm_key->wepPairwiseKey.peerAddress, peer_addr, ETH_ALEN);
-+ memcpy(wsm_key->wepPairwiseKey.keyData, &key->key[0], key->keylen);
-+ wsm_key->wepPairwiseKey.keyLength = key->keylen;
-+ } else {
-+ wsm_key->type = WSM_KEY_TYPE_WEP_DEFAULT;
-+ memcpy(wsm_key->wepGroupKey.keyData, &key->key[0], key->keylen);
-+ wsm_key->wepGroupKey.keyLength = key->keylen;
-+ wsm_key->wepGroupKey.keyId = key->keyidx;
-+ }
-+ break;
-+ case WLAN_CIPHER_SUITE_TKIP:
-+ if (pairwise) {
-+ wsm_key->type = WSM_KEY_TYPE_TKIP_PAIRWISE;
-+ memcpy(wsm_key->tkipPairwiseKey.peerAddress, peer_addr, ETH_ALEN);
-+ memcpy(wsm_key->tkipPairwiseKey.tkipKeyData, &key->key[0], 16);
-+ memcpy(wsm_key->tkipPairwiseKey.txMicKey, &key->key[16], 8);
-+ memcpy(wsm_key->tkipPairwiseKey.rxMicKey, &key->key[24], 8);
-+ } else {
-+ size_t mic_offset = (priv->mode == NL80211_IFTYPE_AP) ? 16 : 24;
-+ wsm_key->type = WSM_KEY_TYPE_TKIP_GROUP;
-+ memcpy(wsm_key->tkipGroupKey.tkipKeyData,&key->key[0], 16);
-+ memcpy(wsm_key->tkipGroupKey.rxMicKey, &key->key[mic_offset], 8);
-+
-+ /* TODO: Where can I find TKIP SEQ? */
-+ memset(wsm_key->tkipGroupKey.rxSeqCounter, 0, 8);
-+ wsm_key->tkipGroupKey.keyId = key->keyidx;
-+ }
-+ break;
-+ case WLAN_CIPHER_SUITE_CCMP:
-+ if (pairwise) {
-+ wsm_key->type = WSM_KEY_TYPE_AES_PAIRWISE;
-+ memcpy(wsm_key->aesPairwiseKey.peerAddress, peer_addr, ETH_ALEN);
-+ memcpy(wsm_key->aesPairwiseKey.aesKeyData, &key->key[0], 16);
-+ wiphy_debug(dev->wiphy, "CCMP_PAIRWISE keylen=%d!\n",
-+ key->keylen);
-+ } else {
-+ wsm_key->type = WSM_KEY_TYPE_AES_GROUP;
-+ memcpy(wsm_key->aesGroupKey.aesKeyData, &key->key[0], 16);
-+ /* TODO: Where can I find AES SEQ? */
-+ memset(wsm_key->aesGroupKey.rxSeqCounter, 0, 8);
-+ wsm_key->aesGroupKey.keyId = key->keyidx;
-+ }
-+ break;
-+#ifdef CONFIG_XRADIO_WAPI_SUPPORT
-+ case WLAN_CIPHER_SUITE_SMS4:
-+ if (pairwise) {
-+ wsm_key->type = WSM_KEY_TYPE_WAPI_PAIRWISE;
-+ memcpy(wsm_key->wapiPairwiseKey.peerAddress, peer_addr, ETH_ALEN);
-+ memcpy(wsm_key->wapiPairwiseKey.wapiKeyData, &key->key[0], 16);
-+ memcpy(wsm_key->wapiPairwiseKey.micKeyData, &key->key[16], 16);
-+ wsm_key->wapiPairwiseKey.keyId = key->keyidx;
-+ sta_printk(XRADIO_DBG_NIY,"%s: WAPI_PAIRWISE keylen=%d!\n",
-+ __func__, key->keylen);
-+ } else {
-+ wsm_key->type = WSM_KEY_TYPE_WAPI_GROUP;
-+ memcpy(wsm_key->wapiGroupKey.wapiKeyData, &key->key[0], 16);
-+ memcpy(wsm_key->wapiGroupKey.micKeyData, &key->key[16], 16);
-+ wsm_key->wapiGroupKey.keyId = key->keyidx;
-+ sta_printk(XRADIO_DBG_NIY,"%s: WAPI_GROUP keylen=%d!\n",
-+ __func__, key->keylen);
-+ }
-+ break;
-+#endif /* CONFIG_XRADIO_WAPI_SUPPORT */
-+ default:
-+ wiphy_err(dev->wiphy, "key->cipher unknown(%d)!\n", key->cipher);
-+ xradio_free_key(hw_priv, idx);
-+ ret = -EOPNOTSUPP;
-+ goto finally;
-+ }
-+ ret = WARN_ON(wsm_add_key(hw_priv, wsm_key, priv->if_id));
-+ if (!ret)
-+ key->hw_key_idx = idx;
-+ else
-+ xradio_free_key(hw_priv, idx);
-+
-+ if (!ret && (pairwise || wsm_key->type == WSM_KEY_TYPE_WEP_DEFAULT) &&
-+ (priv->filter4.enable & 0x2))
-+ xradio_set_arpreply(dev, vif);
-+ } else if (cmd == DISABLE_KEY) {
-+ struct wsm_remove_key wsm_key = {
-+ .entryIndex = key->hw_key_idx,
-+ };
-+
-+ if (wsm_key.entryIndex > WSM_KEY_MAX_IDX) {
-+ ret = -EINVAL;
-+ goto finally;
-+ }
-+
-+ xradio_free_key(hw_priv, wsm_key.entryIndex);
-+ ret = wsm_remove_key(hw_priv, &wsm_key, priv->if_id);
-+ } else {
-+ wiphy_err(dev->wiphy, "Unsupported command\n");
-+ }
-+
-+finally:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return ret;
-+#endif // XRADIO_DISABLE_HW_CRYPTO
-+}
-diff --git a/drivers/net/wireless/xradio/keys.h b/drivers/net/wireless/xradio/keys.h
-new file mode 100644
-index 0000000..23c5880
---- /dev/null
-+++ b/drivers/net/wireless/xradio/keys.h
-@@ -0,0 +1,12 @@
-+#ifndef __KEYS_H_
-+#define __KEYS_H_INCLUDED
-+
-+int xradio_alloc_key(struct xradio_common *hw_priv);
-+void xradio_free_key(struct xradio_common *hw_priv, int idx);
-+void xradio_free_keys(struct xradio_common *hw_priv);
-+int xradio_upload_keys(struct xradio_vif *priv);
-+int xradio_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
-+ struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-+ struct ieee80211_key_conf *key);
-+
-+#endif
-\ No newline at end of file
-diff --git a/drivers/net/wireless/xradio/main.c b/drivers/net/wireless/xradio/main.c
-new file mode 100644
-index 0000000..346710c
---- /dev/null
-+++ b/drivers/net/wireless/xradio/main.c
-@@ -0,0 +1,609 @@
-+/*
-+ * Main code of XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "fwio.h"
-+#include "hwio.h"
-+#include "bh.h"
-+#include "sta.h"
-+#include "ap.h"
-+#include "keys.h"
-+#include "scan.h"
-+#include "pm.h"
-+#include "sdio.h"
-+
-+/* TODO: use rates and channels from the device */
-+#define RATETAB_ENT(_rate, _rateid, _flags) \
-+ { \
-+ .bitrate = (_rate), \
-+ .hw_value = (_rateid), \
-+ .flags = (_flags), \
-+ }
-+
-+static struct ieee80211_rate xradio_rates[] = {
-+ RATETAB_ENT(10, 0, 0),
-+ RATETAB_ENT(20, 1, 0),
-+ RATETAB_ENT(55, 2, 0),
-+ RATETAB_ENT(110, 3, 0),
-+ RATETAB_ENT(60, 6, 0),
-+ RATETAB_ENT(90, 7, 0),
-+ RATETAB_ENT(120, 8, 0),
-+ RATETAB_ENT(180, 9, 0),
-+ RATETAB_ENT(240, 10, 0),
-+ RATETAB_ENT(360, 11, 0),
-+ RATETAB_ENT(480, 12, 0),
-+ RATETAB_ENT(540, 13, 0),
-+};
-+
-+static struct ieee80211_rate xradio_mcs_rates[] = {
-+ RATETAB_ENT(65, 14, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(130, 15, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(195, 16, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(260, 17, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(390, 18, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(520, 19, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(585, 20, IEEE80211_TX_RC_MCS),
-+ RATETAB_ENT(650, 21, IEEE80211_TX_RC_MCS),
-+};
-+
-+#define xradio_g_rates (xradio_rates + 0)
-+#define xradio_a_rates (xradio_rates + 4)
-+#define xradio_n_rates (xradio_mcs_rates)
-+
-+#define xradio_g_rates_size (ARRAY_SIZE(xradio_rates))
-+#define xradio_a_rates_size (ARRAY_SIZE(xradio_rates) - 4)
-+#define xradio_n_rates_size (ARRAY_SIZE(xradio_mcs_rates))
-+
-+#define CHAN2G(_channel, _freq, _flags) { \
-+ .band = NL80211_BAND_2GHZ, \
-+ .center_freq = (_freq), \
-+ .hw_value = (_channel), \
-+ .flags = (_flags), \
-+ .max_antenna_gain = 0, \
-+ .max_power = 30, \
-+}
-+
-+#define CHAN5G(_channel, _flags) { \
-+ .band = NL80211_BAND_5GHZ, \
-+ .center_freq = 5000 + (5 * (_channel)), \
-+ .hw_value = (_channel), \
-+ .flags = (_flags), \
-+ .max_antenna_gain = 0, \
-+ .max_power = 30, \
-+}
-+
-+static struct ieee80211_channel xradio_2ghz_chantable[] = {
-+ CHAN2G(1, 2412, 0),
-+ CHAN2G(2, 2417, 0),
-+ CHAN2G(3, 2422, 0),
-+ CHAN2G(4, 2427, 0),
-+ CHAN2G(5, 2432, 0),
-+ CHAN2G(6, 2437, 0),
-+ CHAN2G(7, 2442, 0),
-+ CHAN2G(8, 2447, 0),
-+ CHAN2G(9, 2452, 0),
-+ CHAN2G(10, 2457, 0),
-+ CHAN2G(11, 2462, 0),
-+ CHAN2G(12, 2467, 0),
-+ CHAN2G(13, 2472, 0),
-+ CHAN2G(14, 2484, 0),
-+};
-+
-+static struct ieee80211_supported_band xradio_band_2ghz = {
-+ .channels = xradio_2ghz_chantable,
-+ .n_channels = ARRAY_SIZE(xradio_2ghz_chantable),
-+ .bitrates = xradio_g_rates,
-+ .n_bitrates = xradio_g_rates_size,
-+ .ht_cap = {
-+ .cap = IEEE80211_HT_CAP_GRN_FLD |
-+ (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT),
-+ .ht_supported = 1,
-+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_32K,
-+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
-+ .mcs = {
-+ .rx_mask[0] = 0xFF,
-+ .rx_highest = __cpu_to_le16(0x41),
-+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
-+ },
-+ },
-+};
-+
-+static const unsigned long xradio_ttl[] = {
-+ 1 * HZ, /* VO */
-+ 2 * HZ, /* VI */
-+ 5 * HZ, /* BE */
-+ 10 * HZ /* BK */
-+};
-+
-+static const struct ieee80211_ops xradio_ops = {
-+ .start = xradio_start,
-+ .stop = xradio_stop,
-+ .add_interface = xradio_add_interface,
-+ .remove_interface = xradio_remove_interface,
-+ .change_interface = xradio_change_interface,
-+ .tx = xradio_tx,
-+ .hw_scan = xradio_hw_scan,
-+#ifdef ROAM_OFFLOAD
-+ .sched_scan_start = xradio_hw_sched_scan_start,
-+ .sched_scan_stop = xradio_hw_sched_scan_stop,
-+#endif /*ROAM_OFFLOAD*/
-+ .set_tim = xradio_set_tim,
-+ .sta_notify = xradio_sta_notify,
-+ .sta_add = xradio_sta_add,
-+ .sta_remove = xradio_sta_remove,
-+ .set_key = xradio_set_key,
-+ .set_rts_threshold = xradio_set_rts_threshold,
-+ .config = xradio_config,
-+ .bss_info_changed = xradio_bss_info_changed,
-+ .prepare_multicast = xradio_prepare_multicast,
-+ .configure_filter = xradio_configure_filter,
-+ .conf_tx = xradio_conf_tx,
-+ .get_stats = xradio_get_stats,
-+ .ampdu_action = xradio_ampdu_action,
-+ .flush = xradio_flush,
-+#ifdef CONFIG_PM
-+ .suspend = xradio_wow_suspend,
-+ .resume = xradio_wow_resume,
-+#endif /* CONFIG_PM */
-+ /* Intentionally not offloaded: */
-+ /*.channel_switch = xradio_channel_switch, */
-+ .remain_on_channel = xradio_remain_on_channel,
-+ .cancel_remain_on_channel = xradio_cancel_remain_on_channel,
-+};
-+
-+
-+/*************************************** functions ***************************************/
-+
-+static void xradio_set_ifce_comb(struct xradio_common *hw_priv,
-+ struct ieee80211_hw *hw)
-+{
-+ hw_priv->if_limits1[0].max = 1;
-+
-+ hw_priv->if_limits1[0].types = BIT(NL80211_IFTYPE_STATION);
-+ hw_priv->if_limits1[1].max = 1;
-+ hw_priv->if_limits1[1].types = BIT(NL80211_IFTYPE_AP);
-+
-+ hw_priv->if_limits2[0].max = 2;
-+ hw_priv->if_limits2[0].types = BIT(NL80211_IFTYPE_STATION);
-+
-+ hw_priv->if_limits3[0].max = 1;
-+
-+ hw_priv->if_limits3[0].types = BIT(NL80211_IFTYPE_STATION);
-+ hw_priv->if_limits3[1].max = 1;
-+ hw_priv->if_limits3[1].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
-+ BIT(NL80211_IFTYPE_P2P_GO);
-+
-+ /* TODO:COMBO: mac80211 doesn't yet support more than 1
-+ * different channel */
-+ hw_priv->if_combs[0].num_different_channels = 1;
-+ hw_priv->if_combs[0].max_interfaces = 2;
-+ hw_priv->if_combs[0].limits = hw_priv->if_limits1;
-+ hw_priv->if_combs[0].n_limits = 2;
-+
-+ hw_priv->if_combs[1].num_different_channels = 1;
-+
-+ hw_priv->if_combs[1].max_interfaces = 2;
-+ hw_priv->if_combs[1].limits = hw_priv->if_limits2;
-+ hw_priv->if_combs[1].n_limits = 1;
-+
-+ hw_priv->if_combs[2].num_different_channels = 1;
-+ hw_priv->if_combs[2].max_interfaces = 2;
-+ hw_priv->if_combs[2].limits = hw_priv->if_limits3;
-+ hw_priv->if_combs[2].n_limits = 2;
-+
-+ hw->wiphy->iface_combinations = &hw_priv->if_combs[0];
-+ hw->wiphy->n_iface_combinations = 3;
-+}
-+
-+struct ieee80211_hw *xradio_init_common(size_t hw_priv_data_len)
-+{
-+ int i;
-+ struct ieee80211_hw *hw;
-+ struct xradio_common *hw_priv;
-+ struct ieee80211_supported_band *sband;
-+ int band;
-+
-+ /* Alloc ieee_802.11 hw and xradio_common struct. */
-+ hw = ieee80211_alloc_hw(hw_priv_data_len, &xradio_ops);
-+ if (!hw)
-+ return NULL;
-+ hw_priv = hw->priv;
-+ memset(hw_priv, 0, sizeof(*hw_priv));
-+
-+ /* Initialize members of hw_priv. */
-+ hw_priv->hw = hw;
-+ hw_priv->if_id_slot = 0;
-+ hw_priv->roc_if_id = -1;
-+ atomic_set(&hw_priv->num_vifs, 0);
-+ /* initial rates and channels TODO: fetch from FW */
-+ hw_priv->rates = xradio_rates;
-+ hw_priv->mcs_rates = xradio_n_rates;
-+#ifdef ROAM_OFFLOAD
-+ hw_priv->auto_scanning = 0;
-+ hw_priv->frame_rcvd = 0;
-+ hw_priv->num_scanchannels = 0;
-+ hw_priv->num_2g_channels = 0;
-+ hw_priv->num_5g_channels = 0;
-+#endif /*ROAM_OFFLOAD*/
-+#ifdef AP_AGGREGATE_FW_FIX
-+ /* Enable block ACK for 4 TID (BE,VI,VI,VO). */
-+ hw_priv->ba_tid_mask = 0xB1; /*due to HW limitations*/
-+#else
-+ /* Enable block ACK for every TID but voice. */
-+ hw_priv->ba_tid_mask = 0x3F;
-+#endif
-+ hw_priv->noise = -94;
-+ /* hw_priv->beacon_req_id = cpu_to_le32(0); */
-+
-+ /* Initialize members of ieee80211_hw, it works in UMAC. */
-+ hw->sta_data_size = sizeof(struct xradio_sta_priv);
-+ hw->vif_data_size = sizeof(struct xradio_vif);
-+
-+ ieee80211_hw_set(hw, SIGNAL_DBM);
-+ ieee80211_hw_set(hw, SUPPORTS_PS);
-+ ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
-+ ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
-+ ieee80211_hw_set(hw, CONNECTION_MONITOR);
-+
-+/* hw->flags = IEEE80211_HW_SIGNAL_DBM |
-+ IEEE80211_HW_SUPPORTS_PS |
-+ IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
-+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
-+ IEEE80211_HW_CONNECTION_MONITOR;*/
-+ //IEEE80211_HW_SUPPORTS_CQM_RSSI |
-+ /* Aggregation is fully controlled by firmware.
-+ * Do not need any support from the mac80211 stack */
-+ /* IEEE80211_HW_AMPDU_AGGREGATION | */
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //IEEE80211_HW_SUPPORTS_P2P_PS |
-+ //IEEE80211_HW_SUPPORTS_CQM_BEACON_MISS |
-+ // IEEE80211_HW_SUPPORTS_CQM_TX_FAIL |
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ //IEEE80211_HW_BEACON_FILTER;
-+
-+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-+ BIT(NL80211_IFTYPE_ADHOC) |
-+ BIT(NL80211_IFTYPE_AP) |
-+ BIT(NL80211_IFTYPE_MESH_POINT) |
-+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
-+ BIT(NL80211_IFTYPE_P2P_GO);
-+
-+ /* Support only for limited wowlan functionalities */
-+ /* TODO by Icenowy: RESTORE THIS */
-+/* hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT;
-+ hw->wiphy->wowlan.n_patterns = 0;*/
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ /* fix the problem that driver can not set pro-resp template frame to fw */
-+ hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
-+
-+#if defined(CONFIG_XRADIO_DISABLE_BEACON_HINTS)
-+ hw->wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
-+#endif
-+ hw->wiphy->n_addresses = XRWL_MAX_VIFS;
-+ hw->wiphy->addresses = hw_priv->addresses;
-+ hw->wiphy->max_remain_on_channel_duration = 500;
-+ hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
-+ 8 /* TKIP IV */ +
-+ 12 /* TKIP ICV and MIC */;
-+ hw->wiphy->bands[NL80211_BAND_2GHZ] = &xradio_band_2ghz;
-+ hw->queues = AC_QUEUE_NUM;
-+ hw->max_rates = MAX_RATES_STAGE;
-+ hw->max_rate_tries = MAX_RATES_RETRY;
-+ /* Channel params have to be cleared before registering wiphy again */
-+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
-+ sband = hw->wiphy->bands[band];
-+ if (!sband)
-+ continue;
-+ for (i = 0; i < sband->n_channels; i++) {
-+ sband->channels[i].flags = 0;
-+ sband->channels[i].max_antenna_gain = 0;
-+ sband->channels[i].max_power = 30;
-+ }
-+ }
-+ /* hw_priv->channel init value is the local->oper_channel init value;when transplanting,take care */
-+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
-+ sband = hw->wiphy->bands[band];
-+ if (!sband)
-+ continue;
-+ if(!hw_priv->channel){
-+ hw_priv->channel = &sband->channels[2];
-+ }
-+ }
-+ hw->wiphy->max_scan_ssids = WSM_SCAN_MAX_NUM_OF_SSIDS;
-+ hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
-+ SET_IEEE80211_PERM_ADDR(hw, hw_priv->addresses[0].addr);
-+
-+ /* Initialize locks. */
-+ spin_lock_init(&hw_priv->vif_list_lock);
-+ mutex_init(&hw_priv->wsm_cmd_mux);
-+ mutex_init(&hw_priv->conf_mutex);
-+ mutex_init(&hw_priv->wsm_oper_lock);
-+ atomic_set(&hw_priv->tx_lock, 0);
-+ sema_init(&hw_priv->tx_lock_sem, 1);
-+
-+ hw_priv->workqueue = create_singlethread_workqueue(XRADIO_WORKQUEUE);
-+ sema_init(&hw_priv->scan.lock, 1);
-+ sema_init(&hw_priv->scan.status_lock,1);
-+ INIT_WORK(&hw_priv->scan.work, xradio_scan_work);
-+#ifdef ROAM_OFFLOAD
-+ INIT_WORK(&hw_priv->scan.swork, xradio_sched_scan_work);
-+#endif /*ROAM_OFFLOAD*/
-+ INIT_DELAYED_WORK(&hw_priv->scan.probe_work, xradio_probe_work);
-+ INIT_DELAYED_WORK(&hw_priv->scan.timeout, xradio_scan_timeout);
-+ INIT_DELAYED_WORK(&hw_priv->rem_chan_timeout, xradio_rem_chan_timeout);
-+ INIT_WORK(&hw_priv->tx_policy_upload_work, tx_policy_upload_work);
-+ atomic_set(&hw_priv->upload_count, 0);
-+ memset(&hw_priv->connet_time, 0, sizeof(hw_priv->connet_time));
-+
-+ spin_lock_init(&hw_priv->event_queue_lock);
-+ INIT_LIST_HEAD(&hw_priv->event_queue);
-+ INIT_WORK(&hw_priv->event_handler, xradio_event_handler);
-+ INIT_WORK(&hw_priv->ba_work, xradio_ba_work);
-+ spin_lock_init(&hw_priv->ba_lock);
-+ timer_setup(&hw_priv->ba_timer, xradio_ba_timer, 0);
-+
-+ if (unlikely(xradio_queue_stats_init(&hw_priv->tx_queue_stats,
-+ WLAN_LINK_ID_MAX,xradio_skb_dtor, hw_priv))) {
-+ ieee80211_free_hw(hw);
-+ return NULL;
-+ }
-+ for (i = 0; i < AC_QUEUE_NUM; ++i) {
-+ if (unlikely(xradio_queue_init(&hw_priv->tx_queue[i],
-+ &hw_priv->tx_queue_stats, i, XRWL_MAX_QUEUE_SZ, xradio_ttl[i]))) {
-+ for (; i > 0; i--)
-+ xradio_queue_deinit(&hw_priv->tx_queue[i - 1]);
-+ xradio_queue_stats_deinit(&hw_priv->tx_queue_stats);
-+ ieee80211_free_hw(hw);
-+ return NULL;
-+ }
-+ }
-+
-+ init_waitqueue_head(&hw_priv->channel_switch_done);
-+ init_waitqueue_head(&hw_priv->wsm_cmd_wq);
-+ init_waitqueue_head(&hw_priv->wsm_startup_done);
-+ init_waitqueue_head(&hw_priv->offchannel_wq);
-+ hw_priv->wsm_caps.firmwareReady = 0;
-+ hw_priv->driver_ready = 0;
-+ hw_priv->offchannel_done = 0;
-+ wsm_buf_init(&hw_priv->wsm_cmd_buf);
-+ spin_lock_init(&hw_priv->wsm_cmd.lock);
-+ tx_policy_init(hw_priv);
-+ xradio_init_resv_skb(hw_priv);
-+ /* add for setting short_frame_max_tx_count(mean wdev->retry_short) to drv,init the max_rate_tries */
-+ spin_lock_bh(&hw_priv->tx_policy_cache.lock);
-+ hw_priv->long_frame_max_tx_count = hw->conf.long_frame_max_tx_count;
-+ hw_priv->short_frame_max_tx_count =
-+ (hw->conf.short_frame_max_tx_count< 0x0F) ?
-+ hw->conf.short_frame_max_tx_count : 0x0F;
-+ hw_priv->hw->max_rate_tries = hw->conf.short_frame_max_tx_count;
-+ spin_unlock_bh(&hw_priv->tx_policy_cache.lock);
-+
-+ for (i = 0; i < XRWL_MAX_VIFS; i++)
-+ hw_priv->hw_bufs_used_vif[i] = 0;
-+
-+#ifdef MCAST_FWDING
-+ for (i = 0; i < WSM_MAX_BUF; i++)
-+ wsm_init_release_buffer_request(hw_priv, i);
-+ hw_priv->buf_released = 0;
-+#endif
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+
-+ hw_priv->query_packetID = 0;
-+ atomic_set(&hw_priv->query_cnt, 0);
-+ INIT_WORK(&hw_priv->query_work, wsm_query_work);
-+
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+ atomic_set(&hw_priv->suspend_state, XRADIO_RESUME);
-+#endif
-+
-+ xradio_set_ifce_comb(hw_priv, hw_priv->hw);
-+
-+ return hw;
-+}
-+
-+void xradio_free_common(struct ieee80211_hw *dev)
-+{
-+ int i;
-+ struct xradio_common *hw_priv = dev->priv;
-+
-+ cancel_work_sync(&hw_priv->query_work);
-+ del_timer_sync(&hw_priv->ba_timer);
-+ mutex_destroy(&hw_priv->wsm_oper_lock);
-+ mutex_destroy(&hw_priv->conf_mutex);
-+ mutex_destroy(&hw_priv->wsm_cmd_mux);
-+ wsm_buf_deinit(&hw_priv->wsm_cmd_buf);
-+ flush_workqueue(hw_priv->workqueue);
-+ destroy_workqueue(hw_priv->workqueue);
-+ hw_priv->workqueue = NULL;
-+
-+ xradio_deinit_resv_skb(hw_priv);
-+ if (hw_priv->skb_cache) {
-+ dev_kfree_skb(hw_priv->skb_cache);
-+ hw_priv->skb_cache = NULL;
-+ }
-+
-+ for (i = 0; i < 4; ++i)
-+ xradio_queue_deinit(&hw_priv->tx_queue[i]);
-+ xradio_queue_stats_deinit(&hw_priv->tx_queue_stats);
-+
-+ for (i = 0; i < XRWL_MAX_VIFS; i++) {
-+ kfree(hw_priv->vif_list[i]);
-+ hw_priv->vif_list[i] = NULL;
-+ }
-+
-+//fixed memory leakage by yangfh
-+#ifdef MCAST_FWDING
-+ wsm_deinit_release_buffer(hw_priv);
-+#endif
-+ /* unsigned int i; */
-+ ieee80211_free_hw(dev);
-+}
-+
-+int xradio_register_common(struct ieee80211_hw *dev)
-+{
-+ int err = 0;
-+ struct xradio_common *hw_priv = dev->priv;
-+
-+ SET_IEEE80211_DEV(dev, hw_priv->pdev);
-+ err = ieee80211_register_hw(dev);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "Cannot register device (%d).\n", err);
-+ return err;
-+ }
-+ dev_dbg(hw_priv->pdev, "is registered as '%s'\n",
-+ wiphy_name(dev->wiphy));
-+
-+ hw_priv->driver_ready = 1;
-+ wake_up(&hw_priv->wsm_startup_done);
-+ return 0;
-+}
-+
-+void xradio_unregister_common(struct ieee80211_hw *dev)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+
-+ if (wiphy_dev(dev->wiphy)) {
-+ ieee80211_unregister_hw(dev);
-+ SET_IEEE80211_DEV(dev, NULL);
-+ }
-+ hw_priv->driver_ready = 0;
-+}
-+
-+int xradio_core_init(struct sdio_func* func)
-+{
-+ int err = -ENOMEM;
-+ u16 ctrl_reg;
-+ int if_id;
-+ struct ieee80211_hw *dev;
-+ struct xradio_common *hw_priv;
-+ unsigned char randomaddr[ETH_ALEN];
-+ const unsigned char *addr = NULL;
-+
-+ //init xradio_common
-+ dev = xradio_init_common(sizeof(struct xradio_common));
-+ if (!dev) {
-+ dev_dbg(&func->dev, "xradio_init_common failed\n");
-+ return err;
-+ }
-+ hw_priv = dev->priv;
-+ hw_priv->pdev = &func->dev;
-+ hw_priv->sdio_func = func;
-+ sdio_set_drvdata(func, hw_priv);
-+
-+ // fill in mac addresses
-+ if (hw_priv->pdev->of_node) {
-+ addr = of_get_mac_address(hw_priv->pdev->of_node);
-+ }
-+ if (!addr) {
-+ dev_warn(hw_priv->pdev, "no mac address provided, using random\n");
-+ eth_random_addr(randomaddr);
-+ addr = randomaddr;
-+ }
-+ memcpy(hw_priv->addresses[0].addr, addr, ETH_ALEN);
-+ memcpy(hw_priv->addresses[1].addr, addr, ETH_ALEN);
-+ hw_priv->addresses[1].addr[5] += 0x01;
-+
-+ /*init pm and wakelock. */
-+#ifdef CONFIG_PM
-+ err = xradio_pm_init(&hw_priv->pm_state, hw_priv);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "xradio_pm_init failed(%d).\n", err);
-+ goto err2;
-+ }
-+#endif
-+ /* Register bh thread*/
-+ err = xradio_register_bh(hw_priv);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "xradio_register_bh failed(%d).\n", err);
-+ goto err3;
-+ }
-+
-+ /* Load firmware and register Interrupt Handler */
-+ err = xradio_load_firmware(hw_priv);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "xradio_load_firmware failed(%d).\n", err);
-+ goto err4;
-+ }
-+
-+ /* Set sdio blocksize. */
-+ sdio_lock(hw_priv);
-+ WARN_ON(sdio_set_blk_size(hw_priv,
-+ SDIO_BLOCK_SIZE));
-+ sdio_unlock(hw_priv);
-+
-+ if (wait_event_interruptible_timeout(hw_priv->wsm_startup_done,
-+ hw_priv->wsm_caps.firmwareReady, 3*HZ) <= 0) {
-+
-+ /* TODO: Needs to find how to reset device */
-+ /* in QUEUE mode properly. */
-+ dev_dbg(hw_priv->pdev, "Firmware Startup Timeout!\n");
-+ err = -ETIMEDOUT;
-+ goto err5;
-+ }
-+ dev_dbg(hw_priv->pdev, "Firmware Startup Done.\n");
-+
-+ /* Keep device wake up. */
-+ WARN_ON(xradio_reg_write_16(hw_priv, HIF_CONTROL_REG_ID, HIF_CTRL_WUP_BIT));
-+ if (xradio_reg_read_16(hw_priv,HIF_CONTROL_REG_ID, &ctrl_reg))
-+ WARN_ON(xradio_reg_read_16(hw_priv,HIF_CONTROL_REG_ID, &ctrl_reg));
-+ WARN_ON(!(ctrl_reg & HIF_CTRL_RDY_BIT));
-+
-+ /* Set device mode parameter. */
-+ for (if_id = 0; if_id < xrwl_get_nr_hw_ifaces(hw_priv); if_id++) {
-+ /* Set low-power mode. */
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, if_id));
-+ /* Enable multi-TX confirmation */
-+ WARN_ON(wsm_use_multi_tx_conf(hw_priv, true, if_id));
-+ }
-+
-+ /* Register wireless net device. */
-+ err = xradio_register_common(dev);
-+ if (err) {
-+ dev_dbg(hw_priv->pdev, "xradio_register_common failed(%d)!\n", err);
-+ goto err5;
-+ }
-+
-+ return err;
-+
-+err5:
-+ xradio_dev_deinit(hw_priv);
-+err4:
-+ xradio_unregister_bh(hw_priv);
-+err3:
-+ xradio_pm_deinit(&hw_priv->pm_state);
-+err2:
-+/* err1: MRK: unused label*/
-+ xradio_free_common(dev);
-+ return err;
-+}
-+
-+void xradio_core_deinit(struct sdio_func* func)
-+{
-+ struct xradio_common* hw_priv = sdio_get_drvdata(func);
-+ if (hw_priv) {
-+ xradio_unregister_common(hw_priv->hw);
-+ xradio_dev_deinit(hw_priv);
-+ xradio_unregister_bh(hw_priv);
-+ xradio_pm_deinit(&hw_priv->pm_state);
-+ xradio_free_common(hw_priv->hw);
-+ }
-+ return;
-+}
-diff --git a/drivers/net/wireless/xradio/main.h b/drivers/net/wireless/xradio/main.h
-new file mode 100644
-index 0000000..2238d75
---- /dev/null
-+++ b/drivers/net/wireless/xradio/main.h
-@@ -0,0 +1,7 @@
-+#ifndef __XRADIO_MAIN_H
-+#define __XRADIO_MAIN_H
-+
-+int xradio_core_init(struct sdio_func* func);
-+void xradio_core_deinit(struct sdio_func* func);
-+
-+#endif
-\ No newline at end of file
-diff --git a/drivers/net/wireless/xradio/module.c b/drivers/net/wireless/xradio/module.c
-new file mode 100644
-index 0000000..2a41c75
---- /dev/null
-+++ b/drivers/net/wireless/xradio/module.c
-@@ -0,0 +1,27 @@
-+#include
-+
-+#include "xradio.h"
-+#include "debug.h"
-+#include "sdio.h"
-+
-+MODULE_AUTHOR("XRadioTech");
-+MODULE_DESCRIPTION("XRadioTech WLAN driver core");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("xradio_core");
-+
-+/* Init Module function -> Called by insmod */
-+static int __init xradio_core_entry(void)
-+{
-+ int ret = 0;
-+ ret = xradio_sdio_register();
-+ return ret;
-+}
-+
-+/* Called at Driver Unloading */
-+static void __exit xradio_core_exit(void)
-+{
-+ xradio_sdio_unregister();
-+}
-+
-+module_init(xradio_core_entry);
-+module_exit(xradio_core_exit);
-diff --git a/drivers/net/wireless/xradio/p2p.c b/drivers/net/wireless/xradio/p2p.c
-new file mode 100644
-index 0000000..f32fb43
---- /dev/null
-+++ b/drivers/net/wireless/xradio/p2p.c
-@@ -0,0 +1,62 @@
-+#include "xradio.h"
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+///w, TES_P2P_0002 WorkAround:
-+///w, P2P GO Neg Process and P2P FIND may be collision.
-+///w, When P2P Device is waiting for GO NEG CFM in 30ms,
-+///w, P2P FIND may end with p2p listen, and then goes to p2p search.
-+///w, Then xradio scan will occupy phy on other channel in 3+ seconds.
-+///w, P2P Device will not be able to receive the GO NEG CFM.
-+///w, We extend the roc period to remaind phy to receive GO NEG CFM as WorkAround.
-+
-+s32 TES_P2P_0002_roc_dur;
-+s32 TES_P2P_0002_roc_sec;
-+s32 TES_P2P_0002_roc_usec;
-+u32 TES_P2P_0002_packet_id;
-+u32 TES_P2P_0002_state = TES_P2P_0002_STATE_IDLE;
-+
-+void xradio_frame_monitor(struct xradio_common *hw_priv, struct sk_buff *skb, bool tx) {
-+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-+
-+ u8 *action = (u8*)&mgmt->u.action.category;
-+ u8 *category_code = &(action[0]);
-+ u8 *action_code = &(action[1]);
-+ u8 *oui = &(action[2]);
-+ u8 *subtype = &(action[5]);
-+ u8 *oui_subtype = &(action[6]);
-+
-+
-+ if(ieee80211_is_action(frame->frame_control)) {
-+ if( *category_code == WLAN_CATEGORY_PUBLIC) {
-+ if (*action_code == 0x09) {
-+ if((oui[0] == 0x50) && (oui[1] == 0x6F) &&
-+ (oui[2] == 0x9A) && (*subtype == 0x09)) {
-+ if ( *oui_subtype == 0x01 ) { ///w, GO Negotiation Response
-+ if((TES_P2P_0002_state == TES_P2P_0002_STATE_IDLE) &&
-+ (tx == true)) { ///w, p2p atturbute:status,id=0
-+ u8 *go_neg_resp_res = &(action[17]);
-+ if (*go_neg_resp_res == 0x0) {
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_SEND_RESP;
-+ txrx_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_SEND_RESP]\n");
-+ }
-+ }
-+ } else if ( *oui_subtype == 0x02 ) { ///w, GO Negotiation Confirmation
-+ if( tx == false ) {
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_IDLE;
-+ txrx_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_IDLE]"
-+ "[GO Negotiation Confirmation]\n");
-+ }
-+ } else if ( *oui_subtype == 0x08 ) { ///w, Provision Discovery Response
-+ if(tx == false) {
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_IDLE;
-+ txrx_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_IDLE]"
-+ "[Provision Discovery Response]\n");
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+}
-+#endif
-\ No newline at end of file
-diff --git a/drivers/net/wireless/xradio/p2p.h b/drivers/net/wireless/xradio/p2p.h
-new file mode 100644
-index 0000000..d86686b
---- /dev/null
-+++ b/drivers/net/wireless/xradio/p2p.h
-@@ -0,0 +1,6 @@
-+#ifndef XRADIO_P2P_H
-+#define XRADIO_P2P_H
-+
-+void xradio_frame_monitor(struct xradio_common *hw_priv, struct sk_buff *skb, bool tx);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/pm.c b/drivers/net/wireless/xradio/pm.c
-new file mode 100644
-index 0000000..488c26c
---- /dev/null
-+++ b/drivers/net/wireless/xradio/pm.c
-@@ -0,0 +1,800 @@
-+/*
-+ * PM implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include "xradio.h"
-+#include "pm.h"
-+#include "sta.h"
-+#include "bh.h"
-+#include "sdio.h"
-+
-+#define XRADIO_BEACON_SKIPPING_MULTIPLIER 3
-+
-+struct xradio_udp_port_filter {
-+ struct wsm_udp_port_filter_hdr hdr;
-+ struct wsm_udp_port_filter dhcp;
-+ struct wsm_udp_port_filter upnp;
-+} __packed;
-+
-+struct xradio_ether_type_filter {
-+ struct wsm_ether_type_filter_hdr hdr;
-+ struct wsm_ether_type_filter ip;
-+ struct wsm_ether_type_filter pae;
-+ struct wsm_ether_type_filter wapi;
-+} __packed;
-+
-+static struct xradio_udp_port_filter xradio_udp_port_filter_on = {
-+ .hdr.nrFilters = 2,
-+ .dhcp = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_OUT,
-+ .portType = WSM_FILTER_PORT_TYPE_DST,
-+ .udpPort = __cpu_to_le16(67),
-+ },
-+ .upnp = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_OUT,
-+ .portType = WSM_FILTER_PORT_TYPE_DST,
-+ .udpPort = __cpu_to_le16(1900),
-+ },
-+ /* Please add other known ports to be filtered out here and
-+ * update nrFilters field in the header.
-+ * Up to 4 filters are allowed. */
-+};
-+
-+static struct wsm_udp_port_filter_hdr xradio_udp_port_filter_off = {
-+ .nrFilters = 0,
-+};
-+
-+#ifndef ETH_P_WAPI
-+#define ETH_P_WAPI 0x88B4
-+#endif
-+
-+#ifdef TES_P2P_000B_DISABLE_EAPOL_FILTER
-+/* TES_P2P_000B WorkAround:
-+ * when the link keep 10min more or less(i am not sure),
-+ * wpa_s session maybe expired, and want to update group key.
-+ * it will use eapol frame(802.1x,0x888E).
-+ * if driver suspend, and discard eapol frame, then session end.
-+ * i don't know why original code discards eapol frame in suspend.
-+ * but now make this filter disable as WorkAround. wzw */
-+static struct xradio_ether_type_filter xradio_ether_type_filter_on = {
-+ .hdr.nrFilters = 1,
-+/* .ip = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_IP),
-+ },*/
-+/* .pae = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_PAE),
-+ },*/
-+ .wapi = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_WAPI),
-+ },
-+ /* Please add other known ether types to be filtered out here and
-+ * update nrFilters field in the header.
-+ * Up to 4 filters are allowed. */
-+};
-+#else
-+static struct xradio_ether_type_filter xradio_ether_type_filter_on = {
-+ .hdr.nrFilters = 2,
-+/* .ip = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_IP),
-+ },*/
-+ .pae = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_PAE),
-+ },
-+ .wapi = {
-+ .filterAction = WSM_FILTER_ACTION_FILTER_IN,
-+ .etherType = __cpu_to_le16(ETH_P_WAPI),
-+ },
-+ /* Please add other known ether types to be filtered out here and
-+ * update nrFilters field in the header.
-+ * Up to 4 filters are allowed. */
-+};
-+#endif
-+
-+static struct wsm_ether_type_filter_hdr xradio_ether_type_filter_off = {
-+ .nrFilters = 0,
-+};
-+
-+static int xradio_suspend_late(struct device *dev);
-+static void xradio_pm_release(struct device *dev);
-+static int xradio_pm_probe(struct platform_device *pdev);
-+static int __xradio_wow_suspend(struct xradio_vif *priv,
-+ struct cfg80211_wowlan *wowlan);
-+static int __xradio_wow_resume(struct xradio_vif *priv);
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+static int xradio_poweroff_suspend(struct xradio_common *hw_priv);
-+static int xradio_poweroff_resume(struct xradio_common *hw_priv);
-+#endif
-+
-+
-+/* private */
-+struct xradio_suspend_state {
-+ unsigned long bss_loss_tmo;
-+ unsigned long connection_loss_tmo;
-+ unsigned long join_tmo;
-+ unsigned long direct_probe;
-+ unsigned long link_id_gc;
-+ bool beacon_skipping;
-+};
-+
-+static const struct dev_pm_ops xradio_pm_ops = {
-+ .suspend_noirq = xradio_suspend_late,
-+};
-+
-+static struct platform_driver xradio_power_driver = {
-+ .probe = xradio_pm_probe,
-+ .driver = {
-+ .name = XRADIO_PM_DEVICE,
-+ .pm = &xradio_pm_ops,
-+ },
-+};
-+
-+static int xradio_pm_init_common(struct xradio_pm_state *pm,
-+ struct xradio_common *hw_priv)
-+{
-+ int ret;
-+ pm_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+
-+ spin_lock_init(&pm->lock);
-+ /* Register pm driver. */
-+ ret = platform_driver_register(&xradio_power_driver);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_ERROR, "%s:platform_driver_register failed(%d)!\n",
-+ __FUNCTION__, ret);
-+ return ret;
-+ }
-+
-+ /* Add pm device. */
-+ pm->pm_dev = platform_device_alloc(XRADIO_PM_DEVICE, 0);
-+ if (!pm->pm_dev) {
-+ pm_printk(XRADIO_DBG_ERROR, "%s:platform_device_alloc failed!\n",
-+ __FUNCTION__);
-+ platform_driver_unregister(&xradio_power_driver);
-+ return -ENOMEM;
-+ }
-+ pm->pm_dev->dev.platform_data = hw_priv;
-+ ret = platform_device_add(pm->pm_dev);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_ERROR, "%s:platform_device_add failed(%d)!\n",
-+ __FUNCTION__, ret);
-+ platform_driver_unregister(&xradio_power_driver);
-+ kfree(pm->pm_dev);
-+ pm->pm_dev = NULL;
-+ }
-+
-+ return ret;
-+}
-+
-+static void xradio_pm_deinit_common(struct xradio_pm_state *pm)
-+{
-+ pm_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+ platform_driver_unregister(&xradio_power_driver);
-+ if (pm->pm_dev) {
-+ pm->pm_dev->dev.platform_data = NULL;
-+ platform_device_unregister(pm->pm_dev); /* kfree is already do */
-+ pm->pm_dev = NULL;
-+ }
-+}
-+
-+#ifdef CONFIG_WAKELOCK
-+
-+int xradio_pm_init(struct xradio_pm_state *pm,
-+ struct xradio_common *hw_priv)
-+{
-+ int ret = 0;
-+ pm_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+
-+ ret = xradio_pm_init_common(pm, hw_priv);
-+ if (!ret)
-+ wake_lock_init(&pm->wakelock, WAKE_LOCK_SUSPEND, XRADIO_WAKE_LOCK);
-+ else
-+ pm_printk(XRADIO_DBG_ERROR,"xradio_pm_init_common failed!\n");
-+ return ret;
-+}
-+
-+void xradio_pm_deinit(struct xradio_pm_state *pm)
-+{
-+ pm_printk(XRADIO_DBG_TRC,"%s\n", __FUNCTION__);
-+ if (wake_lock_active(&pm->wakelock))
-+ wake_unlock(&pm->wakelock);
-+ wake_lock_destroy(&pm->wakelock);
-+ xradio_pm_deinit_common(pm);
-+}
-+
-+void xradio_pm_stay_awake(struct xradio_pm_state *pm,
-+ unsigned long tmo)
-+{
-+ long cur_tmo;
-+ pm_printk(XRADIO_DBG_MSG,"%s\n", __FUNCTION__);
-+
-+ spin_lock_bh(&pm->lock);
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
-+ cur_tmo = pm->wakelock.ws.timer.expires - jiffies;
-+#else
-+ cur_tmo = pm->wakelock.expires - jiffies;
-+#endif
-+ if (!wake_lock_active(&pm->wakelock) || cur_tmo < (long)tmo)
-+ wake_lock_timeout(&pm->wakelock, tmo);
-+ spin_unlock_bh(&pm->lock);
-+}
-+void xradio_pm_lock_awake(struct xradio_pm_state *pm)
-+{
-+
-+ spin_lock_bh(&pm->lock);
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
-+ pm->expires_save = pm->wakelock.ws.timer.expires;
-+#else
-+ pm->expires_save = pm->wakelock.expires;
-+#endif
-+ wake_lock_timeout(&pm->wakelock, LONG_MAX);
-+ spin_unlock_bh(&pm->lock);
-+}
-+void xradio_pm_unlock_awake(struct xradio_pm_state *pm)
-+{
-+
-+ spin_lock_bh(&pm->lock);
-+ pm->expires_save -= jiffies;
-+ if (pm->expires_save)
-+ wake_lock_timeout(&pm->wakelock, pm->expires_save);
-+ else
-+ wake_lock_timeout(&pm->wakelock, 1);
-+ spin_unlock_bh(&pm->lock);
-+}
-+
-+#else /* CONFIG_WAKELOCK */
-+
-+static void xradio_pm_stay_awake_tmo(struct timer_list *t)
-+{
-+ struct xradio_pm_state *pm = from_timer(pm, t, stay_awake);
-+ (void)pm;
-+}
-+
-+int xradio_pm_init(struct xradio_pm_state *pm,
-+ struct xradio_common *hw_priv)
-+{
-+ int ret = 0;
-+ pm_printk(XRADIO_DBG_MSG,"%s\n", __FUNCTION__);
-+
-+ ret = xradio_pm_init_common(pm, hw_priv);
-+ if (!ret) {
-+ timer_setup(&pm->stay_awake, xradio_pm_stay_awake_tmo, 0);
-+ } else
-+ pm_printk(XRADIO_DBG_ERROR,"xradio_pm_init_common failed!\n");
-+ return ret;
-+}
-+
-+void xradio_pm_deinit(struct xradio_pm_state *pm)
-+{
-+ del_timer_sync(&pm->stay_awake);
-+ xradio_pm_deinit_common(pm);
-+}
-+
-+void xradio_pm_stay_awake(struct xradio_pm_state *pm,
-+ unsigned long tmo)
-+{
-+ long cur_tmo;
-+
-+ spin_lock_bh(&pm->lock);
-+ cur_tmo = pm->stay_awake.expires - jiffies;
-+ if (!timer_pending(&pm->stay_awake) || cur_tmo < (long)tmo)
-+ mod_timer(&pm->stay_awake, jiffies + tmo);
-+ spin_unlock_bh(&pm->lock);
-+}
-+void xradio_pm_lock_awake(struct xradio_pm_state *pm)
-+{
-+
-+ spin_lock_bh(&pm->lock);
-+ pm->expires_save = pm->stay_awake.expires;
-+ mod_timer(&pm->stay_awake, jiffies + LONG_MAX);
-+ spin_unlock_bh(&pm->lock);
-+}
-+void xradio_pm_unlock_awake(struct xradio_pm_state *pm)
-+{
-+
-+ spin_lock_bh(&pm->lock);
-+ if (time_before(jiffies, pm->expires_save))
-+ mod_timer(&pm->stay_awake, pm->expires_save);
-+ else
-+ mod_timer(&pm->stay_awake, jiffies + 1);
-+ spin_unlock_bh(&pm->lock);
-+}
-+#endif /* CONFIG_WAKELOCK */
-+
-+static long xradio_suspend_work(struct delayed_work *work)
-+{
-+ int ret = cancel_delayed_work(work);
-+ long tmo;
-+ pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
-+
-+ if (ret > 0) {
-+ /* Timer is pending */
-+ tmo = work->timer.expires - jiffies;
-+ if (tmo < 0)
-+ tmo = 0;
-+ } else {
-+ tmo = -1;
-+ }
-+ return tmo;
-+}
-+
-+static int xradio_resume_work(struct xradio_common *hw_priv,
-+ struct delayed_work *work,
-+ unsigned long tmo)
-+{
-+ pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
-+ if ((long)tmo < 0)
-+ return 1;
-+
-+ return queue_delayed_work(hw_priv->workqueue, work, tmo);
-+}
-+
-+static int xradio_suspend_late(struct device *dev)
-+{
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+ struct xradio_common *hw_priv = dev->platform_data;
-+
-+ if (XRADIO_POWEROFF_SUSP == atomic_read(&hw_priv->suspend_state)) {
-+ return 0; /* we don't rx data when power down wifi.*/
-+ }
-+#endif
-+
-+ //if (atomic_read(&hw_priv->bh_rx)) {
-+ // pm_printk(XRADIO_DBG_WARN, "%s: Suspend interrupted.\n", __func__);
-+ // return -EAGAIN;
-+ //}
-+ return 0;
-+}
-+
-+static void xradio_pm_release(struct device *dev)
-+{
-+ pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
-+}
-+
-+static int xradio_pm_probe(struct platform_device *pdev)
-+{
-+ pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
-+ pdev->dev.release = xradio_pm_release;
-+ return 0;
-+}
-+
-+int xradio_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv;
-+ int i, ret = 0;
-+
-+
-+ if(hw_priv->bh_error) return -EBUSY;
-+ WARN_ON(!atomic_read(&hw_priv->num_vifs));
-+
-+ if (work_pending(&hw_priv->query_work))
-+ return -EBUSY;
-+
-+#ifdef ROAM_OFFLOAD
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ if((priv->vif->type == NL80211_IFTYPE_STATION)
-+ && (priv->join_status == XRADIO_JOIN_STATUS_STA)) {
-+ down(&hw_priv->scan.lock);
-+ hw_priv->scan.if_id = priv->if_id;
-+ xradio_sched_scan_work(&hw_priv->scan.swork);
-+ }
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+
-+ /* Do not suspend when datapath is not idle */
-+ if (hw_priv->tx_queue_stats.num_queued[0] +
-+ hw_priv->tx_queue_stats.num_queued[1]) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of tx_queue is not empty.\n");
-+ return -EBUSY;
-+ }
-+
-+ /* Make sure there is no configuration requests in progress. */
-+ if (!mutex_trylock(&hw_priv->conf_mutex)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of configuration requests.\n");
-+ return -EBUSY;
-+ }
-+
-+ /* Make sure there is no wsm_oper_lock in progress. */
-+ if (!mutex_trylock(&hw_priv->wsm_oper_lock)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of wsm_oper_lock.\n");
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return -EBUSY;
-+ }
-+
-+ /* Do not suspend when scanning or ROC*/
-+ if (down_trylock(&hw_priv->scan.lock)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of scan requests.\n");
-+ goto revert1;
-+ }
-+
-+ if (delayed_work_pending(&hw_priv->scan.probe_work)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of probe frames tx in progress.\n");
-+ goto revert2;
-+ }
-+
-+ /* Lock TX. */
-+ wsm_lock_tx_async(hw_priv);
-+
-+ /* Wait to avoid possible race with bh code.
-+ * But do not wait too long... */
-+ if (wait_event_timeout(hw_priv->bh_evt_wq,
-+ !hw_priv->hw_bufs_used, HZ / 10) <= 0) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of there are frames not confirm.\n");
-+ goto revert3;
-+ }
-+
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+// if (STANDBY_WITH_POWER_OFF == standby_level) {
-+ if (1) {
-+ return xradio_poweroff_suspend(hw_priv);
-+ }
-+#endif
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+
-+ ret = __xradio_wow_suspend(priv, wowlan);
-+ if (ret) {
-+ for (; i >= 0; i--) {
-+ if (!hw_priv->vif_list[i])
-+ continue;
-+ priv = (struct xradio_vif *)hw_priv->vif_list[i]->drv_priv;
-+ __xradio_wow_resume(priv);
-+ }
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of __xradio_wow_suspend failed!\n");
-+ goto revert3;
-+ }
-+ }
-+
-+ /* Stop serving thread */
-+ if (xradio_bh_suspend(hw_priv)) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ "because of xradio_bh_suspend failed!\n");
-+ xradio_wow_resume(hw);
-+ return -EBUSY;
-+ }
-+
-+ /* Enable IRQ wake */
-+ ret = sdio_pm(hw_priv, true);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_WARN, "Don't suspend sbus pm failed\n");
-+ xradio_wow_resume(hw);
-+ return -EBUSY;
-+ }
-+
-+ /* Force resume if event is coming from the device. */
-+ //if (atomic_read(&hw_priv->bh_rx)) {
-+ // pm_printk(XRADIO_DBG_WARN, "Don't suspend "
-+ // "because of recieved rx event!\n");
-+ // xradio_wow_resume(hw);
-+ // return -EAGAIN;
-+ //}
-+ return 0;
-+
-+revert3:
-+ wsm_unlock_tx(hw_priv);
-+revert2:
-+ up(&hw_priv->scan.lock);
-+revert1:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ mutex_unlock(&hw_priv->wsm_oper_lock);
-+ return -EBUSY;
-+}
-+
-+static int __xradio_wow_suspend(struct xradio_vif *priv,
-+ struct cfg80211_wowlan *wowlan)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct xradio_pm_state_vif *pm_state_vif = &priv->pm_state_vif;
-+ struct xradio_suspend_state *state;
-+ int ret;
-+#ifdef MCAST_FWDING
-+ struct wsm_forwarding_offload fwdoffload = {
-+ .fwenable = 0x1,
-+ .flags = 0x1,
-+ };
-+#endif
-+
-+
-+ /* Do not suspend when join work is scheduled */
-+ if (work_pending(&priv->join_work)) {
-+ pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
-+ "when join work is scheduled\n", __func__);
-+ goto revert1;
-+ }
-+
-+ /* Set UDP filter */
-+ wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_on.hdr,
-+ priv->if_id);
-+
-+ /* Set ethernet frame type filter */
-+ wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_on.hdr,
-+ priv->if_id);
-+
-+ /* Set IP multicast filter */
-+ wsm_set_host_sleep(hw_priv, 1, priv->if_id);
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_keepalive_filter(priv, true));
-+
-+#ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
-+ /* Set Multicast Address Filter */
-+ if (priv->multicast_filter.numOfAddresses) {
-+ priv->multicast_filter.enable = 1;
-+ wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id);
-+ }
-+
-+ /* Set Enable Broadcast Address Filter */
-+ priv->broadcast_filter.action_mode = 1;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ priv->broadcast_filter.address_mode = 3;
-+
-+ xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
-+#endif
-+
-+#ifdef MCAST_FWDING
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload,priv->if_id));
-+#endif
-+
-+ /* Allocate state */
-+ state = kzalloc(sizeof(struct xradio_suspend_state), GFP_KERNEL);
-+ if (!state) {
-+ pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
-+ "alloc xradio_suspend_state failed.\n", __func__);
-+ goto revert2;
-+ }
-+ /* Store delayed work states. */
-+ state->bss_loss_tmo = xradio_suspend_work(&priv->bss_loss_work);
-+ state->connection_loss_tmo = xradio_suspend_work(&priv->connection_loss_work);
-+ state->join_tmo = xradio_suspend_work(&priv->join_timeout);
-+ state->link_id_gc = xradio_suspend_work(&priv->link_id_gc_work);
-+
-+ /* Enable beacon skipping */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA &&
-+ priv->join_dtim_period && !priv->has_multicast_subscription) {
-+ state->beacon_skipping = true;
-+ wsm_set_beacon_wakeup_period(hw_priv, priv->join_dtim_period,
-+ XRADIO_BEACON_SKIPPING_MULTIPLIER * \
-+ priv->join_dtim_period, priv->if_id);
-+ }
-+
-+ ret = timer_pending(&priv->mcast_timeout);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
-+ "mcast timeout timer_pending failed.\n", __func__);
-+ goto revert3;
-+ }
-+
-+ /* Store suspend state */
-+ pm_state_vif->suspend_state = state;
-+
-+ return 0;
-+
-+revert3:
-+ xradio_resume_work(hw_priv, &priv->bss_loss_work, state->bss_loss_tmo);
-+ xradio_resume_work(hw_priv, &priv->connection_loss_work,
-+ state->connection_loss_tmo);
-+ xradio_resume_work(hw_priv, &priv->join_timeout, state->join_tmo);
-+ xradio_resume_work(hw_priv, &priv->link_id_gc_work, state->link_id_gc);
-+ kfree(state);
-+
-+revert2:
-+ wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_off, priv->if_id);
-+ wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_off, priv->if_id);
-+ wsm_set_host_sleep(hw_priv, 0, priv->if_id);
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_keepalive_filter(priv, false));
-+
-+#ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
-+ /* Set Multicast Address Filter */
-+ if (priv->multicast_filter.numOfAddresses) {
-+ priv->multicast_filter.enable = 0;
-+ wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id);
-+ }
-+
-+ /* Set Enable Broadcast Address Filter */
-+ priv->broadcast_filter.action_mode = 0;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ priv->broadcast_filter.address_mode = 0;
-+ xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
-+#endif
-+
-+#ifdef MCAST_FWDING
-+ fwdoffload.flags = 0x0;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload,priv->if_id));
-+#endif
-+
-+revert1:
-+ /* mutex_unlock(&hw_priv->conf_mutex); */
-+ return -EBUSY;
-+}
-+
-+int xradio_wow_resume(struct ieee80211_hw *hw)
-+{
-+
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv;
-+ int i, ret = 0;
-+
-+
-+ WARN_ON(!atomic_read(&hw_priv->num_vifs));
-+ if(hw_priv->bh_error) return 0;
-+
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+ if (XRADIO_POWEROFF_SUSP == atomic_read(&hw_priv->suspend_state)) {
-+ return xradio_poweroff_resume(hw_priv);
-+ }
-+#endif
-+
-+ /* Disable IRQ wake */
-+ sdio_pm(hw_priv, false);
-+
-+ up(&hw_priv->scan.lock);
-+
-+ /* Resume BH thread */
-+ WARN_ON(xradio_bh_resume(hw_priv));
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ ret = __xradio_wow_resume(priv);
-+ if (ret) {
-+ pm_printk(XRADIO_DBG_ERROR, "%s:__xradio_wow_resume failed!\n", __func__);
-+ break;
-+ }
-+ }
-+
-+ wsm_unlock_tx(hw_priv);
-+
-+ /* Unlock configuration mutex */
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ mutex_unlock(&hw_priv->wsm_oper_lock);
-+
-+ return ret;
-+}
-+
-+static int __xradio_wow_resume(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct xradio_pm_state_vif *pm_state_vif = &priv->pm_state_vif;
-+ struct xradio_suspend_state *state;
-+#ifdef MCAST_FWDING
-+ struct wsm_forwarding_offload fwdoffload = {
-+ .fwenable = 0x1,
-+ .flags = 0x0,
-+ };
-+#endif
-+
-+
-+ /* Restore suspend state */
-+ state = pm_state_vif->suspend_state;
-+ pm_state_vif->suspend_state = NULL;
-+
-+#ifdef ROAM_OFFLOAD
-+ if((priv->vif->type == NL80211_IFTYPE_STATION)
-+ && (priv->join_status == XRADIO_JOIN_STATUS_STA))
-+ xradio_hw_sched_scan_stop(hw_priv);
-+#endif /*ROAM_OFFLOAD*/
-+
-+ if (state->beacon_skipping) {
-+#ifdef XRADIO_USE_LONG_DTIM_PERIOD
-+ int join_dtim_period_extend;
-+ if (priv->join_dtim_period <= 3) {
-+ join_dtim_period_extend = priv->join_dtim_period * 3;
-+ } else if (priv->join_dtim_period <= 5) {
-+ join_dtim_period_extend = priv->join_dtim_period * 2;
-+ } else {
-+ join_dtim_period_extend = priv->join_dtim_period;
-+ }
-+ wsm_set_beacon_wakeup_period(hw_priv,
-+ ((priv->beacon_int * join_dtim_period_extend) > MAX_BEACON_SKIP_TIME_MS ?
-+ 1 : join_dtim_period_extend) , 0, priv->if_id);
-+#else
-+ wsm_set_beacon_wakeup_period(hw_priv, priv->beacon_int *
-+ (priv->join_dtim_period > MAX_BEACON_SKIP_TIME_MS ? 1 : priv->join_dtim_period),
-+ 0, priv->if_id);
-+#endif
-+ state->beacon_skipping = false;
-+ }
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_keepalive_filter(priv, false));
-+
-+#ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
-+ /* Set Multicast Address Filter */
-+ if (priv->multicast_filter.numOfAddresses) {
-+ priv->multicast_filter.enable = 0;
-+ wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id);
-+ }
-+ /* Set Enable Broadcast Address Filter */
-+ priv->broadcast_filter.action_mode = 0;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ priv->broadcast_filter.address_mode = 0;
-+ xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
-+#endif
-+
-+#ifdef MCAST_FWDING
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP)
-+ WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload,priv->if_id));
-+#endif
-+
-+ /* Resume delayed work */
-+ xradio_resume_work(hw_priv, &priv->bss_loss_work, state->bss_loss_tmo);
-+ xradio_resume_work(hw_priv, &priv->connection_loss_work,
-+ state->connection_loss_tmo);
-+ xradio_resume_work(hw_priv, &priv->join_timeout, state->join_tmo);
-+ xradio_resume_work(hw_priv, &priv->link_id_gc_work, state->link_id_gc);
-+
-+ /* Remove UDP port filter */
-+ wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_off, priv->if_id);
-+
-+ /* Remove ethernet frame type filter */
-+ wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_off, priv->if_id);
-+
-+ /* Remove IP multicast filter */
-+ wsm_set_host_sleep(hw_priv, 0, priv->if_id);
-+ /* Free memory */
-+ kfree(state);
-+
-+ return 0;
-+}
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+static int xradio_poweroff_suspend(struct xradio_common *hw_priv)
-+{
-+
-+ //flush all work.
-+ cancel_work_sync(&hw_priv->query_work);
-+ flush_workqueue(hw_priv->workqueue);
-+ /* Schedule hardware restart, ensure no cmds in progress.*/
-+ mutex_lock(&hw_priv->wsm_cmd_mux);
-+ atomic_set(&hw_priv->suspend_state, XRADIO_POWEROFF_SUSP);
-+ //hw_priv->hw_restart = true;
-+ mutex_unlock(&hw_priv->wsm_cmd_mux);
-+ /* Stop serving thread */
-+ if (xradio_bh_suspend(hw_priv)) {
-+ pm_printk(XRADIO_DBG_WARN, "%s, xradio_bh_suspend failed!\n", __func__);
-+ return -EBUSY;
-+ }
-+
-+ return 0;
-+}
-+
-+static int xradio_poweroff_resume(struct xradio_common *hw_priv)
-+{
-+
-+ /* Revert locks */
-+ wsm_unlock_tx(hw_priv);
-+ up(&hw_priv->scan.lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ mutex_unlock(&hw_priv->wsm_oper_lock);
-+ //if (schedule_work(&hw_priv->hw_restart_work) <= 0)
-+ // pm_printk(XRADIO_DBG_ERROR, "%s restart_work failed!\n", __func__);
-+ return 0;
-+}
-+#endif
-diff --git a/drivers/net/wireless/xradio/pm.h b/drivers/net/wireless/xradio/pm.h
-new file mode 100644
-index 0000000..6443cbc
---- /dev/null
-+++ b/drivers/net/wireless/xradio/pm.h
-@@ -0,0 +1,64 @@
-+/*
-+ * power management interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#ifndef PM_H_INCLUDED
-+#define PM_H_INCLUDED
-+
-+#ifdef CONFIG_WAKELOCK
-+#include
-+#endif
-+
-+/* ******************************************************************** */
-+/* mac80211 API */
-+
-+#ifdef CONFIG_PM
-+
-+#define XRADIO_PM_DEVICE "xradio_pm"
-+#define XRADIO_WAKE_LOCK "xradio_wlan"
-+
-+/* extern */ struct xradio_common;
-+ /* private */ struct xradio_suspend_state;
-+
-+struct xradio_pm_state {
-+#ifdef CONFIG_WAKELOCK
-+ struct wake_lock wakelock;
-+#else
-+ struct timer_list stay_awake;
-+#endif
-+ struct platform_device *pm_dev;
-+ spinlock_t lock;
-+ unsigned long expires_save;
-+};
-+
-+struct xradio_pm_state_vif {
-+ struct xradio_suspend_state *suspend_state;
-+};
-+
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+enum suspend_state {
-+ XRADIO_RESUME = 0,
-+ XRADIO_CONNECT_SUSP,
-+ XRADIO_DISCONNECT_SUSP,
-+ XRADIO_POWEROFF_SUSP
-+};
-+#endif
-+int xradio_pm_init(struct xradio_pm_state *pm, struct xradio_common *priv);
-+void xradio_pm_deinit(struct xradio_pm_state *pm);
-+void xradio_pm_stay_awake(struct xradio_pm_state *pm, unsigned long tmo);
-+void xradio_pm_lock_awake(struct xradio_pm_state *pm);
-+void xradio_pm_unlock_awake(struct xradio_pm_state *pm);
-+int xradio_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
-+int xradio_wow_resume(struct ieee80211_hw *hw);
-+
-+#endif /* CONFIG_PM */
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/queue.c b/drivers/net/wireless/xradio/queue.c
-new file mode 100644
-index 0000000..e4b00ea
---- /dev/null
-+++ b/drivers/net/wireless/xradio/queue.c
-@@ -0,0 +1,820 @@
-+/*
-+ * Queue implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include "xradio.h"
-+#include "queue.h"
-+
-+/* private */ struct xradio_queue_item
-+{
-+ struct list_head head;
-+ struct sk_buff *skb;
-+ u32 packetID;
-+ unsigned long queue_timestamp;
-+ unsigned long xmit_timestamp;
-+ struct xradio_txpriv txpriv;
-+ u8 generation;
-+ u8 pack_stk_wr;
-+};
-+
-+static inline void __xradio_queue_lock(struct xradio_queue *queue)
-+{
-+ struct xradio_queue_stats *stats = queue->stats;
-+ if (queue->tx_locked_cnt++ == 0) {
-+ txrx_printk(XRADIO_DBG_MSG, "[TX] Queue %d is locked.\n",
-+ queue->queue_id);
-+ ieee80211_stop_queue(stats->hw_priv->hw, queue->queue_id);
-+ }
-+}
-+
-+static inline void __xradio_queue_unlock(struct xradio_queue *queue)
-+{
-+ struct xradio_queue_stats *stats = queue->stats;
-+ BUG_ON(!queue->tx_locked_cnt);
-+ if (--queue->tx_locked_cnt == 0) {
-+ txrx_printk(XRADIO_DBG_MSG, "[TX] Queue %d is unlocked.\n",
-+ queue->queue_id);
-+ ieee80211_wake_queue(stats->hw_priv->hw, queue->queue_id);
-+ }
-+}
-+
-+static inline void xradio_queue_parse_id(u32 packetID, u8 *queue_generation,
-+ u8 *queue_id,
-+ u8 *item_generation,
-+ u8 *item_id,
-+ u8 *if_id,
-+ u8 *link_id)
-+{
-+ *item_id = (packetID >> 0) & 0xFF;
-+ *item_generation = (packetID >> 8) & 0xFF;
-+ *queue_id = (packetID >> 16) & 0xF;
-+ *if_id = (packetID >> 20) & 0xF;
-+ *link_id = (packetID >> 24) & 0xF;
-+ *queue_generation = (packetID >> 28) & 0xF;
-+}
-+
-+static inline u32 xradio_queue_make_packet_id(u8 queue_generation, u8 queue_id,
-+ u8 item_generation, u8 item_id,
-+ u8 if_id, u8 link_id)
-+{
-+ /*TODO:COMBO: Add interfaceID to the packetID */
-+ return ((u32)item_id << 0) |
-+ ((u32)item_generation << 8) |
-+ ((u32)queue_id << 16) |
-+ ((u32)if_id << 20) |
-+ ((u32)link_id << 24) |
-+ ((u32)queue_generation << 28);
-+}
-+
-+static void xradio_queue_post_gc(struct xradio_queue_stats *stats,
-+ struct list_head *gc_list)
-+{
-+ struct xradio_queue_item *item;
-+
-+ while (!list_empty(gc_list)) {
-+ item = list_first_entry(
-+ gc_list, struct xradio_queue_item, head);
-+ list_del(&item->head);
-+ stats->skb_dtor(stats->hw_priv, item->skb, &item->txpriv);
-+ kfree(item);
-+ }
-+}
-+
-+static void xradio_queue_register_post_gc(struct list_head *gc_list,
-+ struct xradio_queue_item *item)
-+{
-+ struct xradio_queue_item *gc_item;
-+ gc_item = kmalloc(sizeof(struct xradio_queue_item), GFP_KERNEL);
-+ BUG_ON(!gc_item);
-+ memcpy(gc_item, item, sizeof(struct xradio_queue_item));
-+ list_add_tail(&gc_item->head, gc_list);
-+}
-+
-+static void __xradio_queue_gc(struct xradio_queue *queue,
-+ struct list_head *head,
-+ bool unlock)
-+{
-+ struct xradio_queue_stats *stats = queue->stats;
-+ struct xradio_queue_item *item = NULL;
-+ //struct xradio_vif *priv;
-+ int if_id;
-+ bool wakeup_stats = false;
-+
-+ while (!list_empty(&queue->queue)) {
-+ struct xradio_txpriv *txpriv;
-+ item = list_first_entry(
-+ &queue->queue, struct xradio_queue_item, head);
-+ if (time_before(jiffies, item->queue_timestamp+queue->ttl))
-+ break;
-+
-+ txpriv = &item->txpriv;
-+ if_id = txpriv->if_id;
-+ --queue->num_queued;
-+ --queue->num_queued_vif[if_id];
-+ --queue->link_map_cache[if_id][txpriv->link_id];
-+ spin_lock_bh(&stats->lock);
-+ --stats->num_queued[if_id];
-+ if (!--stats->link_map_cache[if_id][txpriv->link_id])
-+ wakeup_stats = true;
-+ spin_unlock_bh(&stats->lock);
-+ //priv = xrwl_hwpriv_to_vifpriv(stats->hw_priv, if_id);
-+ //if (priv) {
-+ // xradio_debug_tx_ttl(priv);
-+ // spin_unlock(&priv->vif_lock);
-+ //}
-+ xradio_queue_register_post_gc(head, item);
-+ item->skb = NULL;
-+ list_move_tail(&item->head, &queue->free_pool);
-+ }
-+
-+ if (wakeup_stats)
-+ wake_up(&stats->wait_link_id_empty);
-+
-+ //modified by yangfh for test WFD
-+ if (queue->overfull) {
-+ if (queue->num_queued <= ((stats->hw_priv->vif0_throttle +
-+ stats->hw_priv->vif1_throttle+2)>>1)) {
-+ queue->overfull = false;
-+ if (unlock) {
-+ __xradio_queue_unlock(queue);
-+ }
-+ } else if (item) {
-+ unsigned long tmo = item->queue_timestamp + queue->ttl;
-+ mod_timer(&queue->gc, tmo);
-+ xradio_pm_stay_awake(&stats->hw_priv->pm_state,
-+ tmo - jiffies);
-+ }
-+ }
-+}
-+
-+static void xradio_queue_gc(struct timer_list *t)
-+{
-+ struct xradio_queue *queue = from_timer(queue, t, gc);
-+
-+ LIST_HEAD(list);
-+
-+ spin_lock_bh(&queue->lock);
-+ __xradio_queue_gc(queue, &list, true);
-+ spin_unlock_bh(&queue->lock);
-+ xradio_queue_post_gc(queue->stats, &list);
-+}
-+
-+int xradio_queue_stats_init(struct xradio_queue_stats *stats,
-+ size_t map_capacity,
-+ xradio_queue_skb_dtor_t skb_dtor,
-+ struct xradio_common *hw_priv)
-+{
-+ int i;
-+
-+ memset(stats, 0, sizeof(*stats));
-+ stats->map_capacity = map_capacity;
-+ stats->skb_dtor = skb_dtor;
-+ stats->hw_priv = hw_priv;
-+ spin_lock_init(&stats->lock);
-+ init_waitqueue_head(&stats->wait_link_id_empty);
-+ for (i = 0; i < XRWL_MAX_VIFS; i++) {
-+ stats->link_map_cache[i] = kzalloc(sizeof(int[map_capacity]), GFP_KERNEL);
-+ if (!stats->link_map_cache[i]) {
-+ for (; i >= 0; i--)
-+ kfree(stats->link_map_cache[i]);
-+ return -ENOMEM;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int xradio_queue_init(struct xradio_queue *queue,
-+ struct xradio_queue_stats *stats,
-+ u8 queue_id,
-+ size_t capacity,
-+ unsigned long ttl)
-+{
-+ int i;
-+
-+ memset(queue, 0, sizeof(*queue));
-+ queue->stats = stats;
-+ queue->capacity = capacity;
-+ queue->queue_id = queue_id;
-+ queue->ttl = ttl;
-+ INIT_LIST_HEAD(&queue->queue);
-+ INIT_LIST_HEAD(&queue->pending);
-+ INIT_LIST_HEAD(&queue->free_pool);
-+ spin_lock_init(&queue->lock);
-+ timer_setup(&queue->gc, xradio_queue_gc, 0);
-+
-+ queue->pool = kzalloc(sizeof(struct xradio_queue_item) * capacity,
-+ GFP_KERNEL);
-+ if (!queue->pool)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < XRWL_MAX_VIFS; i++) {
-+ queue->link_map_cache[i] =
-+ kzalloc(sizeof(int[stats->map_capacity]), GFP_KERNEL);
-+ if (!queue->link_map_cache[i]) {
-+ for (; i >= 0; i--)
-+ kfree(queue->link_map_cache[i]);
-+ kfree(queue->pool);
-+ queue->pool = NULL;
-+ return -ENOMEM;
-+ }
-+ }
-+
-+ for (i = 0; i < capacity; ++i)
-+ list_add_tail(&queue->pool[i].head, &queue->free_pool);
-+
-+ return 0;
-+}
-+
-+/* TODO:COMBO: Flush only a particular interface specific parts */
-+int xradio_queue_clear(struct xradio_queue *queue, int if_id)
-+{
-+ int i, cnt, iter;
-+ struct xradio_queue_stats *stats = queue->stats;
-+ LIST_HEAD(gc_list);
-+
-+ cnt = 0;
-+ spin_lock_bh(&queue->lock);
-+ queue->generation++;
-+ queue->generation &= 0xf;
-+ list_splice_tail_init(&queue->queue, &queue->pending);
-+ while (!list_empty(&queue->pending)) {
-+ struct xradio_queue_item *item = list_first_entry(
-+ &queue->pending, struct xradio_queue_item, head);
-+ WARN_ON(!item->skb);
-+ if (XRWL_ALL_IFS == if_id || item->txpriv.if_id == if_id) {
-+ xradio_queue_register_post_gc(&gc_list, item);
-+ item->skb = NULL;
-+ list_move_tail(&item->head, &queue->free_pool);
-+ cnt++;
-+ }
-+ }
-+ queue->num_queued -= cnt;
-+ queue->num_pending = 0;
-+ if (XRWL_ALL_IFS != if_id) {
-+ queue->num_queued_vif[if_id] = 0;
-+ queue->num_pending_vif[if_id] = 0;
-+ } else {
-+ for (iter = 0; iter < XRWL_MAX_VIFS; iter++) {
-+ queue->num_queued_vif[iter] = 0;
-+ queue->num_pending_vif[iter] = 0;
-+ }
-+ }
-+ spin_lock_bh(&stats->lock);
-+ if (XRWL_ALL_IFS != if_id) {
-+ for (i = 0; i < stats->map_capacity; ++i) {
-+ stats->num_queued[if_id] -=
-+ queue->link_map_cache[if_id][i];
-+ stats->link_map_cache[if_id][i] -=
-+ queue->link_map_cache[if_id][i];
-+ queue->link_map_cache[if_id][i] = 0;
-+ }
-+ } else {
-+ for (iter = 0; iter < XRWL_MAX_VIFS; iter++) {
-+ for (i = 0; i < stats->map_capacity; ++i) {
-+ stats->num_queued[iter] -=
-+ queue->link_map_cache[iter][i];
-+ stats->link_map_cache[iter][i] -=
-+ queue->link_map_cache[iter][i];
-+ queue->link_map_cache[iter][i] = 0;
-+ }
-+ }
-+ }
-+ spin_unlock_bh(&stats->lock);
-+ if (unlikely(queue->overfull)) {
-+ queue->overfull = false;
-+ __xradio_queue_unlock(queue);
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ wake_up(&stats->wait_link_id_empty);
-+ xradio_queue_post_gc(stats, &gc_list);
-+ return 0;
-+}
-+
-+void xradio_queue_stats_deinit(struct xradio_queue_stats *stats)
-+{
-+ int i;
-+
-+ for (i = 0; i < XRWL_MAX_VIFS ; i++) {
-+ kfree(stats->link_map_cache[i]);
-+ stats->link_map_cache[i] = NULL;
-+ }
-+}
-+
-+void xradio_queue_deinit(struct xradio_queue *queue)
-+{
-+ int i;
-+
-+ xradio_queue_clear(queue, XRWL_ALL_IFS);
-+ del_timer_sync(&queue->gc);
-+ INIT_LIST_HEAD(&queue->free_pool);
-+ kfree(queue->pool);
-+ for (i = 0; i < XRWL_MAX_VIFS; i++) {
-+ kfree(queue->link_map_cache[i]);
-+ queue->link_map_cache[i] = NULL;
-+ }
-+ queue->pool = NULL;
-+ queue->capacity = 0;
-+}
-+
-+size_t xradio_queue_get_num_queued(struct xradio_vif *priv,
-+ struct xradio_queue *queue,
-+ u32 link_id_map)
-+{
-+ size_t ret;
-+ int i, bit;
-+ size_t map_capacity = queue->stats->map_capacity;
-+
-+ if (!link_id_map)
-+ return 0;
-+
-+ spin_lock_bh(&queue->lock);
-+ if (likely(link_id_map == (u32) -1)) {
-+ ret = queue->num_queued_vif[priv->if_id] -
-+ queue->num_pending_vif[priv->if_id];
-+ } else {
-+ ret = 0;
-+ for (i = 0, bit = 1; i < map_capacity; ++i, bit <<= 1) {
-+ if (link_id_map & bit)
-+ ret +=
-+ queue->link_map_cache[priv->if_id][i];
-+ }
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+int xradio_queue_put(struct xradio_queue *queue, struct sk_buff *skb,
-+ struct xradio_txpriv *txpriv)
-+{
-+ int ret = 0;
-+ LIST_HEAD(gc_list);
-+ struct xradio_queue_stats *stats = queue->stats;
-+ /* TODO:COMBO: Add interface ID info to queue item */
-+
-+ if (txpriv->link_id >= queue->stats->map_capacity)
-+ return -EINVAL;
-+
-+ spin_lock_bh(&queue->lock);
-+ if (!WARN_ON(list_empty(&queue->free_pool))) {
-+ struct xradio_queue_item *item = list_first_entry(
-+ &queue->free_pool, struct xradio_queue_item, head);
-+ BUG_ON(item->skb);
-+
-+ list_move_tail(&item->head, &queue->queue);
-+ item->skb = skb;
-+ item->txpriv = *txpriv;
-+ item->generation = 1; /* avoid packet ID is 0.*/
-+ item->pack_stk_wr = 0;
-+ item->packetID = xradio_queue_make_packet_id(
-+ queue->generation, queue->queue_id,
-+ item->generation, item - queue->pool,
-+ txpriv->if_id, txpriv->raw_link_id);
-+ item->queue_timestamp = jiffies;
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ if (TES_P2P_0002_state == TES_P2P_0002_STATE_SEND_RESP) {
-+ TES_P2P_0002_packet_id = item->packetID;
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_GET_PKTID;
-+ txrx_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_GET_PKTID]\n");
-+ }
-+#endif
-+
-+ ++queue->num_queued;
-+ ++queue->num_queued_vif[txpriv->if_id];
-+ ++queue->link_map_cache[txpriv->if_id][txpriv->link_id];
-+
-+ spin_lock_bh(&stats->lock);
-+ ++stats->num_queued[txpriv->if_id];
-+ ++stats->link_map_cache[txpriv->if_id][txpriv->link_id];
-+ spin_unlock_bh(&stats->lock);
-+
-+ /*
-+ * TX may happen in parallel sometimes.
-+ * Leave extra queue slots so we don't overflow.
-+ */
-+ if (queue->overfull == false &&
-+ queue->num_queued >=
-+ ((stats->hw_priv->vif0_throttle +stats->hw_priv->vif1_throttle)
-+ - (num_present_cpus() - 1))) {
-+ queue->overfull = true;
-+ __xradio_queue_lock(queue);
-+ mod_timer(&queue->gc, jiffies);
-+ txrx_printk(XRADIO_DBG_NIY,"!lock queue\n");
-+ }
-+ } else {
-+ ret = -ENOENT;
-+ }
-+#if 0
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_put queue %d, %d, %d\n",
-+ queue->num_queued,
-+ queue->link_map_cache[txpriv->if_id][txpriv->link_id],
-+ queue->num_pending);
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_put stats %d, %d\n", stats->num_queued,
-+ stats->link_map_cache[txpriv->if_id][txpriv->link_id]);
-+#endif
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+int xradio_queue_get(struct xradio_queue *queue,
-+ int if_id,
-+ u32 link_id_map,
-+ struct wsm_tx **tx,
-+ struct ieee80211_tx_info **tx_info,
-+ struct xradio_txpriv **txpriv)
-+{
-+ int ret = -ENOENT;
-+ struct xradio_queue_item *item;
-+ struct xradio_queue_stats *stats = queue->stats;
-+ bool wakeup_stats = false;
-+
-+ spin_lock_bh(&queue->lock);
-+ list_for_each_entry(item, &queue->queue, head) {
-+ if ((item->txpriv.if_id == if_id) &&
-+ (link_id_map & BIT(item->txpriv.link_id))) {
-+ ret = 0;
-+ break;
-+ }
-+ }
-+
-+ if (!WARN_ON(ret)) {
-+ *tx = (struct wsm_tx *)item->skb->data;
-+ *tx_info = IEEE80211_SKB_CB(item->skb);
-+ *txpriv = &item->txpriv;
-+ (*tx)->packetID = __cpu_to_le32(item->packetID);
-+ list_move_tail(&item->head, &queue->pending);
-+ ++queue->num_pending;
-+ ++queue->num_pending_vif[item->txpriv.if_id];
-+ --queue->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id];
-+ item->xmit_timestamp = jiffies;
-+
-+ spin_lock_bh(&stats->lock);
-+ --stats->num_queued[item->txpriv.if_id];
-+ if (!--stats->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id])
-+ wakeup_stats = true;
-+
-+ spin_unlock_bh(&stats->lock);
-+#if 0
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_get queue %d, %d, %d\n",
-+ queue->num_queued,
-+ queue->link_map_cache[item->txpriv.if_id][item->txpriv.link_id],
-+ queue->num_pending);
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_get stats %d, %d\n", stats->num_queued,
-+ stats->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id]);
-+#endif
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ if (wakeup_stats)
-+ wake_up(&stats->wait_link_id_empty);
-+
-+ return ret;
-+}
-+
-+int xradio_queue_requeue(struct xradio_queue *queue, u32 packetID, bool check)
-+{
-+ int ret = 0;
-+ u8 queue_generation, queue_id, item_generation, item_id, if_id, link_id;
-+ struct xradio_queue_item *item;
-+ struct xradio_queue_stats *stats = queue->stats;
-+
-+ xradio_queue_parse_id(packetID, &queue_generation, &queue_id,
-+ &item_generation, &item_id, &if_id, &link_id);
-+
-+ item = &queue->pool[item_id];
-+ if (check && item->txpriv.offchannel_if_id == XRWL_GENERIC_IF_ID) {
-+ txrx_printk(XRADIO_DBG_MSG, "Requeued frame dropped for "
-+ "generic interface id.\n");
-+ xradio_queue_remove(queue, packetID);
-+ return 0;
-+ }
-+
-+ if (!check)
-+ item->txpriv.offchannel_if_id = XRWL_GENERIC_IF_ID;
-+
-+ /*if_id = item->txpriv.if_id;*/
-+
-+ spin_lock_bh(&queue->lock);
-+ BUG_ON(queue_id != queue->queue_id);
-+ if (unlikely(queue_generation != queue->generation)) {
-+ ret = -ENOENT;
-+ } else if (unlikely(item_id >= (unsigned) queue->capacity)) {
-+ WARN_ON(1);
-+ ret = -EINVAL;
-+ } else if (unlikely(item->generation != item_generation)) {
-+ WARN_ON(1);
-+ ret = -ENOENT;
-+ } else {
-+ --queue->num_pending;
-+ --queue->num_pending_vif[if_id];
-+ ++queue->link_map_cache[if_id][item->txpriv.link_id];
-+
-+ spin_lock_bh(&stats->lock);
-+ ++stats->num_queued[item->txpriv.if_id];
-+ ++stats->link_map_cache[if_id][item->txpriv.link_id];
-+ spin_unlock_bh(&stats->lock);
-+
-+ item->generation = ++item_generation;
-+ item->packetID = xradio_queue_make_packet_id(
-+ queue_generation, queue_id, item_generation, item_id,
-+ if_id, link_id);
-+ list_move(&item->head, &queue->queue);
-+#if 0
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_requeue queue %d, %d, %d\n",
-+ queue->num_queued,
-+ queue->link_map_cache[if_id][item->txpriv.link_id],
-+ queue->num_pending);
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_requeue stats %d, %d\n",
-+ stats->num_queued,
-+ stats->link_map_cache[if_id][item->txpriv.link_id]);
-+#endif
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+int xradio_queue_requeue_all(struct xradio_queue *queue)
-+{
-+ struct xradio_queue_stats *stats = queue->stats;
-+ spin_lock_bh(&queue->lock);
-+ while (!list_empty(&queue->pending)) {
-+ struct xradio_queue_item *item = list_entry(
-+ queue->pending.prev, struct xradio_queue_item, head);
-+
-+ --queue->num_pending;
-+ --queue->num_pending_vif[item->txpriv.if_id];
-+ ++queue->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id];
-+
-+ spin_lock_bh(&stats->lock);
-+ ++stats->num_queued[item->txpriv.if_id];
-+ ++stats->link_map_cache[item->txpriv.if_id]
-+ [item->txpriv.link_id];
-+ spin_unlock_bh(&stats->lock);
-+
-+ ++item->generation;
-+ item->packetID = xradio_queue_make_packet_id(
-+ queue->generation, queue->queue_id,
-+ item->generation, item - queue->pool,
-+ item->txpriv.if_id, item->txpriv.raw_link_id);
-+ list_move(&item->head, &queue->queue);
-+ }
-+ spin_unlock_bh(&queue->lock);
-+
-+ return 0;
-+}
-+
-+int xradio_queue_remove(struct xradio_queue *queue, u32 packetID)
-+{
-+ int ret = 0;
-+ u8 queue_generation, queue_id, item_generation, item_id, if_id, link_id;
-+ struct xradio_queue_item *item;
-+ struct xradio_queue_stats *stats = queue->stats;
-+ struct sk_buff *gc_skb = NULL;
-+ struct xradio_txpriv gc_txpriv;
-+
-+ xradio_queue_parse_id(packetID, &queue_generation, &queue_id,
-+ &item_generation, &item_id, &if_id, &link_id);
-+
-+ item = &queue->pool[item_id];
-+
-+ spin_lock_bh(&queue->lock);
-+ BUG_ON(queue_id != queue->queue_id);
-+ /*TODO:COMBO:Add check for interface ID also */
-+ if (unlikely(queue_generation != queue->generation)) {
-+ ret = -ENOENT;
-+ } else if (unlikely(item_id >= (unsigned) queue->capacity)) {
-+ WARN_ON(1);
-+ ret = -EINVAL;
-+ } else if (unlikely(item->generation != item_generation)) {
-+ WARN_ON(1);
-+ ret = -ENOENT;
-+ } else {
-+ gc_txpriv = item->txpriv;
-+ gc_skb = item->skb;
-+ item->skb = NULL;
-+ --queue->num_pending;
-+ --queue->num_pending_vif[if_id];
-+ --queue->num_queued;
-+ --queue->num_queued_vif[if_id];
-+ ++queue->num_sent;
-+ ++item->generation;
-+
-+ /* Do not use list_move_tail here, but list_move:
-+ * try to utilize cache row.
-+ */
-+ list_move(&item->head, &queue->free_pool);
-+
-+ if (unlikely(queue->overfull) &&
-+ (queue->num_queued <= ((stats->hw_priv->vif0_throttle + stats->hw_priv->vif1_throttle + 2)>>1))) {
-+ queue->overfull = false;
-+ __xradio_queue_unlock(queue);
-+ }
-+ }
-+ spin_unlock_bh(&queue->lock);
-+
-+#if 0
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_drop queue %d, %d, %d\n",
-+ queue->num_queued, queue->link_map_cache[if_id][0],
-+ queue->num_pending);
-+ txrx_printk(XRADIO_DBG_ERROR, "queue_drop stats %d, %d\n", stats->num_queued,
-+ stats->link_map_cache[if_id][0]);
-+#endif
-+ if (gc_skb)
-+ stats->skb_dtor(stats->hw_priv, gc_skb, &gc_txpriv);
-+
-+ return ret;
-+}
-+
-+int xradio_queue_get_skb(struct xradio_queue *queue, u32 packetID,
-+ struct sk_buff **skb,
-+ const struct xradio_txpriv **txpriv)
-+{
-+ int ret = 0;
-+ u8 queue_generation, queue_id, item_generation, item_id, if_id, link_id;
-+ struct xradio_queue_item *item;
-+
-+ xradio_queue_parse_id(packetID, &queue_generation, &queue_id,
-+ &item_generation, &item_id, &if_id, &link_id);
-+
-+ item = &queue->pool[item_id];
-+
-+ spin_lock_bh(&queue->lock);
-+ BUG_ON(queue_id != queue->queue_id);
-+ /* TODO:COMBO: Add check for interface ID here */
-+ if (unlikely(queue_generation != queue->generation)) {
-+ ret = -ENOENT;
-+ } else if (unlikely(item_id >= (unsigned) queue->capacity)) {
-+ WARN_ON(1);
-+ ret = -EINVAL;
-+ } else if (unlikely(item->generation != item_generation)) {
-+ WARN_ON(1);
-+ ret = -ENOENT;
-+ } else {
-+ *skb = item->skb;
-+ *txpriv = &item->txpriv;
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+void xradio_queue_lock(struct xradio_queue *queue)
-+{
-+ spin_lock_bh(&queue->lock);
-+ __xradio_queue_lock(queue);
-+ spin_unlock_bh(&queue->lock);
-+}
-+
-+void xradio_queue_unlock(struct xradio_queue *queue)
-+{
-+ spin_lock_bh(&queue->lock);
-+ __xradio_queue_unlock(queue);
-+ spin_unlock_bh(&queue->lock);
-+}
-+
-+bool xradio_queue_get_xmit_timestamp(struct xradio_queue *queue,
-+ unsigned long *timestamp, int if_id,
-+ u32 pending_frameID, u32 *Old_frame_ID)
-+{
-+ struct xradio_queue_item *item;
-+ bool ret;
-+
-+ spin_lock_bh(&queue->lock);
-+ ret = !list_empty(&queue->pending);
-+ if (ret) {
-+ list_for_each_entry(item, &queue->pending, head) {
-+ if (((if_id == XRWL_GENERIC_IF_ID) ||
-+ (if_id == XRWL_ALL_IFS) ||
-+ (item->txpriv.if_id == if_id)) &&
-+ (item->packetID != pending_frameID)) {
-+ if (time_before(item->xmit_timestamp,
-+ *timestamp)) {
-+ *timestamp = item->xmit_timestamp;
-+ *Old_frame_ID = item->packetID;
-+ }
-+ }
-+ }
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ return ret;
-+}
-+
-+bool xradio_queue_stats_is_empty(struct xradio_queue_stats *stats,
-+ u32 link_id_map, int if_id)
-+{
-+ bool empty = true;
-+
-+ spin_lock_bh(&stats->lock);
-+ if (link_id_map == (u32)-1)
-+ empty = stats->num_queued[if_id] == 0;
-+ else {
-+ int i, if_id;
-+ for (if_id = 0; if_id < XRWL_MAX_VIFS; if_id++) {
-+ for (i = 0; i < stats->map_capacity; ++i) {
-+ if (link_id_map & BIT(i)) {
-+ if (stats->link_map_cache[if_id][i]) {
-+ empty = false;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ spin_unlock_bh(&stats->lock);
-+
-+ return empty;
-+}
-+
-+bool xradio_query_txpkt_timeout(struct xradio_common *hw_priv, int if_id,
-+ u32 pending_pkt_id, long *timeout)
-+{
-+ int i;
-+ bool pending = false;
-+ unsigned long timestamp = jiffies;
-+ struct xradio_queue *queue = NULL;
-+ struct xradio_queue_item *item = NULL;
-+ struct xradio_queue *old_queue = NULL;
-+ struct xradio_queue_item *old_item = NULL;
-+ u8 pack_stk_wr = 0;
-+
-+ /* Get oldest frame.*/
-+ for (i = 0; i < AC_QUEUE_NUM; ++i) {
-+ queue = &hw_priv->tx_queue[i];
-+ spin_lock_bh(&queue->lock);
-+ if (!list_empty(&queue->pending)) {
-+ list_for_each_entry(item, &queue->pending, head) {
-+ if (((if_id == XRWL_GENERIC_IF_ID) ||
-+ (if_id == XRWL_ALL_IFS) ||
-+ (item->txpriv.if_id == if_id)) &&
-+ (item->packetID != pending_pkt_id)) {
-+ if (time_before(item->xmit_timestamp, timestamp)) {
-+ timestamp = item->xmit_timestamp;
-+ pack_stk_wr = item->pack_stk_wr;
-+ old_queue = queue;
-+ old_item = item;
-+ }
-+ }
-+ }
-+ pending = true;
-+ }
-+ spin_unlock_bh(&queue->lock);
-+ }
-+ if (!pending)
-+ return false;
-+
-+ /* Check if frame transmission is timed out.
-+ * add (WSM_CMD_LAST_CHANCE_TIMEOUT>>1) for stuck workaround.*/
-+ *timeout = timestamp + WSM_CMD_LAST_CHANCE_TIMEOUT - jiffies;
-+ if (unlikely(*timeout < 0) && !pack_stk_wr) {
-+ struct ieee80211_hdr *frame = NULL;
-+ const struct xradio_txpriv *txpriv = NULL;
-+ u16 fctl = 0x0;
-+ u32 len = 0x0;
-+ u8 if_id = 0, link_id = 0, tid = 0;
-+
-+ /* query the timeout frame. */
-+ spin_lock_bh(&old_queue->lock);
-+ if (likely(old_item->skb && !hw_priv->query_packetID)) {
-+ hw_priv->query_packetID = old_item->packetID;
-+ old_item->pack_stk_wr = 1;
-+ atomic_add(1, &hw_priv->query_cnt);
-+
-+ /* Info of stuck frames for debug.*/
-+ txpriv = &old_item->txpriv;
-+ frame = (struct ieee80211_hdr *)(&old_item->skb->data[txpriv->offset]);
-+ fctl = frame->frame_control;
-+ len = old_item->skb->len;
-+ if_id = txpriv->if_id;
-+ link_id = txpriv->link_id;
-+ tid = txpriv->tid;
-+ }
-+ spin_unlock_bh(&old_queue->lock);
-+ /* Dump Info of stuck frames. */
-+ if (frame) {
-+ txrx_printk(XRADIO_DBG_ERROR, "TX confirm timeout(%ds).\n",
-+ WSM_CMD_LAST_CHANCE_TIMEOUT/HZ);
-+ txrx_printk(XRADIO_DBG_ERROR, "if=%d, linkid=%d, tid=%d, " \
-+ "old_packetID=0x%08x, fctl=0x%04x, len=%d, wr=%d\n",
-+ if_id, link_id, tid, hw_priv->query_packetID, fctl, len,
-+ pack_stk_wr);
-+ }
-+ /* Return half of timeout for query packet. */
-+ *timeout = (WSM_CMD_LAST_CHANCE_TIMEOUT>>1);
-+ } else if (unlikely(pack_stk_wr)){
-+ *timeout = *timeout + (WSM_CMD_LAST_CHANCE_TIMEOUT>>1);
-+ txrx_printk(XRADIO_DBG_MSG,"%s, wr and timeout=%ld\n", __func__, *timeout);
-+ }
-+ return pending;
-+}
-diff --git a/drivers/net/wireless/xradio/queue.h b/drivers/net/wireless/xradio/queue.h
-new file mode 100644
-index 0000000..d6b64ce
---- /dev/null
-+++ b/drivers/net/wireless/xradio/queue.h
-@@ -0,0 +1,139 @@
-+/*
-+ * queue operations for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#ifndef XRADIO_QUEUE_H_INCLUDED
-+#define XRADIO_QUEUE_H_INCLUDED
-+
-+/* private */ struct xradio_queue_item;
-+
-+/* extern */ struct sk_buff;
-+/* extern */ struct wsm_tx;
-+/* extern */ struct xradio_common;
-+/* extern */ struct xradio_vif;
-+/* extern */ struct ieee80211_tx_queue_stats;
-+/* extern */ struct xradio_txpriv;
-+
-+/* forward */ struct xradio_queue_stats;
-+
-+typedef void (*xradio_queue_skb_dtor_t)(struct xradio_common *priv,
-+ struct sk_buff *skb,
-+ const struct xradio_txpriv *txpriv);
-+
-+struct xradio_queue {
-+ struct xradio_queue_stats *stats;
-+ size_t capacity;
-+ size_t num_queued;
-+ size_t num_queued_vif[XRWL_MAX_VIFS];
-+ size_t num_pending;
-+ size_t num_pending_vif[XRWL_MAX_VIFS];
-+ size_t num_sent;
-+ struct xradio_queue_item *pool;
-+ struct list_head queue;
-+ struct list_head free_pool;
-+ struct list_head pending;
-+ int tx_locked_cnt;
-+ int *link_map_cache[XRWL_MAX_VIFS];
-+ bool overfull;
-+ spinlock_t lock;
-+ u8 queue_id;
-+ u8 generation;
-+ struct timer_list gc;
-+ unsigned long ttl;
-+};
-+
-+struct xradio_queue_stats {
-+ spinlock_t lock;
-+ int *link_map_cache[XRWL_MAX_VIFS];
-+ int num_queued[XRWL_MAX_VIFS];
-+ size_t map_capacity;
-+ wait_queue_head_t wait_link_id_empty;
-+ xradio_queue_skb_dtor_t skb_dtor;
-+ struct xradio_common *hw_priv;
-+};
-+
-+struct xradio_txpriv {
-+ u8 link_id;
-+ u8 raw_link_id;
-+ u8 tid;
-+ u8 rate_id;
-+ u8 offset;
-+ u8 if_id;
-+ u8 offchannel_if_id;
-+ u8 use_bg_rate;
-+};
-+
-+int xradio_queue_stats_init(struct xradio_queue_stats *stats,
-+ size_t map_capacity,
-+ xradio_queue_skb_dtor_t skb_dtor,
-+ struct xradio_common *priv);
-+int xradio_queue_init(struct xradio_queue *queue,
-+ struct xradio_queue_stats *stats,
-+ u8 queue_id,
-+ size_t capacity,
-+ unsigned long ttl);
-+int xradio_queue_clear(struct xradio_queue *queue, int if_id);
-+void xradio_queue_stats_deinit(struct xradio_queue_stats *stats);
-+void xradio_queue_deinit(struct xradio_queue *queue);
-+
-+size_t xradio_queue_get_num_queued(struct xradio_vif *priv,
-+ struct xradio_queue *queue,
-+ u32 link_id_map);
-+int xradio_queue_put(struct xradio_queue *queue,
-+ struct sk_buff *skb, struct xradio_txpriv *txpriv);
-+int xradio_queue_get(struct xradio_queue *queue,
-+ int if_id, u32 link_id_map,
-+ struct wsm_tx **tx,
-+ struct ieee80211_tx_info **tx_info,
-+ struct xradio_txpriv **txpriv);
-+
-+int xradio_queue_requeue(struct xradio_queue *queue, u32 packetID, bool check);
-+
-+int xradio_queue_requeue_all(struct xradio_queue *queue);
-+int xradio_queue_remove(struct xradio_queue *queue,
-+ u32 packetID);
-+
-+int xradio_queue_get_skb(struct xradio_queue *queue, u32 packetID,
-+ struct sk_buff **skb,
-+ const struct xradio_txpriv **txpriv);
-+void xradio_queue_lock(struct xradio_queue *queue);
-+void xradio_queue_unlock(struct xradio_queue *queue);
-+bool xradio_queue_get_xmit_timestamp(struct xradio_queue *queue,
-+ unsigned long *timestamp, int if_id,
-+ u32 pending_frameID, u32 *Old_frame_ID);
-+bool xradio_query_txpkt_timeout(struct xradio_common *hw_priv, int if_id,
-+ u32 pending_pkt_id, long *timeout);
-+
-+
-+bool xradio_queue_stats_is_empty(struct xradio_queue_stats *stats,
-+ u32 link_id_map, int if_id);
-+
-+static inline u8 xradio_queue_get_queue_id(u32 packetID)
-+{
-+ return (packetID >> 16) & 0xF;
-+}
-+
-+static inline u8 xradio_queue_get_if_id(u32 packetID)
-+{
-+ return (packetID >> 20) & 0xF;
-+}
-+
-+static inline u8 xradio_queue_get_link_id(u32 packetID)
-+{
-+ return (packetID >> 24) & 0xF;
-+}
-+
-+static inline u8 xradio_queue_get_generation(u32 packetID)
-+{
-+ return (packetID >> 8) & 0xFF;
-+}
-+
-+#endif /* XRADIO_QUEUE_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/rx.c b/drivers/net/wireless/xradio/rx.c
-new file mode 100644
-index 0000000..fb8be92
---- /dev/null
-+++ b/drivers/net/wireless/xradio/rx.c
-@@ -0,0 +1,414 @@
-+#include
-+
-+#include "xradio.h"
-+#include "rx.h"
-+#include "ht.h"
-+#include "p2p.h"
-+#include "sta.h"
-+#include "bh.h"
-+#include "ap.h"
-+
-+ // MRK: added copy of this tx.c function here for testing, renamed _rx
-+
-+static void xradio_check_go_neg_conf_success_rx(struct xradio_common *hw_priv,
-+ u8 *action)
-+{
-+ if (action[2] == 0x50 && action[3] == 0x6F && action[4] == 0x9A &&
-+ action[5] == 0x09 && action[6] == 0x02) {
-+ if(action[17] == 0) {
-+ hw_priv->is_go_thru_go_neg = true;
-+ }
-+ else {
-+ hw_priv->is_go_thru_go_neg = false;
-+ }
-+ }
-+}
-+
-+
-+static int xradio_handle_pspoll(struct xradio_vif *priv,
-+ struct sk_buff *skb)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct ieee80211_sta *sta;
-+ struct ieee80211_pspoll *pspoll =
-+ (struct ieee80211_pspoll *) skb->data;
-+ int link_id = 0;
-+ u32 pspoll_mask = 0;
-+ int drop = 1;
-+ int i;
-+
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_AP)
-+ goto done;
-+ if (memcmp(priv->vif->addr, pspoll->bssid, ETH_ALEN))
-+ goto done;
-+
-+ rcu_read_lock();
-+ sta = ieee80211_find_sta(priv->vif, pspoll->ta);
-+ if (sta) {
-+ struct xradio_sta_priv *sta_priv;
-+ sta_priv = (struct xradio_sta_priv *)&sta->drv_priv;
-+ link_id = sta_priv->link_id;
-+ pspoll_mask = BIT(sta_priv->link_id);
-+ }
-+ rcu_read_unlock();
-+ if (!link_id)
-+ goto done;
-+
-+ priv->pspoll_mask |= pspoll_mask;
-+ drop = 0;
-+
-+ /* Do not report pspols if data for given link id is
-+ * queued already. */
-+ for (i = 0; i < 4; ++i) {
-+ if (xradio_queue_get_num_queued(priv,
-+ &hw_priv->tx_queue[i],
-+ pspoll_mask)) {
-+ xradio_bh_wakeup(hw_priv);
-+ drop = 1;
-+ break;
-+ }
-+ }
-+ txrx_printk(XRADIO_DBG_NIY, "[RX] PSPOLL: %s\n", drop ? "local" : "fwd");
-+done:
-+ return drop;
-+}
-+
-+
-+static void
-+xradio_rx_h_ba_stat(struct xradio_vif *priv,
-+ size_t hdrlen, size_t skb_len )
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_STA)
-+ return;
-+ if (!xradio_is_ht(&hw_priv->ht_oper))
-+ return;
-+ if (!priv->setbssparams_done)
-+ return;
-+
-+ spin_lock_bh(&hw_priv->ba_lock);
-+ hw_priv->ba_acc_rx += skb_len - hdrlen;
-+ if (!(hw_priv->ba_cnt_rx || hw_priv->ba_cnt)) {
-+ mod_timer(&hw_priv->ba_timer,
-+ jiffies + XRADIO_BLOCK_ACK_INTERVAL);
-+ }
-+ hw_priv->ba_cnt_rx++;
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+}
-+
-+void xradio_rx_cb(struct xradio_vif *priv,
-+ struct wsm_rx *arg,
-+ struct sk_buff **skb_p)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct sk_buff *skb = *skb_p;
-+ struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-+#endif
-+ struct xradio_link_entry *entry = NULL;
-+ unsigned long grace_period;
-+ bool early_data = false;
-+ size_t hdrlen = 0;
-+ u8 parse_iv_len = 0;
-+
-+ dev_dbg(hw_priv->pdev, "vif %d: rx, status %u flags 0x%.8x",
-+ priv->if_id, arg->status, arg->flags);
-+ if(ieee80211_is_deauth(frame->frame_control))
-+ dev_dbg(hw_priv->pdev, "vif %d: deauth\n", priv->if_id);
-+
-+ hdr->flag = 0;
-+
-+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
-+ /* STA is stopped. */
-+ goto drop;
-+ }
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ xradio_frame_monitor(hw_priv,skb,false);
-+#endif
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ if ((ieee80211_is_action(frame->frame_control))
-+ && (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) {
-+ u8 *action = (u8*)&mgmt->u.action.category;
-+ xradio_check_go_neg_conf_success_rx(hw_priv, action);
-+ }
-+#endif
-+
-+ if (arg->link_id && (arg->link_id != XRADIO_LINK_ID_UNMAPPED)
-+ && (arg->link_id <= XRADIO_MAX_STA_IN_AP_MODE)) {
-+ entry = &priv->link_id_db[arg->link_id - 1];
-+ if (entry->status == XRADIO_LINK_SOFT &&
-+ ieee80211_is_data(frame->frame_control))
-+ early_data = true;
-+ entry->timestamp = jiffies;
-+ }
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ else if ((arg->link_id == XRADIO_LINK_ID_UNMAPPED)
-+ && (priv->vif->p2p == WSM_START_MODE_P2P_GO)
-+ && ieee80211_is_action(frame->frame_control)
-+ && (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) {
-+ txrx_printk(XRADIO_DBG_NIY, "[RX] Going to MAP&RESET link ID\n");
-+
-+ if (work_pending(&priv->linkid_reset_work))
-+ WARN_ON(1);
-+
-+ memcpy(&priv->action_frame_sa[0],
-+ ieee80211_get_SA(frame), ETH_ALEN);
-+ priv->action_linkid = 0;
-+ schedule_work(&priv->linkid_reset_work);
-+ }
-+
-+ if (arg->link_id && (arg->link_id != XRADIO_LINK_ID_UNMAPPED)
-+ && (priv->vif->p2p == WSM_START_MODE_P2P_GO)
-+ && ieee80211_is_action(frame->frame_control)
-+ && (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) {
-+ /* Link ID already exists for the ACTION frame.
-+ * Reset and Remap */
-+ if (work_pending(&priv->linkid_reset_work))
-+ WARN_ON(1);
-+ memcpy(&priv->action_frame_sa[0],
-+ ieee80211_get_SA(frame), ETH_ALEN);
-+ priv->action_linkid = arg->link_id;
-+ schedule_work(&priv->linkid_reset_work);
-+ }
-+#endif
-+ if (unlikely(arg->status)) {
-+ if (arg->status == WSM_STATUS_MICFAILURE) {
-+ dev_err(priv->hw_priv->pdev, "[RX] IF=%d, MIC failure.\n",
-+ priv->if_id);
-+ hdr->flag |= RX_FLAG_MMIC_ERROR;
-+ } else if (arg->status == WSM_STATUS_NO_KEY_FOUND) {
-+ dev_warn(priv->hw_priv->pdev, "received frame has no key status\n");
-+ //goto drop;
-+ } else {
-+ dev_err(priv->hw_priv->pdev, "[RX] IF=%d, Receive failure: %d.\n",
-+ priv->if_id, arg->status);
-+ goto drop;
-+ }
-+ }
-+
-+ if (skb->len < sizeof(struct ieee80211_pspoll)) {
-+ dev_err(priv->hw_priv->pdev, "Malformed SDU rx'ed. "
-+ "Size is lesser than IEEE header.\n");
-+ goto drop;
-+ }
-+
-+ if (unlikely(ieee80211_is_pspoll(frame->frame_control)))
-+ if (xradio_handle_pspoll(priv, skb))
-+ goto drop;
-+
-+ hdr->mactime = 0; /* Not supported by WSM */
-+ hdr->band = (arg->channelNumber > 14) ?
-+ NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
-+ hdr->freq = ieee80211_channel_to_frequency(
-+ arg->channelNumber,
-+ hdr->band);
-+
-+#ifdef AP_HT_COMPAT_FIX
-+ if (!priv->ht_compat_det && priv->htcap &&
-+ ieee80211_is_data_qos(frame->frame_control)) {
-+ if(xradio_apcompat_detect(priv, arg->rxedRate))
-+ goto drop;
-+ }
-+#endif
-+
-+ if (arg->rxedRate >= 14) {
-+ hdr->encoding = RX_ENC_HT;
-+ hdr->rate_idx = arg->rxedRate - 14;
-+ } else if (arg->rxedRate >= 4) {
-+ if (hdr->band == NL80211_BAND_5GHZ)
-+ hdr->rate_idx = arg->rxedRate - 6;
-+ else
-+ hdr->rate_idx = arg->rxedRate - 2;
-+ } else {
-+ hdr->rate_idx = arg->rxedRate;
-+ }
-+
-+ hdr->signal = (s8)arg->rcpiRssi;
-+ hdr->antenna = 0;
-+
-+ hdrlen = ieee80211_hdrlen(frame->frame_control);
-+
-+ if (WSM_RX_STATUS_ENCRYPTION(arg->flags)) {
-+ size_t iv_len = 0, icv_len = 0;
-+
-+ hdr->flag |= RX_FLAG_DECRYPTED;
-+
-+ /* Oops... There is no fast way to ask mac80211 about
-+ * IV/ICV lengths. Even defines are not exposed.*/
-+ switch (WSM_RX_STATUS_ENCRYPTION(arg->flags)) {
-+ case WSM_RX_STATUS_WEP:
-+ iv_len = 4 /* WEP_IV_LEN */;
-+ icv_len = 4 /* WEP_ICV_LEN */;
-+ break;
-+ case WSM_RX_STATUS_TKIP:
-+ iv_len = 8 /* TKIP_IV_LEN */;
-+ icv_len = 4 /* TKIP_ICV_LEN */
-+ + 8 /*MICHAEL_MIC_LEN*/;
-+ break;
-+ case WSM_RX_STATUS_AES:
-+ iv_len = 8 /* CCMP_HDR_LEN */;
-+ icv_len = 8 /* CCMP_MIC_LEN */;
-+ break;
-+ case WSM_RX_STATUS_WAPI:
-+ iv_len = 18 /* WAPI_HDR_LEN */;
-+ icv_len = 16 /* WAPI_MIC_LEN */;
-+ hdr->flag |= RX_FLAG_IV_STRIPPED;
-+ break;
-+ default:
-+ WARN_ON("Unknown encryption type");
-+ goto drop;
-+ }
-+
-+ /* Firmware strips ICV in case of MIC failure. */
-+ if (arg->status == WSM_STATUS_MICFAILURE) {
-+ icv_len = 0;
-+ hdr->flag |= RX_FLAG_IV_STRIPPED;
-+ }
-+
-+ if (skb->len < hdrlen + iv_len + icv_len) {
-+ dev_err(priv->hw_priv->pdev, "Mailformed SDU rx'ed. "
-+ "Size is lesser than crypto headers.\n");
-+ goto drop;
-+ }
-+
-+ if (WSM_RX_STATUS_ENCRYPTION(arg->flags) ==
-+ WSM_RX_STATUS_TKIP) {
-+ /* Remove TKIP MIC 8 bytes*/
-+ memmove(skb->data + skb->len-icv_len,
-+ skb->data + skb->len-icv_len+8, 4);
-+ skb_trim(skb, skb->len - 8);
-+ hdr->flag |= RX_FLAG_MMIC_STRIPPED;
-+ } else if (unlikely(WSM_RX_STATUS_ENCRYPTION(arg->flags) ==
-+ WSM_RX_STATUS_WAPI)) {
-+ /* Protocols not defined in mac80211 should be
-+ stripped/crypted in driver/firmware */
-+ /* Remove IV, ICV and MIC */
-+ skb_trim(skb, skb->len - icv_len);
-+ memmove(skb->data + iv_len, skb->data, hdrlen);
-+ skb_pull(skb, iv_len);
-+ }
-+ parse_iv_len = iv_len;
-+ }
-+
-+ if (ieee80211_is_beacon(frame->frame_control) &&
-+ !arg->status &&
-+ !memcmp(ieee80211_get_SA(frame), priv->join_bssid,ETH_ALEN)) {
-+ const u8 *tim_ie;
-+ u8 *ies;
-+ size_t ies_len;
-+ priv->disable_beacon_filter = false;
-+ queue_work(hw_priv->workqueue, &priv->update_filtering_work);
-+ ies = ((struct ieee80211_mgmt *)
-+ (skb->data))->u.beacon.variable;
-+ ies_len = skb->len - (ies - (u8 *)(skb->data));
-+
-+ tim_ie = xradio_get_ie(ies, ies_len, WLAN_EID_TIM);
-+ if (tim_ie) {
-+ struct ieee80211_tim_ie *tim =
-+ (struct ieee80211_tim_ie *)&tim_ie[2];
-+
-+ if (priv->join_dtim_period != tim->dtim_period) {
-+ priv->join_dtim_period = tim->dtim_period;
-+ queue_work(hw_priv->workqueue,
-+ &priv->set_beacon_wakeup_period_work);
-+ }
-+ }
-+ if (unlikely(priv->disable_beacon_filter)) {
-+ priv->disable_beacon_filter = false;
-+ queue_work(hw_priv->workqueue,
-+ &priv->update_filtering_work);
-+ }
-+ }
-+#ifdef AP_HT_CAP_UPDATE
-+ if (priv->mode == NL80211_IFTYPE_AP &&
-+ ieee80211_is_beacon(frame->frame_control) &&
-+ ((priv->ht_oper&HT_INFO_MASK) != 0x0011) &&
-+ !arg->status){
-+ u8 *ies;
-+ size_t ies_len;
-+ const u8 *ht_cap;
-+ ies = ((struct ieee80211_mgmt *)(skb->data))->u.beacon.variable;
-+ ies_len = skb->len - (ies - (u8 *)(skb->data));
-+ ht_cap = xradio_get_ie(ies, ies_len, WLAN_EID_HT_CAPABILITY);
-+ if(!ht_cap) {
-+ priv->ht_oper |= 0x0011;
-+ queue_work(hw_priv->workqueue, &priv->ht_oper_update_work);
-+ }
-+ }
-+#endif
-+
-+#ifdef AP_HT_COMPAT_FIX
-+ if (ieee80211_is_mgmt(frame->frame_control) &&
-+ priv->if_id == 0 && !(priv->ht_compat_det & 0x10)) {
-+ xradio_remove_ht_ie(priv, skb);
-+ }
-+#endif
-+
-+#ifdef ROAM_OFFLOAD
-+ if ((ieee80211_is_beacon(frame->frame_control)||ieee80211_is_probe_resp(frame->frame_control)) &&
-+ !arg->status ) {
-+ if (hw_priv->auto_scanning && !atomic_read(&hw_priv->scan.in_progress))
-+ hw_priv->frame_rcvd = 1;
-+
-+ if (!memcmp(ieee80211_get_SA(frame), priv->join_bssid, ETH_ALEN)) {
-+ if (hw_priv->beacon)
-+ dev_kfree_skb(hw_priv->beacon);
-+ hw_priv->beacon = skb_copy(skb, GFP_ATOMIC);
-+ if (!hw_priv->beacon)
-+ txrx_printk(XRADIO_DBG_ERROR, "sched_scan: own beacon storing failed\n");
-+ }
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+
-+ //don't delay scan before next connect, yangfh.
-+ if (ieee80211_is_deauth(frame->frame_control) ||
-+ ieee80211_is_disassoc(frame->frame_control))
-+ hw_priv->connet_time[priv->if_id] = 0;
-+
-+ /* Stay awake for 1sec. after frame is received to give
-+ * userspace chance to react and acquire appropriate
-+ * wakelock. */
-+ if (ieee80211_is_auth(frame->frame_control))
-+ grace_period = 5 * HZ;
-+ else if (ieee80211_is_deauth(frame->frame_control))
-+ grace_period = 5 * HZ;
-+ else
-+ grace_period = HZ;
-+
-+ if (ieee80211_is_data(frame->frame_control))
-+ xradio_rx_h_ba_stat(priv, hdrlen, skb->len);
-+
-+ xradio_pm_stay_awake(&hw_priv->pm_state, grace_period);
-+
-+ if(xradio_realloc_resv_skb(hw_priv, *skb_p)) {
-+ *skb_p = NULL;
-+ return;
-+ }
-+ /* Try to a packet for the case dev_alloc_skb failed in bh.*/
-+ if (unlikely(early_data)) {
-+ spin_lock_bh(&priv->ps_state_lock);
-+ /* Double-check status with lock held */
-+ if (entry->status == XRADIO_LINK_SOFT) {
-+ skb_queue_tail(&entry->rx_queue, skb);
-+ dev_warn(priv->hw_priv->pdev, "***skb_queue_tail\n");
-+ } else
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ } else {
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+ *skb_p = NULL;
-+
-+ return;
-+
-+drop:
-+ dev_warn(priv->hw_priv->pdev, "dropped received frame\n");
-+ return;
-+}
-diff --git a/drivers/net/wireless/xradio/rx.h b/drivers/net/wireless/xradio/rx.h
-new file mode 100644
-index 0000000..0c02b23
---- /dev/null
-+++ b/drivers/net/wireless/xradio/rx.h
-@@ -0,0 +1,8 @@
-+#ifndef XRADIO_RX_H
-+#define XRADIO_RX_H
-+
-+void xradio_rx_cb(struct xradio_vif *priv,
-+ struct wsm_rx *arg,
-+ struct sk_buff **skb_p);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/scan.c b/drivers/net/wireless/xradio/scan.c
-new file mode 100644
-index 0000000..a8829c0
---- /dev/null
-+++ b/drivers/net/wireless/xradio/scan.c
-@@ -0,0 +1,897 @@
-+/*
-+ * Scan implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include "xradio.h"
-+#include "scan.h"
-+#include "sta.h"
-+#include "pm.h"
-+
-+static void xradio_scan_restart_delayed(struct xradio_vif *priv);
-+
-+static void xradio_remove_wps_p2p_ie(struct wsm_template_frame *frame)
-+{
-+ u8 *ies;
-+ u32 ies_len;
-+ u32 ie_len;
-+ u32 p2p_ie_len = 0;
-+ u32 wps_ie_len = 0;
-+
-+
-+ ies = &frame->skb->data[sizeof(struct ieee80211_hdr_3addr)];
-+ ies_len = frame->skb->len - sizeof(struct ieee80211_hdr_3addr);
-+ while (ies_len >= 6) {
-+ ie_len = ies[1] + 2;
-+ ies_len -= ie_len;
-+ if ((ies[0] == WLAN_EID_VENDOR_SPECIFIC) &&
-+ (ies[2] == 0x00 && ies[3] == 0x50 &&
-+ ies[4] == 0xf2 && ies[5] == 0x04)) {
-+ wps_ie_len = ie_len;
-+ memmove(ies, ies + ie_len, ies_len);
-+ } else if ((ies[0] == WLAN_EID_VENDOR_SPECIFIC) &&
-+ (ies[2] == 0x50 && ies[3] == 0x6f &&
-+ ies[4] == 0x9a && ies[5] == 0x09)) {
-+ p2p_ie_len = ie_len;
-+ memmove(ies, ies + ie_len, ies_len);
-+ } else {
-+ ies += ie_len;
-+ }
-+ }
-+
-+ if (p2p_ie_len || wps_ie_len) {
-+ skb_trim(frame->skb, frame->skb->len - (p2p_ie_len + wps_ie_len));
-+ }
-+}
-+
-+static int xradio_scan_start(struct xradio_vif *priv, struct wsm_scan *scan)
-+{
-+ int ret, i;
-+#ifdef FPGA_SETUP
-+ int tmo = 5000;
-+#else
-+ int tmo = 5000;
-+#endif
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+
-+ for (i = 0; i < scan->numOfChannels; ++i)
-+ tmo += scan->ch[i].maxChannelTime + 10;
-+
-+ atomic_set(&hw_priv->scan.in_progress, 1);
-+ atomic_set(&hw_priv->recent_scan, 1);
-+ xradio_pm_stay_awake(&hw_priv->pm_state, tmo * HZ / 1000);
-+ ret = wsm_scan(hw_priv, scan, priv->if_id);
-+ if (unlikely(ret)) {
-+ scan_printk(XRADIO_DBG_WARN, "%s,wsm_scan failed!\n", __func__);
-+ atomic_set(&hw_priv->scan.in_progress, 0);
-+ xradio_scan_restart_delayed(priv);
-+ } else {
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.timeout,
-+ tmo * HZ / 1000);
-+ }
-+ return ret;
-+}
-+
-+#ifdef ROAM_OFFLOAD
-+static int xradio_sched_scan_start(struct xradio_vif *priv, struct wsm_scan *scan)
-+{
-+ int ret;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+
-+ ret = wsm_scan(hw_priv, scan, priv->if_id);
-+ if (unlikely(ret)) {
-+ atomic_set(&hw_priv->scan.in_progress, 0);
-+ scan_printk(XRADIO_DBG_WARN,"%s,wsm_scan failed!\n", __func__);
-+ }
-+ return ret;
-+}
-+#endif /*ROAM_OFFLOAD*/
-+
-+int xradio_hw_scan(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_scan_request *hw_req)
-+{
-+ struct cfg80211_scan_request *req = &hw_req->req;
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
-+ };
-+ int i;
-+
-+ /* Scan when P2P_GO corrupt firmware MiniAP mode */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ scan_printk(XRADIO_DBG_WARN,"%s, can't scan in AP mode!\n", __func__);
-+ return -EOPNOTSUPP;
-+ }
-+
-+ if (hw_priv->bh_error) {
-+ scan_printk(XRADIO_DBG_NIY, "Ignoring scan bh error occur!\n");
-+ return -EBUSY;
-+ }
-+
-+ if (work_pending(&priv->offchannel_work) ||
-+ (hw_priv->roc_if_id != -1)) {
-+ scan_printk(XRADIO_DBG_WARN, "Offchannel work pending, "
-+ "ignoring scan work %d\n", hw_priv->roc_if_id);
-+ return -EBUSY;
-+ }
-+
-+ if (req->n_ssids == 1 && !req->ssids[0].ssid_len)
-+ req->n_ssids = 0;
-+
-+ scan_printk(XRADIO_DBG_NIY, "vif%d Scan request(%s-%dchs) for %d SSIDs.\n",
-+ priv->if_id, (req->channels[0]->band==NL80211_BAND_2GHZ)?"2.4G":"5G",
-+ req->n_channels, req->n_ssids);
-+
-+ /*delay multiple ssids scan of vif0 for 3s when connnetting to a node*/
-+ if(hw_priv->connet_time[0] > 0 && req->n_ssids == 0 && priv->if_id == 0) {
-+ long timeleft0 = hw_priv->connet_time[0] + SCAN_MAX_DELAY - jiffies;
-+ if(jiffies >= hw_priv->connet_time[0] && timeleft0 > 0) {
-+ scan_printk(XRADIO_DBG_NIY, "vif0 connetting, scan delay %ldms\n",
-+ timeleft0*1000/HZ);
-+ return -EBUSY;
-+ }
-+ hw_priv->connet_time[0] = 0;
-+ }
-+
-+ if (req->n_ssids > hw->wiphy->max_scan_ssids){
-+ scan_printk(XRADIO_DBG_ERROR, "%s: ssids is too much(%d)\n",
-+ __func__, req->n_ssids);
-+ return -EINVAL;
-+ }
-+
-+ /* TODO by Icenowy: so strange function call */
-+ frame.skb = ieee80211_probereq_get(hw, vif->addr, NULL, 0, 0);
-+ if (!frame.skb) {
-+ scan_printk(XRADIO_DBG_ERROR, "%s: ieee80211_probereq_get failed!\n",
-+ __func__);
-+ return -ENOMEM;
-+ }
-+
-+#ifdef ROAM_OFFLOAD
-+ if (priv->join_status != XRADIO_JOIN_STATUS_STA) {
-+ if (req->channels[0]->band == NL80211_BAND_2GHZ)
-+ hw_priv->num_scanchannels = 0;
-+ else
-+ hw_priv->num_scanchannels = hw_priv->num_2g_channels;
-+
-+ for (i=0; i < req->n_channels; i++) {
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].number = \
-+ req->channels[i]->hw_value;
-+ if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) {
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].minChannelTime = 50;
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].maxChannelTime = 110;
-+ }
-+ else {
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].minChannelTime = 10;
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].maxChannelTime = 40;
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].number |= \
-+ XRADIO_SCAN_TYPE_ACTIVE;
-+ }
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].txPowerLevel = \
-+ req->channels[i]->max_power;
-+ if (req->channels[0]->band == NL80211_BAND_5GHZ)
-+ hw_priv->scan_channels[hw_priv->num_scanchannels + i].number |= \
-+ XRADIO_SCAN_BAND_5G;
-+ }
-+ if (req->channels[0]->band == NL80211_BAND_2GHZ)
-+ hw_priv->num_2g_channels = req->n_channels;
-+ else
-+ hw_priv->num_5g_channels = req->n_channels;
-+ }
-+ hw_priv->num_scanchannels = hw_priv->num_2g_channels + hw_priv->num_5g_channels;
-+#endif /*ROAM_OFFLOAD*/
-+
-+ /* will be unlocked in xradio_scan_work() */
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ if (frame.skb) {
-+ int ret = 0;
-+ if (priv->if_id == 0)
-+ xradio_remove_wps_p2p_ie(&frame);
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ if (ret) {
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+ dev_kfree_skb(frame.skb);
-+ scan_printk(XRADIO_DBG_ERROR, "%s: wsm_set_template_frame failed: %d.\n",
-+ __func__, ret);
-+ return ret;
-+ }
-+ }
-+
-+ wsm_vif_lock_tx(priv);
-+
-+ BUG_ON(hw_priv->scan.req);
-+ hw_priv->scan.req = req;
-+ hw_priv->scan.n_ssids = 0;
-+ hw_priv->scan.status = 0;
-+ hw_priv->scan.begin = &req->channels[0];
-+ hw_priv->scan.curr = hw_priv->scan.begin;
-+ hw_priv->scan.end = &req->channels[req->n_channels];
-+ hw_priv->scan.output_power = hw_priv->output_power;
-+ hw_priv->scan.if_id = priv->if_id;
-+ /* TODO:COMBO: Populate BIT4 in scanflags to decide on which MAC
-+ * address the SCAN request will be sent */
-+
-+ for (i = 0; i < req->n_ssids; ++i) {
-+ struct wsm_ssid *dst = &hw_priv->scan.ssids[hw_priv->scan.n_ssids];
-+ BUG_ON(req->ssids[i].ssid_len > sizeof(dst->ssid));
-+ memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid));
-+ dst->length = req->ssids[i].ssid_len;
-+ ++hw_priv->scan.n_ssids;
-+ }
-+
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ if (frame.skb)
-+ dev_kfree_skb(frame.skb);
-+ queue_work(hw_priv->workqueue, &hw_priv->scan.work);
-+
-+ return 0;
-+}
-+
-+#ifdef ROAM_OFFLOAD
-+int xradio_hw_sched_scan_start(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct cfg80211_sched_scan_request *req,
-+ struct ieee80211_sched_scan_ies *ies)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
-+ };
-+ int i;
-+
-+
-+ scan_printk(XRADIO_DBG_WARN, "Scheduled scan request-->.\n");
-+ if (!priv->vif)
-+ return -EINVAL;
-+
-+ /* Scan when P2P_GO corrupt firmware MiniAP mode */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ scan_printk(XRADIO_DBG_WARN,"%s, can't scan in AP mode!\n", __func__);
-+ return -EOPNOTSUPP;
-+ }
-+
-+ scan_printk(XRADIO_DBG_WARN, "Scheduled scan: n_ssids %d, ssid[0].len = %d\n",
-+ req->n_ssids, req->ssids[0].ssid_len);
-+ if (req->n_ssids == 1 && !req->ssids[0].ssid_len)
-+ req->n_ssids = 0;
-+
-+ scan_printk(XRADIO_DBG_NIY, "[SCAN] Scan request for %d SSIDs.\n",
-+ req->n_ssids);
-+
-+ if (req->n_ssids > hw->wiphy->max_scan_ssids) [
-+ scan_printk(XRADIO_DBG_ERROR, "%s: ssids is too much(%d)\n",
-+ __func__, req->n_ssids);
-+ return -EINVAL;
-+ }
-+
-+ frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0,
-+ ies->ie[0], ies->len[0]);
-+ if (!frame.skb) {
-+ scan_printk(XRADIO_DBG_ERROR, "%s: ieee80211_probereq_get failed!\n",
-+ __func__);
-+ return -ENOMEM;
-+ }
-+
-+ /* will be unlocked in xradio_scan_work() */
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (frame.skb) {
-+ int ret;
-+ if (priv->if_id == 0)
-+ xradio_remove_wps_p2p_ie(&frame);
-+ ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
-+ if (0 == ret) {
-+ /* Host want to be the probe responder. */
-+ ret = wsm_set_probe_responder(priv, true);
-+ }
-+ if (ret) {
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+ dev_kfree_skb(frame.skb);
-+ scan_printk(XRADIO_DBG_ERROR, "%s: wsm_set_probe_responder failed: %d.\n",
-+ __func__, ret);
-+ return ret;
-+ }
-+ }
-+
-+ wsm_lock_tx(hw_priv);
-+ BUG_ON(hw_priv->scan.req);
-+ hw_priv->scan.sched_req = req;
-+ hw_priv->scan.n_ssids = 0;
-+ hw_priv->scan.status = 0;
-+ hw_priv->scan.begin = &req->channels[0];
-+ hw_priv->scan.curr = hw_priv->scan.begin;
-+ hw_priv->scan.end = &req->channels[req->n_channels];
-+ hw_priv->scan.output_power = hw_priv->output_power;
-+
-+ for (i = 0; i < req->n_ssids; ++i) {
-+ u8 j;
-+ struct wsm_ssid *dst = &hw_priv->scan.ssids[hw_priv->scan.n_ssids];
-+ BUG_ON(req->ssids[i].ssid_len > sizeof(dst->ssid));
-+ memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid));
-+ dst->length = req->ssids[i].ssid_len;
-+ ++hw_priv->scan.n_ssids;
-+ scan_printk(XRADIO_DBG_NIY, "SSID %d\n",i);
-+ for(j=0; jssids[i].ssid_len; j++)
-+ scan_printk(XRADIO_DBG_NIY, "0x%x\n", req->ssids[i].ssid[j]);
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ if (frame.skb)
-+ dev_kfree_skb(frame.skb);
-+ queue_work(hw_priv->workqueue, &hw_priv->scan.swork);
-+ scan_printk(XRADIO_DBG_NIY, "<-- Scheduled scan request.\n");
-+ return 0;
-+}
-+#endif /*ROAM_OFFLOAD*/
-+
-+void xradio_scan_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv = container_of(work,
-+ struct xradio_common,
-+ scan.work);
-+ struct xradio_vif *priv;
-+ struct ieee80211_channel **it;
-+ struct wsm_scan scan = {
-+ .scanType = WSM_SCAN_TYPE_FOREGROUND,
-+ .scanFlags = 0, /* TODO:COMBO */
-+ //.scanFlags = WSM_SCAN_FLAG_SPLIT_METHOD, /* TODO:COMBO */
-+ };
-+ bool first_run;
-+ int i;
-+ const u32 ProbeRequestTime = 2;
-+ const u32 ChannelRemainTime = 15;
-+ u32 maxChannelTime;
-+ struct cfg80211_scan_info scan_info;
-+
-+
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
-+
-+ /*TODO: COMBO: introduce locking so vif is not removed in meanwhile */
-+ if (!priv) {
-+ scan_printk(XRADIO_DBG_WARN, "interface removed, "
-+ "ignoring scan work\n");
-+ return;
-+ }
-+
-+ if (priv->if_id)
-+ scan.scanFlags |= WSM_FLAG_MAC_INSTANCE_1;
-+ else
-+ scan.scanFlags &= ~WSM_FLAG_MAC_INSTANCE_1;
-+
-+ /* No need to set WSM_SCAN_FLAG_FORCE_BACKGROUND in BSS_LOSS work.
-+ * yangfh 2015-11-11 18:45:02 */
-+ //xradio_for_each_vif(hw_priv, vif, i) {
-+ // if (!vif)
-+ // continue;
-+ // if (vif->bss_loss_status > XRADIO_BSS_LOSS_NONE)
-+ // scan.scanFlags |= WSM_SCAN_FLAG_FORCE_BACKGROUND;
-+ //}
-+
-+ first_run = (hw_priv->scan.begin == hw_priv->scan.curr &&
-+ hw_priv->scan.begin != hw_priv->scan.end);
-+ if (first_run) {
-+ /* Firmware gets crazy if scan request is sent
-+ * when STA is joined but not yet associated.
-+ * Force unjoin in this case. */
-+ if (cancel_delayed_work_sync(&priv->join_timeout) > 0)
-+ xradio_join_timeout(&priv->join_timeout.work);
-+ }
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (first_run) {
-+#if 0
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA &&
-+ !(priv->powersave_mode.pmMode & WSM_PSM_PS)) {
-+ struct wsm_set_pm pm = priv->powersave_mode;
-+ pm.pmMode = WSM_PSM_PS;
-+ xradio_set_pm(priv, &pm);
-+ } else
-+#endif
-+ if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR) {
-+ /* FW bug: driver has to restart p2p-dev mode
-+ * after scan */
-+ xradio_disable_listening(priv);
-+ }
-+ }
-+
-+ if (!hw_priv->scan.req || (hw_priv->scan.curr == hw_priv->scan.end)) {
-+ if (hw_priv->scan.output_power != hw_priv->output_power) {
-+ /* TODO:COMBO: Change when mac80211 implementation
-+ * is available for output power also */
-+ WARN_ON(wsm_set_output_power(hw_priv, hw_priv->output_power * 10,
-+ priv->if_id));
-+ }
-+
-+#if 0
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA &&
-+ !(priv->powersave_mode.pmMode & WSM_PSM_PS))
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+#endif
-+
-+ if (hw_priv->scan.status < 0)
-+ scan_printk(XRADIO_DBG_ERROR, "Scan failed (%d).\n", hw_priv->scan.status);
-+ else if (hw_priv->scan.req)
-+ scan_printk(XRADIO_DBG_NIY, "Scan completed.\n");
-+ else
-+ scan_printk(XRADIO_DBG_NIY, "Scan canceled.\n");
-+
-+ hw_priv->scan.req = NULL;
-+ xradio_scan_restart_delayed(priv);
-+ wsm_unlock_tx(hw_priv);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ memset(&scan_info, 0, sizeof(scan_info));
-+ scan_info.aborted = hw_priv->scan.status ? 1 : 0;
-+ ieee80211_scan_completed(hw_priv->hw, &scan_info);
-+ up(&hw_priv->scan.lock);
-+ return;
-+
-+ } else {
-+ struct ieee80211_channel *first = *hw_priv->scan.curr;
-+ for (it = hw_priv->scan.curr + 1, i = 1;
-+ it != hw_priv->scan.end && i < WSM_SCAN_MAX_NUM_OF_CHANNELS;
-+ ++it, ++i) {
-+ if ((*it)->band != first->band)
-+ break;
-+ if (((*it)->flags ^ first->flags) & IEEE80211_CHAN_NO_IR)
-+ break;
-+ if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
-+ (*it)->max_power != first->max_power)
-+ break;
-+ }
-+ scan.band = first->band;
-+
-+ if (hw_priv->scan.req->no_cck)
-+ scan.maxTransmitRate = WSM_TRANSMIT_RATE_6;
-+ else
-+ scan.maxTransmitRate = WSM_TRANSMIT_RATE_1;
-+
-+ /* TODO: Is it optimal? */
-+ scan.numOfProbeRequests = (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2;
-+
-+ scan.numOfSSIDs = hw_priv->scan.n_ssids;
-+ scan.ssids = &hw_priv->scan.ssids[0];
-+ scan.numOfChannels = it - hw_priv->scan.curr;
-+ /* TODO: Is it optimal? */
-+ scan.probeDelay = 100;
-+ /* It is not stated in WSM specification, however
-+ * FW team says that driver may not use FG scan
-+ * when joined. */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ scan.scanType = WSM_SCAN_TYPE_BACKGROUND;
-+ scan.scanFlags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
-+ }
-+ scan.ch = kzalloc(sizeof(struct wsm_scan_ch[it - hw_priv->scan.curr]), GFP_KERNEL);
-+ if (!scan.ch) {
-+ hw_priv->scan.status = -ENOMEM;
-+ scan_printk(XRADIO_DBG_ERROR, "xr_kzalloc wsm_scan_ch failed.\n");
-+ goto fail;
-+ }
-+ maxChannelTime = (scan.numOfSSIDs * scan.numOfProbeRequests *ProbeRequestTime) +
-+ ChannelRemainTime;
-+ maxChannelTime = (maxChannelTime < 35) ? 35 : maxChannelTime;
-+ for (i = 0; i < scan.numOfChannels; ++i) {
-+ scan.ch[i].number = hw_priv->scan.curr[i]->hw_value;
-+
-+
-+ if (hw_priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) {
-+ scan.ch[i].minChannelTime = 50;
-+ scan.ch[i].maxChannelTime = 110;
-+ } else {
-+ scan.ch[i].minChannelTime = 15;
-+ scan.ch[i].maxChannelTime = maxChannelTime;
-+ }
-+
-+
-+ }
-+
-+ if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
-+ hw_priv->scan.output_power != first->max_power) {
-+ hw_priv->scan.output_power = first->max_power;
-+ /* TODO:COMBO: Change after mac80211 implementation
-+ * complete */
-+ WARN_ON(wsm_set_output_power(hw_priv, hw_priv->scan.output_power * 10,
-+ priv->if_id));
-+ }
-+
-+ down(&hw_priv->scan.status_lock);
-+ hw_priv->scan.status = xradio_scan_start(priv, &scan);
-+
-+ kfree(scan.ch);
-+ if (WARN_ON(hw_priv->scan.status)) {
-+ scan_printk(XRADIO_DBG_ERROR, "scan failed, status=%d.\n",
-+ hw_priv->scan.status);
-+ up(&hw_priv->scan.status_lock);
-+ goto fail;
-+ }
-+ up(&hw_priv->scan.status_lock);
-+ hw_priv->scan.curr = it;
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return;
-+
-+fail:
-+ hw_priv->scan.curr = hw_priv->scan.end;
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ queue_work(hw_priv->workqueue, &hw_priv->scan.work);
-+ return;
-+}
-+
-+#ifdef ROAM_OFFLOAD
-+void xradio_sched_scan_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv = container_of(work, struct xradio_common,
-+ scan.swork);
-+ struct wsm_scan scan;
-+ struct wsm_ssid scan_ssid;
-+ int i;
-+ struct xradio_vif *priv = NULL;
-+
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
-+ if (unlikely(!priv)) {
-+ WARN_ON(1);
-+ return;
-+ }
-+
-+ spin_unlock(&priv->vif_lock);
-+ /* Firmware gets crazy if scan request is sent
-+ * when STA is joined but not yet associated.
-+ * Force unjoin in this case. */
-+ if (cancel_delayed_work_sync(&priv->join_timeout) > 0) {
-+ xradio_join_timeout(&priv->join_timeout.work);
-+ }
-+ mutex_lock(&hw_priv->conf_mutex);
-+ hw_priv->auto_scanning = 1;
-+ scan.band = 0;
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA)
-+ scan.scanType = 3; /* auto background */
-+ else
-+ scan.scanType = 2; /* auto foreground */
-+
-+ scan.scanFlags = 0x01; /* bit 0 set => forced background scan */
-+ scan.maxTransmitRate = WSM_TRANSMIT_RATE_6;
-+ scan.autoScanInterval = (0xba << 24)|(30 * 1024); /* 30 seconds, -70 rssi */
-+ scan.numOfProbeRequests = 1;
-+ //scan.numOfChannels = 11;
-+ scan.numOfChannels = hw_priv->num_scanchannels;
-+ scan.numOfSSIDs = 1;
-+ scan.probeDelay = 100;
-+ scan_ssid.length = priv->ssid_length;
-+ memcpy(scan_ssid.ssid, priv->ssid, priv->ssid_length);
-+ scan.ssids = &scan_ssid;
-+
-+ scan.ch = xr_kzalloc(sizeof(struct wsm_scan_ch[scan.numOfChannels]), false);
-+ if (!scan.ch) {
-+ scan_printk(XRADIO_DBG_ERROR, "xr_kzalloc wsm_scan_ch failed.\n");
-+ hw_priv->scan.status = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ for (i = 0; i < scan.numOfChannels; i++) {
-+ scan.ch[i].number = hw_priv->scan_channels[i].number;
-+ scan.ch[i].minChannelTime = hw_priv->scan_channels[i].minChannelTime;
-+ scan.ch[i].maxChannelTime = hw_priv->scan_channels[i].maxChannelTime;
-+ scan.ch[i].txPowerLevel = hw_priv->scan_channels[i].txPowerLevel;
-+ }
-+
-+#if 0
-+ for (i = 1; i <= scan.numOfChannels; i++) {
-+ scan.ch[i-1].number = i;
-+ scan.ch[i-1].minChannelTime = 10;
-+ scan.ch[i-1].maxChannelTime = 40;
-+ }
-+#endif
-+
-+ hw_priv->scan.status = xradio_sched_scan_start(priv, &scan);
-+ kfree(scan.ch);
-+ if (hw_priv->scan.status) {
-+ scan_printk(XRADIO_DBG_ERROR, "scan failed, status=%d.\n",
-+ hw_priv->scan.status);
-+ goto fail;
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return;
-+
-+fail:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ queue_work(hw_priv->workqueue, &hw_priv->scan.swork);
-+ return;
-+}
-+
-+void xradio_hw_sched_scan_stop(struct xradio_common *hw_priv)
-+{
-+ struct xradio_vif *priv = NULL;
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv,hw_priv->scan.if_id);
-+ if (unlikely(!priv))
-+ return;
-+
-+ spin_unlock(&priv->vif_lock);
-+ wsm_stop_scan(hw_priv, priv->if_id);
-+
-+ return;
-+}
-+#endif /*ROAM_OFFLOAD*/
-+
-+
-+static void xradio_scan_restart_delayed(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+
-+ if (priv->delayed_link_loss) {
-+ int tmo = hw_priv->scan.direct_probe ? 0 : priv->cqm_beacon_loss_count;
-+
-+ priv->delayed_link_loss = 0;
-+ /* Restart beacon loss timer and requeue
-+ BSS loss work. */
-+ scan_printk(XRADIO_DBG_WARN, "[CQM] Requeue BSS loss in %d "
-+ "beacons.\n", tmo);
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ queue_delayed_work(hw_priv->workqueue, &priv->bss_loss_work,
-+ tmo * HZ / 10);
-+
-+ }
-+
-+ /* FW bug: driver has to restart p2p-dev mode after scan. */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR) {
-+ /*xradio_enable_listening(priv);*/
-+ WARN_ON(1);
-+ xradio_update_filtering(priv);
-+ scan_printk(XRADIO_DBG_WARN, "driver has to restart "
-+ "p2p-dev mode after scan");
-+ }
-+
-+ if (atomic_xchg(&priv->delayed_unjoin, 0)) {
-+ if (queue_work(hw_priv->workqueue, &priv->unjoin_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+}
-+
-+static void xradio_scan_complete(struct xradio_common *hw_priv, int if_id)
-+{
-+ struct xradio_vif *priv;
-+ atomic_xchg(&hw_priv->recent_scan, 0);
-+
-+
-+ if (hw_priv->scan.direct_probe) {
-+ mutex_lock(&hw_priv->conf_mutex);
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, if_id);
-+ if (priv) {
-+ scan_printk(XRADIO_DBG_MSG, "Direct probe complete.\n");
-+ xradio_scan_restart_delayed(priv);
-+ } else {
-+ scan_printk(XRADIO_DBG_MSG, "Direct probe complete without interface!\n");
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ hw_priv->scan.direct_probe = 0;
-+ up(&hw_priv->scan.lock);
-+ wsm_unlock_tx(hw_priv);
-+ } else {
-+ xradio_scan_work(&hw_priv->scan.work);
-+ }
-+}
-+
-+void xradio_scan_complete_cb(struct xradio_common *hw_priv,
-+ struct wsm_scan_complete *arg)
-+{
-+ struct xradio_vif *priv = xrwl_hwpriv_to_vifpriv(hw_priv,
-+ hw_priv->scan.if_id);
-+
-+
-+ if (unlikely(!priv))
-+ return;
-+
-+#ifdef ROAM_OFFLOAD
-+ if (hw_priv->auto_scanning)
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.timeout, 0);
-+#endif /*ROAM_OFFLOAD*/
-+
-+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
-+ /* STA is stopped. */
-+ spin_unlock(&priv->vif_lock);
-+ scan_printk(XRADIO_DBG_WARN, "%s: priv->mode UNSPECIFIED.\n", __func__);
-+ return;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+
-+ /*
-+ if(hw_priv->scan.status == -ETIMEDOUT)
-+ scan_printk(XRADIO_DBG_WARN, "Scan timeout already occured. "
-+ "Don't cancel work");
-+ if ((hw_priv->scan.status != -ETIMEDOUT) &&
-+ (cancel_delayed_work_sync(&hw_priv->scan.timeout) > 0)) {
-+ hw_priv->scan.status = 1;
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.timeout, 0);
-+ }
-+ */ // should not involve status as a condition
-+
-+ if (cancel_delayed_work_sync(&hw_priv->scan.timeout) > 0) {
-+ down(&hw_priv->scan.status_lock);
-+ hw_priv->scan.status = 1;
-+ up(&hw_priv->scan.status_lock);
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.timeout, 0);
-+ }
-+}
-+
-+void xradio_scan_timeout(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, scan.timeout.work);
-+
-+
-+ if (likely(atomic_xchg(&hw_priv->scan.in_progress, 0))) {
-+ if (hw_priv->scan.status > 0)
-+ hw_priv->scan.status = 0;
-+ else if (!hw_priv->scan.status) {
-+ scan_printk(XRADIO_DBG_WARN, "Timeout waiting for scan "
-+ "complete notification.\n");
-+ hw_priv->scan.status = -ETIMEDOUT;
-+ hw_priv->scan.curr = hw_priv->scan.end;
-+ WARN_ON(wsm_stop_scan(hw_priv, hw_priv->scan.if_id ? 1 : 0));
-+ }
-+ xradio_scan_complete(hw_priv, hw_priv->scan.if_id);
-+#ifdef ROAM_OFFLOAD
-+ } else if (hw_priv->auto_scanning) {
-+ hw_priv->auto_scanning = 0;
-+ ieee80211_sched_scan_results(hw_priv->hw);
-+#endif /*ROAM_OFFLOAD*/
-+ }
-+}
-+
-+void xradio_probe_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, scan.probe_work.work);
-+ struct xradio_vif *priv;
-+ u8 queueId = xradio_queue_get_queue_id(hw_priv->pending_frame_id);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queueId];
-+ const struct xradio_txpriv *txpriv;
-+ struct wsm_tx *wsm;
-+ struct wsm_template_frame frame = {
-+ .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
-+ };
-+ struct wsm_ssid ssids[1] = {{
-+ .length = 0,
-+ } };
-+ struct wsm_scan_ch ch[1] = {{
-+ .minChannelTime = 0,
-+ .maxChannelTime = 10,
-+ } };
-+ struct wsm_scan scan = {
-+ .scanType = WSM_SCAN_TYPE_FOREGROUND,
-+ .numOfProbeRequests = 1,
-+ .probeDelay = 0,
-+ .numOfChannels = 1,
-+ .ssids = ssids,
-+ .ch = ch,
-+ };
-+ u8 *ies;
-+ size_t ies_len;
-+ int ret = 1;
-+ scan_printk(XRADIO_DBG_MSG, "%s:Direct probe.\n", __func__);
-+
-+ BUG_ON(queueId >= 4);
-+ BUG_ON(!hw_priv->channel);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (unlikely(down_trylock(&hw_priv->scan.lock))) {
-+ /* Scan is already in progress. Requeue self. */
-+ schedule();
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->scan.probe_work,
-+ HZ / 10);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return;
-+ }
-+
-+ if (xradio_queue_get_skb(queue, hw_priv->pending_frame_id, &frame.skb, &txpriv)) {
-+ up(&hw_priv->scan.lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ wsm_unlock_tx(hw_priv);
-+ scan_printk(XRADIO_DBG_ERROR, "%s:xradio_queue_get_skb error!\n", __func__);
-+ return;
-+ }
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, txpriv->if_id);
-+ if (!priv) {
-+ up(&hw_priv->scan.lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ scan_printk(XRADIO_DBG_ERROR, "%s:priv error!\n", __func__);
-+ return;
-+ }
-+ wsm = (struct wsm_tx *)frame.skb->data;
-+ scan.maxTransmitRate = wsm->maxTxRate;
-+ scan.band = (hw_priv->channel->band == NL80211_BAND_5GHZ) ?
-+ WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ scan.scanType = WSM_SCAN_TYPE_BACKGROUND;
-+ scan.scanFlags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
-+ if (priv->if_id)
-+ scan.scanFlags |= WSM_FLAG_MAC_INSTANCE_1;
-+ else
-+ scan.scanFlags &= ~WSM_FLAG_MAC_INSTANCE_1;
-+ }
-+
-+ /* No need to set WSM_SCAN_FLAG_FORCE_BACKGROUND in BSS_LOSS work.
-+ * yangfh 2015-11-11 18:45:02 */
-+ //xradio_for_each_vif(hw_priv, vif, i) {
-+ // if (!vif)
-+ // continue;
-+ // if (vif->bss_loss_status > XRADIO_BSS_LOSS_NONE)
-+ // scan.scanFlags |= WSM_SCAN_FLAG_FORCE_BACKGROUND;
-+ //}
-+
-+ ch[0].number = hw_priv->channel->hw_value;
-+ skb_pull(frame.skb, txpriv->offset);
-+ ies = &frame.skb->data[sizeof(struct ieee80211_hdr_3addr)];
-+ ies_len = frame.skb->len - sizeof(struct ieee80211_hdr_3addr);
-+
-+ if (ies_len) {
-+ u8 *ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
-+ if (ssidie && ssidie[1] && ssidie[1] <= sizeof(ssids[0].ssid)) {
-+ u8 *nextie = &ssidie[2 + ssidie[1]];
-+ /* Remove SSID from the IE list. It has to be provided
-+ * as a separate argument in xradio_scan_start call */
-+
-+ /* Store SSID localy */
-+ ssids[0].length = ssidie[1];
-+ memcpy(ssids[0].ssid, &ssidie[2], ssids[0].length);
-+ scan.numOfSSIDs = 1;
-+
-+ /* Remove SSID from IE list */
-+ ssidie[1] = 0;
-+ memmove(&ssidie[2], nextie, &ies[ies_len] - nextie);
-+ skb_trim(frame.skb, frame.skb->len - ssids[0].length);
-+ }
-+ }
-+
-+ if (priv->if_id == 0)
-+ xradio_remove_wps_p2p_ie(&frame);
-+
-+ /* FW bug: driver has to restart p2p-dev mode after scan */
-+ if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR) {
-+ WARN_ON(1);
-+ /*xradio_disable_listening(priv);*/
-+ }
-+ ret = WARN_ON(wsm_set_template_frame(hw_priv, &frame,
-+ priv->if_id));
-+
-+ hw_priv->scan.direct_probe = 1;
-+ hw_priv->scan.if_id = priv->if_id;
-+ if (!ret) {
-+ wsm_flush_tx(hw_priv);
-+ ret = WARN_ON(xradio_scan_start(priv, &scan));
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ skb_push(frame.skb, txpriv->offset);
-+ if (!ret)
-+ IEEE80211_SKB_CB(frame.skb)->flags |= IEEE80211_TX_STAT_ACK;
-+
-+ BUG_ON(xradio_queue_remove(queue, hw_priv->pending_frame_id));
-+
-+ if (ret) {
-+ hw_priv->scan.direct_probe = 0;
-+ up(&hw_priv->scan.lock);
-+ wsm_unlock_tx(hw_priv);
-+ }
-+
-+ return;
-+}
-diff --git a/drivers/net/wireless/xradio/scan.h b/drivers/net/wireless/xradio/scan.h
-new file mode 100644
-index 0000000..5c520ed
---- /dev/null
-+++ b/drivers/net/wireless/xradio/scan.h
-@@ -0,0 +1,71 @@
-+/*
-+ * Scan interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#ifndef SCAN_H_INCLUDED
-+#define SCAN_H_INCLUDED
-+
-+#include
-+#include "wsm.h"
-+
-+/* external */ struct sk_buff;
-+/* external */ struct cfg80211_scan_request;
-+/* external */ struct ieee80211_channel;
-+/* external */ struct ieee80211_hw;
-+/* external */ struct work_struct;
-+
-+#define SCAN_MAX_DELAY (3*HZ) //3s, add by yangfh for connect
-+
-+struct xradio_scan {
-+ struct semaphore lock;
-+ struct work_struct work;
-+#ifdef ROAM_OFFLOAD
-+ struct work_struct swork; /* scheduled scan work */
-+ struct cfg80211_sched_scan_request *sched_req;
-+#endif /*ROAM_OFFLOAD*/
-+ struct delayed_work timeout;
-+ struct cfg80211_scan_request *req;
-+ struct ieee80211_channel **begin;
-+ struct ieee80211_channel **curr;
-+ struct ieee80211_channel **end;
-+ struct wsm_ssid ssids[WSM_SCAN_MAX_NUM_OF_SSIDS];
-+ int output_power;
-+ int n_ssids;
-+ //add by liwei, for h64 ping WS550 BUG
-+ struct semaphore status_lock;
-+ int status;
-+ atomic_t in_progress;
-+ /* Direct probe requests workaround */
-+ struct delayed_work probe_work;
-+ int direct_probe;
-+ u8 if_id;
-+};
-+
-+int xradio_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_scan_request *req);
-+#ifdef ROAM_OFFLOAD
-+int xradio_hw_sched_scan_start(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct cfg80211_sched_scan_request *req,
-+ struct ieee80211_sched_scan_ies *ies);
-+void xradio_hw_sched_scan_stop(struct xradio_common *priv);
-+void xradio_sched_scan_work(struct work_struct *work);
-+#endif /*ROAM_OFFLOAD*/
-+void xradio_scan_work(struct work_struct *work);
-+void xradio_scan_timeout(struct work_struct *work);
-+void xradio_scan_complete_cb(struct xradio_common *priv,
-+ struct wsm_scan_complete *arg);
-+
-+/* ******************************************************************** */
-+/* Raw probe requests TX workaround */
-+void xradio_probe_work(struct work_struct *work);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/sdio.c b/drivers/net/wireless/xradio/sdio.c
-new file mode 100644
-index 0000000..13d4eb5
---- /dev/null
-+++ b/drivers/net/wireless/xradio/sdio.c
-@@ -0,0 +1,246 @@
-+/*
-+ * SDIO driver for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "sdio.h"
-+#include "main.h"
-+
-+/* sdio vendor id and device id*/
-+#define SDIO_VENDOR_ID_XRADIO 0x0020
-+#define SDIO_DEVICE_ID_XRADIO 0x2281
-+static const struct sdio_device_id xradio_sdio_ids[] = {
-+ { SDIO_DEVICE(SDIO_VENDOR_ID_XRADIO, SDIO_DEVICE_ID_XRADIO) },
-+ //{ SDIO_DEVICE(SDIO_ANY_ID, SDIO_ANY_ID) },
-+ { /* end: all zeroes */ },
-+};
-+
-+/* sbus_ops implemetation */
-+int sdio_data_read(struct xradio_common* self, unsigned int addr,
-+ void *dst, int count)
-+{
-+ int ret = sdio_memcpy_fromio(self->sdio_func, dst, addr, count);
-+// printk("sdio_memcpy_fromio 0x%x:%d ret %d\n", addr, count, ret);
-+// print_hex_dump_bytes("sdio read ", 0, dst, min(count,32));
-+ return ret;
-+}
-+
-+int sdio_data_write(struct xradio_common* self, unsigned int addr,
-+ const void *src, int count)
-+{
-+ int ret = sdio_memcpy_toio(self->sdio_func, addr, (void *)src, count);
-+// printk("sdio_memcpy_toio 0x%x:%d ret %d\n", addr, count, ret);
-+// print_hex_dump_bytes("sdio write", 0, src, min(count,32));
-+ return ret;
-+}
-+
-+void sdio_lock(struct xradio_common* self)
-+{
-+ sdio_claim_host(self->sdio_func);
-+}
-+
-+void sdio_unlock(struct xradio_common *self)
-+{
-+ sdio_release_host(self->sdio_func);
-+}
-+
-+size_t sdio_align_len(struct xradio_common *self, size_t size)
-+{
-+ return sdio_align_size(self->sdio_func, size);
-+}
-+
-+int sdio_set_blk_size(struct xradio_common *self, size_t size)
-+{
-+ return sdio_set_block_size(self->sdio_func, size);
-+}
-+
-+extern void xradio_irq_handler(struct xradio_common*);
-+
-+static irqreturn_t sdio_irq_handler(int irq, void *dev_id)
-+{
-+ struct sdio_func *func = (struct sdio_func*) dev_id;
-+ struct xradio_common *self = sdio_get_drvdata(func);
-+ if (self != NULL)
-+ xradio_irq_handler(self);
-+ return IRQ_HANDLED;
-+}
-+
-+static int sdio_enableint(struct sdio_func* func)
-+{
-+ int ret = 0;
-+ u8 cccr;
-+ int func_num;
-+
-+ sdio_claim_host(func);
-+
-+ /* Hack to access Fuction-0 */
-+ func_num = func->num;
-+ func->num = 0;
-+ cccr = sdio_readb(func, SDIO_CCCR_IENx, &ret);
-+ cccr |= BIT(0); /* Master interrupt enable ... */
-+ cccr |= BIT(func_num); /* ... for our function */
-+ sdio_writeb(func, cccr, SDIO_CCCR_IENx, &ret);
-+
-+ /* Restore the WLAN function number */
-+ func->num = func_num;
-+
-+ sdio_release_host(func);
-+
-+ return ret;
-+}
-+
-+int sdio_pm(struct xradio_common *self, bool suspend)
-+{
-+ int ret = 0;
-+ if (suspend) {
-+ /* Notify SDIO that XRADIO will remain powered during suspend */
-+ ret = sdio_set_host_pm_flags(self->sdio_func, MMC_PM_KEEP_POWER);
-+ if (ret)
-+ dev_dbg(&self->sdio_func->dev, "Error setting SDIO pm flags: %i\n", ret);
-+ }
-+
-+ return ret;
-+}
-+
-+static const struct of_device_id xradio_sdio_of_match_table[] = {
-+ { .compatible = "xradio,xr819" },
-+ { }
-+};
-+
-+static int xradio_probe_of(struct sdio_func *func)
-+{
-+ struct device *dev = &func->dev;
-+ struct device_node *np = dev->of_node;
-+ const struct of_device_id *of_id;
-+ int irq;
-+ int ret;
-+
-+ of_id = of_match_node(xradio_sdio_of_match_table, np);
-+ if (!of_id)
-+ return -ENODEV;
-+
-+ //pdev_data->family = of_id->data;
-+
-+ irq = irq_of_parse_and_map(np, 0);
-+ if (!irq) {
-+ dev_err(dev, "No irq in platform data\n");
-+ return -EINVAL;
-+ }
-+
-+ ret = devm_request_irq(dev, irq, sdio_irq_handler, 0, "xradio", func);
-+ if (ret) {
-+ dev_err(dev, "Failed to request irq_wakeup.\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Probe Function to be called by SDIO stack when device is discovered */
-+static int sdio_probe(struct sdio_func *func,
-+ const struct sdio_device_id *id)
-+{
-+ dev_dbg(&func->dev, "XRadio Device:sdio clk=%d\n",
-+ func->card->host->ios.clock);
-+ dev_dbg(&func->dev, "sdio func->class=%x\n", func->class);
-+ dev_dbg(&func->dev, "sdio_vendor: 0x%04x\n", func->vendor);
-+ dev_dbg(&func->dev, "sdio_device: 0x%04x\n", func->device);
-+ dev_dbg(&func->dev, "Function#: 0x%04x\n", func->num);
-+
-+#if 0 //for odly and sdly debug.
-+{
-+ u32 sdio_param = 0;
-+ sdio_param = readl(__io_address(0x01c20088));
-+ sdio_param &= ~(0xf<<8);
-+ sdio_param |= 3<<8;
-+ sdio_param &= ~(0xf<<20);
-+ sdio_param |= s_dly<<20;
-+ writel(sdio_param, __io_address(0x01c20088));
-+ sbus_printk(XRADIO_DBG_ALWY, "%s: 0x01c20088=0x%08x\n", __func__, sdio_param);
-+}
-+#endif
-+
-+ xradio_probe_of(func);
-+
-+ func->card->quirks |= MMC_QUIRK_BROKEN_BYTE_MODE_512;
-+ sdio_claim_host(func);
-+ sdio_enable_func(func);
-+ sdio_release_host(func);
-+
-+ sdio_enableint(func);
-+
-+ xradio_core_init(func);
-+
-+ try_module_get(func->dev.driver->owner);
-+ return 0;
-+}
-+/* Disconnect Function to be called by SDIO stack when
-+ * device is disconnected */
-+static void sdio_remove(struct sdio_func *func)
-+{
-+ sdio_claim_host(func);
-+ sdio_disable_func(func);
-+ sdio_release_host(func);
-+ module_put(func->dev.driver->owner);
-+}
-+
-+static int sdio_suspend(struct device *dev)
-+{
-+ int ret = 0;
-+ /*
-+ struct sdio_func *func = dev_to_sdio_func(dev);
-+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
-+ if (ret)
-+ sbus_printk(XRADIO_DBG_ERROR, "set MMC_PM_KEEP_POWER error\n");
-+ */
-+ return ret;
-+}
-+
-+static int sdio_resume(struct device *dev)
-+{
-+ return 0;
-+}
-+
-+static const struct dev_pm_ops sdio_pm_ops = {
-+ .suspend = sdio_suspend,
-+ .resume = sdio_resume,
-+};
-+
-+static struct sdio_driver sdio_driver = {
-+ .name = "xradio_wlan",
-+ .id_table = xradio_sdio_ids,
-+ .probe = sdio_probe,
-+ .remove = sdio_remove,
-+ .drv = {
-+ .owner = THIS_MODULE,
-+ .pm = &sdio_pm_ops,
-+ }
-+};
-+
-+
-+int xradio_sdio_register(){
-+ return sdio_register_driver(&sdio_driver);
-+}
-+
-+void xradio_sdio_unregister(){
-+ sdio_unregister_driver(&sdio_driver);
-+}
-+
-+MODULE_DEVICE_TABLE(sdio, xradio_sdio_ids);
-diff --git a/drivers/net/wireless/xradio/sdio.h b/drivers/net/wireless/xradio/sdio.h
-new file mode 100644
-index 0000000..ea3c45a
---- /dev/null
-+++ b/drivers/net/wireless/xradio/sdio.h
-@@ -0,0 +1,17 @@
-+#ifndef __XRADIO_SDIO_H
-+#define __XRADIO_SDIO_H
-+
-+size_t sdio_align_len(struct xradio_common *self, size_t size);
-+void sdio_lock(struct xradio_common *self);
-+void sdio_unlock(struct xradio_common *self);
-+int sdio_set_blk_size(struct xradio_common *self, size_t size);
-+int sdio_data_read(struct xradio_common *self, unsigned int addr, void *dst,
-+ int count);
-+int sdio_data_write(struct xradio_common *self, unsigned int addr, const void *src,
-+ int count);
-+int sdio_pm(struct xradio_common *self, bool suspend);
-+
-+int xradio_sdio_register(void);
-+void xradio_sdio_unregister(void);
-+
-+#endif
-diff --git a/drivers/net/wireless/xradio/sta.c b/drivers/net/wireless/xradio/sta.c
-new file mode 100644
-index 0000000..5e9d8a2
---- /dev/null
-+++ b/drivers/net/wireless/xradio/sta.c
-@@ -0,0 +1,2199 @@
-+/*
-+ * STA APIs for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "sta.h"
-+#include "ap.h"
-+#include "keys.h"
-+#include "fwio.h"
-+#include "bh.h"
-+#include "wsm.h"
-+#ifdef ROAM_OFFLOAD
-+#include
-+#endif /*ROAM_OFFLOAD*/
-+
-+#include "net/mac80211.h"
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+#include
-+#endif
-+
-+#define WEP_ENCRYPT_HDR_SIZE 4
-+#define WEP_ENCRYPT_TAIL_SIZE 4
-+#define WPA_ENCRYPT_HDR_SIZE 8
-+#define WPA_ENCRYPT_TAIL_SIZE 12
-+#define WPA2_ENCRYPT_HDR_SIZE 8
-+#define WPA2_ENCRYPT_TAIL_SIZE 8
-+#define WAPI_ENCRYPT_HDR_SIZE 18
-+#define WAPI_ENCRYPT_TAIL_SIZE 16
-+#define MAX_ARP_REPLY_TEMPLATE_SIZE 120
-+
-+static inline void __xradio_free_event_queue(struct list_head *list)
-+{
-+ while (!list_empty(list)) {
-+ struct xradio_wsm_event *event =
-+ list_first_entry(list, struct xradio_wsm_event,link);
-+ list_del(&event->link);
-+ kfree(event);
-+ }
-+}
-+
-+static inline void __xradio_bf_configure(struct xradio_vif *priv)
-+{
-+ priv->bf_table.numOfIEs = __cpu_to_le32(3);
-+ priv->bf_table.entry[0].ieId = WLAN_EID_VENDOR_SPECIFIC;
-+ priv->bf_table.entry[0].actionFlags =
-+ WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED;
-+
-+ priv->bf_table.entry[0].oui[0] = 0x50;
-+ priv->bf_table.entry[0].oui[1] = 0x6F;
-+ priv->bf_table.entry[0].oui[2] = 0x9A;
-+
-+ priv->bf_table.entry[1].ieId = WLAN_EID_ERP_INFO;
-+ priv->bf_table.entry[1].actionFlags =
-+ WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED;
-+
-+ priv->bf_table.entry[2].ieId = WLAN_EID_HT_OPERATION;
-+ priv->bf_table.entry[2].actionFlags =
-+ WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED;
-+
-+ priv->bf_control.enabled = WSM_BEACON_FILTER_ENABLE;
-+}
-+
-+/* ******************************************************************** */
-+/* STA API */
-+
-+int xradio_start(struct ieee80211_hw *dev)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ int ret = 0;
-+
-+
-+ if (wait_event_interruptible_timeout(hw_priv->wsm_startup_done,
-+ hw_priv->driver_ready, 3*HZ) <= 0) {
-+ wiphy_err(dev->wiphy, "driver is not ready!\n");
-+ return -ETIMEDOUT;
-+ }
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ memcpy(hw_priv->mac_addr, dev->wiphy->perm_addr, ETH_ALEN);
-+ hw_priv->softled_state = 0;
-+
-+ ret = xradio_setup_mac(hw_priv);
-+ if (WARN_ON(ret)) {
-+ wiphy_err(dev->wiphy, "xradio_setup_mac failed(%d)\n", ret);
-+ goto out;
-+ }
-+
-+out:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return ret;
-+}
-+
-+void xradio_stop(struct ieee80211_hw *dev)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = NULL;
-+ LIST_HEAD(list);
-+ int i;
-+
-+ wsm_lock_tx(hw_priv);
-+ while (down_trylock(&hw_priv->scan.lock)) {
-+ /* Scan is in progress. Force it to stop. */
-+ hw_priv->scan.req = NULL;
-+ schedule();
-+ }
-+ up(&hw_priv->scan.lock);
-+
-+ cancel_delayed_work_sync(&hw_priv->scan.probe_work);
-+ cancel_delayed_work_sync(&hw_priv->scan.timeout);
-+ flush_workqueue(hw_priv->workqueue);
-+ del_timer_sync(&hw_priv->ba_timer);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ hw_priv->softled_state = 0;
-+ /* xradio_set_leds(hw_priv); */
-+
-+ spin_lock(&hw_priv->event_queue_lock);
-+ list_splice_init(&hw_priv->event_queue, &list);
-+ spin_unlock(&hw_priv->event_queue_lock);
-+ __xradio_free_event_queue(&list);
-+
-+ for (i = 0; i < 4; i++)
-+ xradio_queue_clear(&hw_priv->tx_queue[i], XRWL_ALL_IFS);
-+
-+ /* HACK! */
-+ if (atomic_xchg(&hw_priv->tx_lock, 1) != 1)
-+ wiphy_debug(dev->wiphy, "TX is force-unlocked due to stop request.\n");
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
-+ priv->listening = false;
-+ priv->delayed_link_loss = 0;
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ cancel_delayed_work_sync(&priv->link_id_gc_work);
-+ del_timer_sync(&priv->mcast_timeout);
-+ }
-+
-+ wsm_unlock_tx(hw_priv);
-+
-+ mutex_unlock(&hw_priv->conf_mutex);
-+}
-+
-+int xradio_add_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif)
-+{
-+ int ret;
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv;
-+ struct xradio_vif **drv_priv = (void *)vif->drv_priv;
-+ int i;
-+ if (atomic_read(&hw_priv->num_vifs) >= XRWL_MAX_VIFS)
-+ return -EOPNOTSUPP;
-+
-+ if (wait_event_interruptible_timeout(hw_priv->wsm_startup_done,
-+ hw_priv->driver_ready, 3*HZ) <= 0) {
-+ wiphy_err(dev->wiphy, "driver is not ready!\n");
-+ return -ETIMEDOUT;
-+ }
-+
-+ /* fix the problem that when connected,then deauth */
-+ vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
-+ vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
-+
-+ priv = xrwl_get_vif_from_ieee80211(vif);
-+ atomic_set(&priv->enabled, 0);
-+
-+ *drv_priv = priv;
-+ /* __le32 auto_calibration_mode = __cpu_to_le32(1); */
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ priv->mode = vif->type;
-+
-+ spin_lock(&hw_priv->vif_list_lock);
-+ if (atomic_read(&hw_priv->num_vifs) < XRWL_MAX_VIFS) {
-+ for (i = 0; i < XRWL_MAX_VIFS; i++)
-+ if (!memcmp(vif->addr, hw_priv->addresses[i].addr, ETH_ALEN))
-+ break;
-+ if (i == XRWL_MAX_VIFS) {
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return -EINVAL;
-+ }
-+ priv->if_id = i;
-+
-+ hw_priv->if_id_slot |= BIT(priv->if_id);
-+ priv->hw_priv = hw_priv;
-+ priv->hw = dev;
-+ priv->vif = vif;
-+ hw_priv->vif_list[priv->if_id] = vif;
-+ atomic_inc(&hw_priv->num_vifs);
-+ } else {
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return -EOPNOTSUPP;
-+ }
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ /* TODO:COMBO :Check if MAC address matches the one expected by FW */
-+ memcpy(hw_priv->mac_addr, vif->addr, ETH_ALEN);
-+
-+ /* Enable auto-calibration */
-+ /* Exception in subsequent channel switch; disabled.
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_SET_AUTO_CALIBRATION_MODE,
-+ &auto_calibration_mode, sizeof(auto_calibration_mode)));
-+ */
-+ wiphy_debug(dev->wiphy, "Interface ID:%d of type:%d added\n", priv->if_id, priv->mode);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ xradio_vif_setup(priv);
-+
-+ ret = WARN_ON(xradio_setup_mac_pvif(priv));
-+
-+ return ret;
-+}
-+
-+void xradio_remove_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct wsm_reset reset = {
-+ .reset_statistics = true,
-+ };
-+ int i;
-+ bool is_htcapie = false;
-+ struct xradio_vif *tmp_priv;
-+
-+ wiphy_warn(dev->wiphy, "!!! vif_id=%d\n", priv->if_id);
-+ atomic_set(&priv->enabled, 0);
-+ down(&hw_priv->scan.lock);
-+ if(priv->join_status == XRADIO_JOIN_STATUS_STA){
-+ if (atomic_xchg(&priv->delayed_unjoin, 0)) {
-+ wsm_unlock_tx(hw_priv);
-+ wiphy_err(dev->wiphy, "delayed_unjoin exist!\n");
-+ }
-+ cancel_work_sync(&priv->unjoin_work);
-+ wsm_lock_tx(hw_priv);
-+ xradio_unjoin_work(&priv->unjoin_work);
-+ }
-+ mutex_lock(&hw_priv->conf_mutex);
-+ xradio_tx_queues_lock(hw_priv);
-+ wsm_lock_tx(hw_priv);
-+ switch (priv->join_status) {
-+ case XRADIO_JOIN_STATUS_AP:
-+ for (i = 0; priv->link_id_map; ++i) {
-+ if (priv->link_id_map & BIT(i)) {
-+ xrwl_unmap_link(priv, i);
-+ priv->link_id_map &= ~BIT(i);
-+ }
-+ }
-+ memset(priv->link_id_db, 0,
-+ sizeof(priv->link_id_db));
-+ priv->sta_asleep_mask = 0;
-+ priv->enable_beacon = false;
-+ priv->tx_multicast = false;
-+ priv->aid0_bit_set = false;
-+ priv->buffered_multicasts = false;
-+ priv->pspoll_mask = 0;
-+ reset.link_id = 0;
-+ wsm_reset(hw_priv, &reset, priv->if_id);
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ xradio_for_each_vif(hw_priv, tmp_priv, i) {
-+ if (!tmp_priv)
-+ continue;
-+ if ((tmp_priv->join_status == XRADIO_JOIN_STATUS_STA) && tmp_priv->htcap)
-+ is_htcapie = true;
-+ }
-+
-+ if (is_htcapie) {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11N_THROTTLE;
-+ sta_printk(XRADIO_DBG_NIY, "AP REMOVE HTCAP 11N %d\n",hw_priv->vif0_throttle);
-+ } else {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ sta_printk(XRADIO_DBG_NIY, "AP REMOVE 11BG %d\n",hw_priv->vif0_throttle);
-+ }
-+ break;
-+ case XRADIO_JOIN_STATUS_MONITOR:
-+ xradio_disable_listening(priv);
-+ break;
-+ default:
-+ break;
-+ }
-+ /* TODO:COMBO: Change Queue Module */
-+ __xradio_flush(hw_priv, false, priv->if_id);
-+
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ cancel_delayed_work_sync(&priv->link_id_gc_work);
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+ cancel_delayed_work_sync(&priv->set_cts_work);
-+ cancel_delayed_work_sync(&priv->pending_offchanneltx_work);
-+
-+ del_timer_sync(&priv->mcast_timeout);
-+ /* TODO:COMBO: May be reset of these variables "delayed_link_loss and
-+ * join_status to default can be removed as dev_priv will be freed by
-+ * mac80211 */
-+ priv->delayed_link_loss = 0;
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+ wsm_unlock_tx(hw_priv);
-+
-+ if ((priv->if_id ==1) && (priv->mode == NL80211_IFTYPE_AP
-+ || priv->mode == NL80211_IFTYPE_P2P_GO)) {
-+ hw_priv->is_go_thru_go_neg = false;
-+ }
-+ spin_lock(&hw_priv->vif_list_lock);
-+ spin_lock(&priv->vif_lock);
-+ hw_priv->vif_list[priv->if_id] = NULL;
-+ hw_priv->if_id_slot &= (~BIT(priv->if_id));
-+ atomic_dec(&hw_priv->num_vifs);
-+ if (atomic_read(&hw_priv->num_vifs) == 0) {
-+ xradio_free_keys(hw_priv);
-+ memset(hw_priv->mac_addr, 0, ETH_ALEN);
-+ }
-+ spin_unlock(&priv->vif_lock);
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ priv->listening = false;
-+
-+ xradio_tx_queues_unlock(hw_priv);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+
-+ if (atomic_read(&hw_priv->num_vifs) == 0)
-+ flush_workqueue(hw_priv->workqueue);
-+ memset(priv, 0, sizeof(struct xradio_vif));
-+ up(&hw_priv->scan.lock);
-+}
-+
-+int xradio_change_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ enum nl80211_iftype new_type,
-+ bool p2p)
-+{
-+ int ret = 0;
-+ wiphy_debug(dev->wiphy, "changing interface type; new type=%d(%d), p2p=%d(%d)\n",
-+ new_type, vif->type, p2p, vif->p2p);
-+ if (new_type != vif->type || vif->p2p != p2p) {
-+ xradio_remove_interface(dev, vif);
-+ vif->type = new_type;
-+ vif->p2p = p2p;
-+ ret = xradio_add_interface(dev, vif);
-+ }
-+
-+ return ret;
-+}
-+
-+int xradio_config(struct ieee80211_hw *dev, u32 changed)
-+{
-+ int ret = 0;
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct ieee80211_conf *conf = &dev->conf;
-+ /* TODO:COMBO: adjust to multi vif interface
-+ * IEEE80211_CONF_CHANGE_IDLE is still handled per xradio_vif*/
-+ int if_id = 0;
-+ struct xradio_vif *priv;
-+
-+
-+ if (changed &
-+ (IEEE80211_CONF_CHANGE_MONITOR|IEEE80211_CONF_CHANGE_IDLE)) {
-+ /* TBD: It looks like it's transparent
-+ * there's a monitor interface present -- use this
-+ * to determine for example whether to calculate
-+ * timestamps for packets or not, do not use instead
-+ * of filter flags! */
-+ wiphy_debug(dev->wiphy, "ignore IEEE80211_CONF_CHANGE_MONITOR (%d)"
-+ "IEEE80211_CONF_CHANGE_IDLE (%d)\n",
-+ (changed & IEEE80211_CONF_CHANGE_MONITOR) ? 1 : 0,
-+ (changed & IEEE80211_CONF_CHANGE_IDLE) ? 1 : 0);
-+ return ret;
-+ }
-+
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
-+ /* TODO: IEEE80211_CONF_CHANGE_QOS */
-+ /* TODO:COMBO:Change when support is available mac80211*/
-+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
-+ /*hw_priv->output_power = conf->power_level;*/
-+ hw_priv->output_power = 20;
-+ wiphy_debug(dev->wiphy, "Config Tx power=%d, but real=%d\n",
-+ conf->power_level, hw_priv->output_power);
-+ WARN_ON(wsm_set_output_power(hw_priv, hw_priv->output_power * 10, if_id));
-+ }
-+
-+ if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) &&
-+ (hw_priv->channel != conf->chandef.chan)) {
-+ /* Switch Channel commented for CC Mode */
-+ struct ieee80211_channel *ch = conf->chandef.chan;
-+ wiphy_debug(dev->wiphy, "Freq %d (wsm ch: %d).\n",
-+ ch->center_freq, ch->hw_value);
-+ /* Earlier there was a call to __xradio_flush().
-+ Removed as deemed unnecessary */
-+ hw_priv->channel = ch;
-+ hw_priv->channel_changed = 1;
-+ }
-+
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+ return ret;
-+}
-+
-+void xradio_update_filtering(struct xradio_vif *priv)
-+{
-+ int ret;
-+ bool bssid_filtering = !priv->rx_filter.bssid;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ static struct wsm_beacon_filter_control bf_disabled = {
-+ .enabled = 0,
-+ .bcn_count = 1,
-+ };
-+ bool ap_mode = 0;
-+ static struct wsm_beacon_filter_table bf_table_auto = {
-+ .numOfIEs = __cpu_to_le32(2),
-+ .entry[0].ieId = WLAN_EID_VENDOR_SPECIFIC,
-+ .entry[0].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED,
-+ .entry[0].oui[0] = 0x50,
-+ .entry[0].oui[1] = 0x6F,
-+ .entry[0].oui[2] = 0x9A,
-+
-+ .entry[1].ieId = WLAN_EID_HT_OPERATION,
-+ .entry[1].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
-+ WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
-+ WSM_BEACON_FILTER_IE_HAS_APPEARED,
-+ };
-+ static struct wsm_beacon_filter_control bf_auto = {
-+ .enabled = WSM_BEACON_FILTER_ENABLE |
-+ WSM_BEACON_FILTER_AUTO_ERP,
-+ .bcn_count = 1,
-+ };
-+
-+
-+ bf_auto.bcn_count = priv->bf_control.bcn_count;
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_PASSIVE)
-+ return;
-+ else if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR)
-+ bssid_filtering = false;
-+
-+ if (priv->vif && (priv->vif->type == NL80211_IFTYPE_AP))
-+ ap_mode = true;
-+ /*
-+ * When acting as p2p client being connected to p2p GO, in order to
-+ * receive frames from a different p2p device, turn off bssid filter.
-+ *
-+ * WARNING: FW dependency!
-+ * This can only be used with FW WSM371 and its successors.
-+ * In that FW version even with bssid filter turned off,
-+ * device will block most of the unwanted frames.
-+ */
-+ if (priv->vif && priv->vif->p2p)
-+ bssid_filtering = false;
-+
-+ ret = wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
-+ if (!ret && !ap_mode) {
-+ if (priv->vif) {
-+ if (priv->vif->p2p || NL80211_IFTYPE_STATION != priv->vif->type)
-+ ret = wsm_set_beacon_filter_table(hw_priv, &priv->bf_table, priv->if_id);
-+ else
-+ ret = wsm_set_beacon_filter_table(hw_priv, &bf_table_auto, priv->if_id);
-+ } else
-+ WARN_ON(1);
-+ }
-+ if (!ret && !ap_mode) {
-+ if (priv->disable_beacon_filter)
-+ ret = wsm_beacon_filter_control(hw_priv, &bf_disabled, priv->if_id);
-+ else {
-+ if (priv->vif) {
-+ if (priv->vif->p2p || NL80211_IFTYPE_STATION != priv->vif->type)
-+ ret = wsm_beacon_filter_control(hw_priv, &priv->bf_control,
-+ priv->if_id);
-+ else
-+ ret = wsm_beacon_filter_control(hw_priv, &bf_auto, priv->if_id);
-+ } else
-+ WARN_ON(1);
-+ }
-+ }
-+
-+ if (!ret)
-+ ret = wsm_set_bssid_filtering(hw_priv, bssid_filtering, priv->if_id);
-+#if 0
-+ if (!ret) {
-+ ret = wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id);
-+ }
-+#endif
-+ if (ret)
-+ wiphy_debug(priv->hw_priv->hw->wiphy, "Update filtering failed: %d.\n", ret);
-+ return;
-+}
-+
-+void xradio_update_filtering_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif,
-+ update_filtering_work);
-+
-+ xradio_update_filtering(priv);
-+}
-+
-+void xradio_set_beacon_wakeup_period_work(struct work_struct *work)
-+{
-+
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, set_beacon_wakeup_period_work);
-+
-+
-+#ifdef XRADIO_USE_LONG_DTIM_PERIOD
-+{
-+ int join_dtim_period_extend;
-+ if (priv->join_dtim_period <= 3) {
-+ join_dtim_period_extend = priv->join_dtim_period * 3;
-+ } else if (priv->join_dtim_period <= 5) {
-+ join_dtim_period_extend = priv->join_dtim_period * 2;
-+ } else {
-+ join_dtim_period_extend = priv->join_dtim_period;
-+ }
-+ WARN_ON(wsm_set_beacon_wakeup_period(priv->hw_priv,
-+ priv->beacon_int * join_dtim_period_extend >
-+ MAX_BEACON_SKIP_TIME_MS ? 1 : join_dtim_period_extend,
-+ 0, priv->if_id));
-+}
-+#else
-+ WARN_ON(wsm_set_beacon_wakeup_period(priv->hw_priv,
-+ priv->beacon_int * priv->join_dtim_period >
-+ MAX_BEACON_SKIP_TIME_MS ? 1 :priv->join_dtim_period,
-+ 0, priv->if_id));
-+#endif
-+}
-+
-+u64 xradio_prepare_multicast(struct ieee80211_hw *hw,
-+ struct netdev_hw_addr_list *mc_list)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = NULL;
-+ static u8 broadcast_ipv6[ETH_ALEN] = {
-+ 0x33, 0x33, 0x00, 0x00, 0x00, 0x01
-+ };
-+ static u8 broadcast_ipv4[ETH_ALEN] = {
-+ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01
-+ };
-+
-+ int i= 0;
-+ xradio_for_each_vif(hw_priv,priv,i) {
-+ struct netdev_hw_addr *ha = NULL;
-+ int count = 0;
-+ if ((!priv))
-+ continue;
-+
-+ /* Disable multicast filtering */
-+ priv->has_multicast_subscription = false;
-+ memset(&priv->multicast_filter, 0x00, sizeof(priv->multicast_filter));
-+ if (netdev_hw_addr_list_count(mc_list) > WSM_MAX_GRP_ADDRTABLE_ENTRIES)
-+ return 0;
-+
-+ /* Enable if requested */
-+ netdev_hw_addr_list_for_each(ha, mc_list) {
-+ sta_printk(XRADIO_DBG_MSG, "multicast: %pM\n", ha->addr);
-+ memcpy(&priv->multicast_filter.macAddress[count], ha->addr, ETH_ALEN);
-+ if (memcmp(ha->addr, broadcast_ipv4, ETH_ALEN) &&
-+ memcmp(ha->addr, broadcast_ipv6, ETH_ALEN))
-+ priv->has_multicast_subscription = true;
-+ count++;
-+ }
-+ if (count) {
-+ priv->multicast_filter.enable = __cpu_to_le32(1);
-+ priv->multicast_filter.numOfAddresses = __cpu_to_le32(count);
-+ }
-+ }
-+ return netdev_hw_addr_list_count(mc_list);
-+}
-+
-+void xradio_configure_filter(struct ieee80211_hw *hw,
-+ unsigned int changed_flags,
-+ unsigned int *total_flags,
-+ u64 multicast)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = NULL;
-+ int i = 0;
-+
-+ /* delete umac warning */
-+ if (hw_priv->vif_list[0] == NULL && hw_priv->vif_list[1] == NULL)
-+
-+ *total_flags &= ~(1<<31);
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if(NULL == priv)
-+ continue;
-+
-+#if 0
-+ bool listening = !!(*total_flags &
-+ (FIF_PROMISC_IN_BSS |
-+ FIF_OTHER_BSS |
-+ FIF_BCN_PRBRESP_PROMISC |
-+ FIF_PROBE_REQ));
-+#endif
-+
-+ *total_flags &= FIF_OTHER_BSS |
-+ FIF_FCSFAIL |
-+ FIF_BCN_PRBRESP_PROMISC |
-+ FIF_PROBE_REQ;
-+
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ priv->rx_filter.promiscuous = 0;
-+ priv->rx_filter.bssid = (*total_flags &
-+ (FIF_OTHER_BSS | FIF_PROBE_REQ)) ? 1 : 0;
-+ priv->rx_filter.fcs = (*total_flags & FIF_FCSFAIL) ? 1 : 0;
-+ priv->bf_control.bcn_count = (*total_flags &
-+ (FIF_BCN_PRBRESP_PROMISC |
-+ FIF_PROBE_REQ)) ? 1 : 0;
-+
-+ /*add for handle ap FIF_PROBE_REQ message,*/
-+ priv->rx_filter.promiscuous = 0;
-+ priv->rx_filter.fcs = 0;
-+ if(NL80211_IFTYPE_AP == priv->vif->type){
-+ priv->bf_control.bcn_count = 1;
-+ priv->rx_filter.bssid = 1;
-+ }else{
-+ priv->bf_control.bcn_count = 0;
-+ priv->rx_filter.bssid = 0;
-+ }
-+#if 0
-+ if (priv->listening ^ listening) {
-+ priv->listening = listening;
-+ wsm_lock_tx(hw_priv);
-+ xradio_update_listening(priv, listening);
-+ wsm_unlock_tx(hw_priv);
-+ }
-+#endif
-+ xradio_update_filtering(priv);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+ }
-+}
-+
-+int xradio_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
-+ u16 queue, const struct ieee80211_tx_queue_params *params)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ int ret = 0;
-+ /* To prevent re-applying PM request OID again and again*/
-+ bool old_uapsdFlags;
-+
-+ wiphy_debug(dev->wiphy, "vif %d, configuring tx\n", priv->if_id);
-+
-+ if (WARN_ON(!priv))
-+ return -EOPNOTSUPP;
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+
-+ if (queue < dev->queues) {
-+ old_uapsdFlags = priv->uapsd_info.uapsdFlags;
-+
-+ WSM_TX_QUEUE_SET(&priv->tx_queue_params, queue, 0, 0, 0);
-+ ret = wsm_set_tx_queue_params(hw_priv,
-+ &priv->tx_queue_params.params[queue],
-+ queue, priv->if_id);
-+ if (ret) {
-+ wiphy_err(dev->wiphy, "wsm_set_tx_queue_params failed!\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ WSM_EDCA_SET(&priv->edca, queue, params->aifs,
-+ params->cw_min, params->cw_max,
-+ params->txop, 0xc8, params->uapsd);
-+ /* sta role is not support the uapsd */
-+ if (priv->mode == NL80211_IFTYPE_STATION ||
-+ priv->mode == NL80211_IFTYPE_P2P_CLIENT)
-+ priv->edca.params[queue].uapsdEnable = 0;
-+
-+ ret = wsm_set_edca_params(hw_priv, &priv->edca, priv->if_id);
-+ if (ret) {
-+ wiphy_err(dev->wiphy, "wsm_set_edca_params failed!\n");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (priv->mode == NL80211_IFTYPE_STATION) {
-+ ret = xradio_set_uapsd_param(priv, &priv->edca);
-+ if (!ret && priv->setbssparams_done &&
-+ (priv->join_status == XRADIO_JOIN_STATUS_STA) &&
-+ (old_uapsdFlags != priv->uapsd_info.uapsdFlags))
-+ xradio_set_pm(priv, &priv->powersave_mode);
-+ }
-+ } else {
-+ wiphy_err(dev->wiphy, "queue is to large!\n");
-+ ret = -EINVAL;
-+ }
-+
-+out:
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return ret;
-+}
-+
-+int xradio_get_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_low_level_stats *stats)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+
-+ memcpy(stats, &hw_priv->stats, sizeof(*stats));
-+ return 0;
-+}
-+
-+/*
-+int xradio_get_tx_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_tx_queue_stats *stats)
-+{
-+ int i;
-+ struct xradio_common *priv = dev->priv;
-+
-+ for (i = 0; i < dev->queues; ++i)
-+ xradio_queue_get_stats(&priv->tx_queue[i], &stats[i]);
-+
-+ return 0;
-+}
-+*/
-+
-+int xradio_set_pm(struct xradio_vif *priv, const struct wsm_set_pm *arg)
-+{
-+ struct wsm_set_pm pm = *arg;
-+
-+ if (priv->uapsd_info.uapsdFlags != 0)
-+ pm.pmMode &= ~WSM_PSM_FAST_PS_FLAG;
-+
-+ if (memcmp(&pm, &priv->firmware_ps_mode, sizeof(struct wsm_set_pm))) {
-+ priv->firmware_ps_mode = pm;
-+ return wsm_set_pm(priv->hw_priv, &pm, priv->if_id);
-+ } else {
-+ return 0;
-+ }
-+}
-+
-+void xradio_wep_key_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv = container_of(work, struct xradio_vif , wep_key_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u8 queueId = xradio_queue_get_queue_id(hw_priv->pending_frame_id);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queueId];
-+ __le32 wep_default_key_id = __cpu_to_le32(priv->wep_default_key_id);
-+
-+
-+ BUG_ON(queueId >= 4);
-+
-+ sta_printk(XRADIO_DBG_MSG, "Setting default WEP key: %d\n",
-+ priv->wep_default_key_id);
-+
-+ wsm_flush_tx(hw_priv);
-+ WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID,
-+ &wep_default_key_id, sizeof(wep_default_key_id),
-+ priv->if_id));
-+
-+ xradio_queue_requeue(queue, hw_priv->pending_frame_id, true);
-+
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+int xradio_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+ int ret = 0;
-+ __le32 val32;
-+ struct xradio_vif *priv = NULL;
-+ int i =0;
-+ int if_id;
-+
-+
-+ xradio_for_each_vif(hw_priv,priv,i) {
-+ if (!priv)
-+ continue;
-+ if_id = priv->if_id;
-+
-+ if (value != (u32) -1)
-+ val32 = __cpu_to_le32(value);
-+ else
-+ val32 = 0; /* disabled */
-+
-+ /* mutex_lock(&priv->conf_mutex); */
-+ ret = WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_RTS_THRESHOLD,
-+ &val32, sizeof(val32), if_id));
-+ /* mutex_unlock(&priv->conf_mutex); */
-+ }
-+ return ret;
-+}
-+
-+/* TODO: COMBO: Flush only a particular interface specific parts */
-+int __xradio_flush(struct xradio_common *hw_priv, bool drop, int if_id)
-+{
-+ int i, ret;
-+ struct xradio_vif *priv =
-+ __xrwl_hwpriv_to_vifpriv(hw_priv, if_id);
-+
-+
-+ for (;;) {
-+ /* TODO: correct flush handling is required when dev_stop.
-+ * Temporary workaround: 2s
-+ */
-+ if (drop) {
-+ for (i = 0; i < 4; ++i)
-+ xradio_queue_clear(&hw_priv->tx_queue[i],if_id);
-+ } else if(!hw_priv->bh_error){
-+ ret = wait_event_timeout(
-+ hw_priv->tx_queue_stats.wait_link_id_empty,
-+ xradio_queue_stats_is_empty(&hw_priv->tx_queue_stats, -1, if_id),
-+ 2 * HZ);
-+ } else { //add by yangfh, don't wait when bh error
-+ sta_printk(XRADIO_DBG_ERROR, " %s:bh_error occur.\n", __func__);
-+ ret = -1;
-+ break;
-+ }
-+
-+ if (!drop && unlikely(ret <= 0)) {
-+ sta_printk(XRADIO_DBG_ERROR, " %s: timeout...\n", __func__);
-+ ret = -ETIMEDOUT;
-+ break;
-+ } else {
-+ ret = 0;
-+ }
-+
-+ wsm_vif_lock_tx(priv);
-+ if (unlikely(!xradio_queue_stats_is_empty(&hw_priv->tx_queue_stats,
-+ -1, if_id))) {
-+ /* Highly unlekely: WSM requeued frames. */
-+ wsm_unlock_tx(hw_priv);
-+ continue;
-+ }
-+ wsm_unlock_tx(hw_priv);
-+ break;
-+ }
-+ return ret;
-+}
-+
-+void xradio_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop)
-+{
-+ //struct xradio_vif *priv = NULL;
-+ struct xradio_common *hw_priv = hw->priv;
-+ int i = 0;
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+
-+ /*TODO:COMBO: reenable this part of code when flush callback
-+ * is implemented per vif */
-+ /*switch (hw_priv->mode) {
-+ case NL80211_IFTYPE_MONITOR:
-+ drop = true;
-+ break;
-+ case NL80211_IFTYPE_AP:
-+ if (!hw_priv->enable_beacon)
-+ drop = true;
-+ break;
-+ }*/
-+
-+ //if (!(hw_priv->if_id_slot & BIT(priv->if_id)))
-+ // return;
-+
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if(NULL == priv)
-+ continue;
-+ if ((hw_priv->if_id_slot & BIT(priv->if_id)))
-+ __xradio_flush(hw_priv, drop, priv->if_id);
-+ }
-+ return;
-+}
-+
-+int xradio_remain_on_channel(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_channel *chan,
-+ int duration, enum ieee80211_roc_type type)
-+{
-+ int ret = 0;
-+ struct xradio_common *hw_priv = hw->priv;
-+ struct xradio_vif *priv = NULL;
-+ int i = 0;
-+ int if_id;
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ struct timeval TES_P2P_0002_tmval;
-+#endif
-+
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ do_gettimeofday(&TES_P2P_0002_tmval);
-+ TES_P2P_0002_roc_dur = (s32)duration;
-+ TES_P2P_0002_roc_sec = (s32)TES_P2P_0002_tmval.tv_sec;
-+ TES_P2P_0002_roc_usec = (s32)TES_P2P_0002_tmval.tv_usec;
-+#endif
-+
-+ down(&hw_priv->scan.lock);
-+ mutex_lock(&hw_priv->conf_mutex);
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if(NULL == priv)
-+ continue;
-+ if_id = priv->if_id;
-+
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "ROC IN %d ch %d\n",
-+ priv->if_id, chan->hw_value);
-+#endif
-+ /* default only p2p interface if_id can remain on */
-+ if((priv->if_id == 0) || (priv->if_id == 1))
-+ continue;
-+ hw_priv->roc_if_id = priv->if_id;
-+ ret = WARN_ON(__xradio_flush(hw_priv, false, if_id));
-+ xradio_enable_listening(priv, chan);
-+
-+ if (!ret) {
-+ atomic_set(&hw_priv->remain_on_channel, 1);
-+ queue_delayed_work(hw_priv->workqueue, &hw_priv->rem_chan_timeout,
-+ duration * HZ / 1000);
-+ priv->join_status = XRADIO_JOIN_STATUS_MONITOR;
-+ ieee80211_ready_on_channel(hw);
-+ } else {
-+ hw_priv->roc_if_id = -1;
-+ up(&hw_priv->scan.lock);
-+ }
-+
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "ROC OUT %d\n", priv->if_id);
-+#endif
-+ }
-+ /* set the channel to supplied ieee80211_channel pointer, if it
-+ is not set. This is to remove the crash while sending a probe res
-+ in listen state. Later channel will updated on
-+ IEEE80211_CONF_CHANGE_CHANNEL event*/
-+ if(!hw_priv->channel) {
-+ hw_priv->channel = chan;
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return ret;
-+}
-+
-+int xradio_cancel_remain_on_channel(struct ieee80211_hw *hw)
-+{
-+ struct xradio_common *hw_priv = hw->priv;
-+
-+
-+ sta_printk(XRADIO_DBG_NIY, "Cancel remain on channel\n");
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ if (TES_P2P_0002_state == TES_P2P_0002_STATE_GET_PKTID) {
-+ TES_P2P_0002_state = TES_P2P_0002_STATE_IDLE;
-+ sta_printk(XRADIO_DBG_WARN, "[ROC_RESTART_STATE_IDLE][Cancel ROC]\n");
-+ }
-+#endif
-+
-+ if (atomic_read(&hw_priv->remain_on_channel))
-+ cancel_delayed_work_sync(&hw_priv->rem_chan_timeout);
-+
-+ if (atomic_read(&hw_priv->remain_on_channel))
-+ xradio_rem_chan_timeout(&hw_priv->rem_chan_timeout.work);
-+
-+ return 0;
-+}
-+
-+/* ******************************************************************** */
-+/* WSM callbacks */
-+
-+void xradio_channel_switch_cb(struct xradio_common *hw_priv)
-+{
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_free_event_queue(struct xradio_common *hw_priv)
-+{
-+ LIST_HEAD(list);
-+
-+
-+ spin_lock(&hw_priv->event_queue_lock);
-+ list_splice_init(&hw_priv->event_queue, &list);
-+ spin_unlock(&hw_priv->event_queue_lock);
-+
-+ __xradio_free_event_queue(&list);
-+}
-+
-+void xradio_event_handler(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, event_handler);
-+ struct xradio_vif *priv;
-+ struct xradio_wsm_event *event;
-+ LIST_HEAD(list);
-+
-+
-+ spin_lock(&hw_priv->event_queue_lock);
-+ list_splice_init(&hw_priv->event_queue, &list);
-+ spin_unlock(&hw_priv->event_queue_lock);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ list_for_each_entry(event, &list, link) {
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, event->if_id);
-+ if (!priv) {
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] Event for non existing "
-+ "interface, ignoring.\n");
-+ continue;
-+ }
-+ switch (event->evt.eventId) {
-+ case WSM_EVENT_ERROR:
-+ /* I even don't know what is it about.. */
-+ //STUB();
-+ break;
-+ case WSM_EVENT_BSS_LOST:
-+ {
-+ spin_lock(&priv->bss_loss_lock);
-+ if (priv->bss_loss_status > XRADIO_BSS_LOSS_NONE) {
-+ spin_unlock(&priv->bss_loss_lock);
-+ break;
-+ }
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_CHECKING;
-+ spin_unlock(&priv->bss_loss_lock);
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] BSS lost, Beacon miss=%d, event=%x.\n",
-+ (event->evt.eventData>>8)&0xff, event->evt.eventData&0xff);
-+
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ if (!down_trylock(&hw_priv->scan.lock)) {
-+ up(&hw_priv->scan.lock);
-+ priv->delayed_link_loss = 0;
-+ queue_delayed_work(hw_priv->workqueue,
-+ &priv->bss_loss_work, HZ/10); //100ms
-+ } else {
-+ /* Scan is in progress. Delay reporting. */
-+ /* Scan complete will trigger bss_loss_work */
-+ priv->delayed_link_loss = 1;
-+ /* Also we're starting watchdog. */
-+ queue_delayed_work(hw_priv->workqueue,
-+ &priv->bss_loss_work, 10 * HZ);
-+ }
-+ break;
-+ }
-+ case WSM_EVENT_BSS_REGAINED:
-+ {
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] BSS regained.\n");
-+ priv->delayed_link_loss = 0;
-+ spin_lock(&priv->bss_loss_lock);
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_NONE;
-+ spin_unlock(&priv->bss_loss_lock);
-+ cancel_delayed_work_sync(&priv->bss_loss_work);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ break;
-+ }
-+ case WSM_EVENT_RADAR_DETECTED:
-+ //STUB();
-+ break;
-+ case WSM_EVENT_RCPI_RSSI:
-+ {
-+ /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
-+ * RSSI = RCPI / 2 - 110 */
-+ int rcpiRssi = (int)(event->evt.eventData & 0xFF);
-+ int cqm_evt;
-+ if (priv->cqm_use_rssi)
-+ rcpiRssi = (s8)rcpiRssi;
-+ else
-+ rcpiRssi = rcpiRssi / 2 - 110;
-+
-+ cqm_evt = (rcpiRssi <= priv->cqm_rssi_thold) ?
-+ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW :
-+ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
-+ sta_printk(XRADIO_DBG_NIY, "[CQM] RSSI event: %d", rcpiRssi);
-+ ieee80211_cqm_rssi_notify(priv->vif,
-+ cqm_evt,
-+ 0,
-+ GFP_KERNEL);
-+ break;
-+ }
-+ case WSM_EVENT_BT_INACTIVE:
-+ //STUB();
-+ break;
-+ case WSM_EVENT_BT_ACTIVE:
-+ //STUB();
-+ break;
-+ case WSM_EVENT_INACTIVITY:
-+ {
-+ int link_id = ffs((u32)(event->evt.eventData)) - 1;
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *deauth;
-+ struct xradio_link_entry *entry = NULL;
-+
-+ sta_printk(XRADIO_DBG_WARN, "Inactivity Event Recieved for "
-+ "link_id %d\n", link_id);
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ break;
-+ skb_reserve(skb, 64);
-+ xrwl_unmap_link(priv, link_id);
-+ deauth = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ WARN_ON(!deauth);
-+ entry = &priv->link_id_db[link_id - 1];
-+ deauth->duration = 0;
-+ memcpy(deauth->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(deauth->sa, entry->mac/*priv->link_id_db[i].mac*/, ETH_ALEN);
-+ memcpy(deauth->bssid, priv->vif->addr, ETH_ALEN);
-+ deauth->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-+ IEEE80211_STYPE_DEAUTH |
-+ IEEE80211_FCTL_TODS);
-+ deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
-+ deauth->seq_ctrl = 0;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ sta_printk(XRADIO_DBG_WARN, " Inactivity Deauth Frame sent for MAC SA %pM \t and DA %pM\n", deauth->sa, deauth->da);
-+ queue_work(priv->hw_priv->workqueue, &priv->set_tim_work);
-+ break;
-+ }
-+ case WSM_EVENT_PS_MODE_ERROR:
-+ {
-+ if (!priv->uapsd_info.uapsdFlags &&
-+ (priv->user_pm_mode != WSM_PSM_PS))
-+ {
-+ struct wsm_set_pm pm = priv->powersave_mode;
-+ int ret = 0;
-+
-+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
-+ ret = xradio_set_pm (priv, &priv->powersave_mode);
-+ if(ret)
-+ priv->powersave_mode = pm;
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ __xradio_free_event_queue(&list);
-+}
-+
-+void xradio_bss_loss_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, bss_loss_work.work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int timeout; /* in beacons */
-+
-+
-+ timeout = priv->cqm_link_loss_count - priv->cqm_beacon_loss_count;
-+ /* Skip the confimration procedure in P2P case */
-+ if (priv->vif->p2p)
-+ goto report;
-+
-+ spin_lock(&priv->bss_loss_lock);
-+ if (priv->bss_loss_status == XRADIO_BSS_LOSS_CONFIRMING) {
-+ //do loss report next time.
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_CONFIRMED;
-+ spin_unlock(&priv->bss_loss_lock);
-+ //wait for more 1s to loss confirm.
-+ queue_delayed_work(hw_priv->workqueue, &priv->bss_loss_work, 1 * HZ);
-+ return;
-+ } else if (priv->bss_loss_status == XRADIO_BSS_LOSS_NONE) {
-+ spin_unlock(&priv->bss_loss_lock);
-+ //link is alive.
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ return;
-+ } else if (priv->bss_loss_status == XRADIO_BSS_LOSS_CHECKING) {
-+ /* it mean no confirming packets, just report loss. */
-+ }
-+ spin_unlock(&priv->bss_loss_lock);
-+
-+report:
-+ if (priv->cqm_beacon_loss_count) {
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] Beacon loss.\n");
-+ if (timeout <= 0)
-+ timeout = 0;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //ieee80211_cqm_beacon_miss_notify(priv->vif, GFP_KERNEL);
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ } else {
-+ timeout = 0;
-+ }
-+
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ queue_delayed_work(hw_priv->workqueue, &priv->connection_loss_work,
-+ timeout * HZ / 10);
-+
-+ spin_lock(&priv->bss_loss_lock);
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_NONE;
-+ spin_unlock(&priv->bss_loss_lock);
-+}
-+
-+void xradio_connection_loss_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, connection_loss_work.work);
-+ sta_printk(XRADIO_DBG_ERROR, "[CQM] if%d Reporting connection loss.\n",
-+ priv->if_id);
-+ ieee80211_connection_loss(priv->vif);
-+}
-+
-+void xradio_tx_failure_work(struct work_struct *work)
-+{
-+ //struct xradio_vif *priv =
-+ // container_of(work, struct xradio_vif, tx_failure_work);
-+ sta_printk(XRADIO_DBG_WARN, "[CQM] Reporting TX failure.\n");
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ //ieee80211_cqm_tx_fail_notify(priv->vif, GFP_KERNEL);
-+#else /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ //(void)priv;
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+}
-+
-+/* Internal API */
-+int xradio_setup_mac(struct xradio_common *hw_priv)
-+{
-+ int ret = 0, if_id;
-+
-+
-+ if (hw_priv->sdd) {
-+ struct wsm_configuration cfg = {
-+ .dot11StationId = &hw_priv->mac_addr[0],
-+ .dpdData = hw_priv->sdd->data,
-+ .dpdData_size = hw_priv->sdd->size,
-+ };
-+ for (if_id = 0; if_id < xrwl_get_nr_hw_ifaces(hw_priv);
-+ if_id++) {
-+ /* Set low-power mode. */
-+ ret |= WARN_ON(wsm_configuration(hw_priv, &cfg,
-+ if_id));
-+ }
-+ /* wsm_configuration only once, so release it */
-+ release_firmware(hw_priv->sdd);
-+ hw_priv->sdd = NULL;
-+ }
-+
-+ /* BUG:TX output power is not set untill config_xradio is called.
-+ * This would lead to 0 power set in fw and would effect scan & p2p-find
-+ * Setting to default value here from sdd which would be overwritten when
-+ * we make connection to AP.This value is used only during scan & p2p-ops
-+ * untill AP connection is made */
-+ /*BUG:TX output power: Hardcoding to 20dbm if CCX is not enabled*/
-+ /*TODO: This might change*/
-+ if (!hw_priv->output_power)
-+ hw_priv->output_power=20;
-+ sta_printk(XRADIO_DBG_MSG, "%s output power %d\n",__func__,hw_priv->output_power);
-+
-+ return ret;
-+}
-+
-+void xradio_pending_offchanneltx_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, pending_offchanneltx_work.work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "OFFCHAN PEND IN\n");
-+#endif
-+ xradio_disable_listening(priv);
-+ hw_priv->roc_if_id = -1;
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "OFFCHAN PEND OUT\n");
-+#endif
-+ up(&hw_priv->scan.lock);
-+ mutex_unlock(&hw_priv->conf_mutex);
-+}
-+
-+void xradio_offchannel_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, offchannel_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u8 queueId = xradio_queue_get_queue_id(hw_priv->pending_frame_id);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queueId];
-+
-+
-+ BUG_ON(queueId >= 4);
-+ BUG_ON(!hw_priv->channel);
-+
-+ if (unlikely(down_trylock(&hw_priv->scan.lock))) {
-+ int ret;
-+ sta_printk(XRADIO_DBG_ERROR, "xradio_offchannel_work***** drop frame\n");
-+ ret = xradio_queue_remove(queue, hw_priv->pending_frame_id);
-+ if (ret)
-+ sta_printk(XRADIO_DBG_ERROR, "xradio_offchannel_work: "
-+ "queue_remove failed %d\n", ret);
-+ wsm_unlock_tx(hw_priv);
-+ //workaround by yangfh
-+ up(&hw_priv->scan.lock);
-+ ieee80211_connection_loss(priv->vif);
-+ sta_printk(XRADIO_DBG_ERROR,"lock %d\n", hw_priv->scan.lock.count);
-+
-+ return;
-+ }
-+ mutex_lock(&hw_priv->conf_mutex);
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "OFFCHAN WORK IN %d\n", priv->if_id);
-+#endif
-+ hw_priv->roc_if_id = priv->if_id;
-+ if (likely(!priv->join_status)) {
-+ wsm_vif_flush_tx(priv);
-+ xradio_enable_listening(priv, hw_priv->channel);
-+ /* xradio_update_filtering(priv); */
-+ }
-+ if (unlikely(!priv->join_status))
-+ xradio_queue_remove(queue, hw_priv->pending_frame_id);
-+ else
-+ xradio_queue_requeue(queue, hw_priv->pending_frame_id, false);
-+
-+ queue_delayed_work(hw_priv->workqueue,
-+ &priv->pending_offchanneltx_work, 204 * HZ/1000);
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_WARN, "OFFCHAN WORK OUT %d\n", priv->if_id);
-+#endif
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_join_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, join_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ u8 queueId = xradio_queue_get_queue_id(hw_priv->pending_frame_id);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queueId];
-+ const struct xradio_txpriv *txpriv = NULL;
-+ struct sk_buff *skb = NULL;
-+ const struct wsm_tx *wsm;
-+ const struct ieee80211_hdr *frame;
-+ const u8 *bssid;
-+ struct cfg80211_bss *bss;
-+ const u8 *ssidie;
-+ const u8 *dtimie;
-+ const struct ieee80211_tim_ie *tim = NULL;
-+ struct wsm_protected_mgmt_policy mgmt_policy;
-+ //struct wsm_reset reset = {
-+ // .reset_statistics = true,
-+ //};
-+
-+
-+
-+ BUG_ON(queueId >= 4);
-+ if (xradio_queue_get_skb(queue, hw_priv->pending_frame_id,
-+ &skb, &txpriv)) {
-+ wsm_unlock_tx(hw_priv);
-+ return;
-+ }
-+ wsm = (struct wsm_tx *)&skb->data[0];
-+ frame = (struct ieee80211_hdr *)&skb->data[txpriv->offset];
-+ bssid = &frame->addr1[0]; /* AP SSID in a 802.11 frame */
-+
-+ BUG_ON(!wsm);
-+ BUG_ON(!hw_priv->channel);
-+
-+ if (unlikely(priv->join_status)) {
-+ sta_printk(XRADIO_DBG_WARN, "%s, pre join_status=%d.\n",
-+ __func__, priv->join_status);
-+ wsm_lock_tx(hw_priv);
-+ xradio_unjoin_work(&priv->unjoin_work);
-+ }
-+
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+
-+ bss = cfg80211_get_bss(hw_priv->hw->wiphy, hw_priv->channel,
-+ bssid, NULL, 0, 0, 0);
-+ if (!bss) {
-+ xradio_queue_remove(queue, hw_priv->pending_frame_id);
-+ wsm_unlock_tx(hw_priv);
-+ return;
-+ }
-+ ssidie = cfg80211_find_ie(WLAN_EID_SSID,
-+ bss->ies->data,
-+ bss->ies->len);
-+ dtimie = cfg80211_find_ie(WLAN_EID_TIM,
-+ bss->ies->data,
-+ bss->ies->len);
-+ if (dtimie)
-+ tim = (struct ieee80211_tim_ie *)&dtimie[2];
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ {
-+ struct wsm_join join = {
-+ .mode = (bss->capability & WLAN_CAPABILITY_IBSS) ?
-+ WSM_JOIN_MODE_IBSS : WSM_JOIN_MODE_BSS,
-+ /* default changed to LONG, by HuangLu, fix 2/5.5/11m tx fail*/
-+ .preambleType = WSM_JOIN_PREAMBLE_LONG,
-+ .probeForJoin = 1,
-+ /* dtimPeriod will be updated after association */
-+ .dtimPeriod = 1,
-+ .beaconInterval = bss->beacon_interval,
-+ };
-+
-+ if (priv->if_id)
-+ join.flags |= WSM_FLAG_MAC_INSTANCE_1;
-+ else
-+ join.flags &= ~WSM_FLAG_MAC_INSTANCE_1;
-+
-+ /* BT Coex related changes */
-+ if (hw_priv->is_BT_Present) {
-+ if (((hw_priv->conf_listen_interval * 100) %
-+ bss->beacon_interval) == 0)
-+ priv->listen_interval =
-+ ((hw_priv->conf_listen_interval * 100) /
-+ bss->beacon_interval);
-+ else
-+ priv->listen_interval =
-+ ((hw_priv->conf_listen_interval * 100) /
-+ bss->beacon_interval + 1);
-+ }
-+
-+ if (tim && tim->dtim_period > 1) {
-+ join.dtimPeriod = tim->dtim_period;
-+ priv->join_dtim_period = tim->dtim_period;
-+ }
-+ priv->beacon_int = bss->beacon_interval;
-+ sta_printk(XRADIO_DBG_NIY, "Join DTIM: %d, interval: %d\n",
-+ join.dtimPeriod, priv->beacon_int);
-+
-+ hw_priv->is_go_thru_go_neg = false;
-+ join.channelNumber = hw_priv->channel->hw_value;
-+
-+ /* basicRateSet will be updated after association.
-+ Currently these values are hardcoded */
-+ if (hw_priv->channel->band == NL80211_BAND_5GHZ) {
-+ join.band = WSM_PHY_BAND_5G;
-+ join.basicRateSet = 64; /*6 mbps*/
-+ }else{
-+ join.band = WSM_PHY_BAND_2_4G;
-+ join.basicRateSet = 7; /*1, 2, 5.5 mbps*/
-+ }
-+ memcpy(&join.bssid[0], bssid, sizeof(join.bssid));
-+ memcpy(&priv->join_bssid[0], bssid, sizeof(priv->join_bssid));
-+
-+ if (ssidie) {
-+ join.ssidLength = ssidie[1];
-+ if (WARN_ON(join.ssidLength > sizeof(join.ssid)))
-+ join.ssidLength = sizeof(join.ssid);
-+ memcpy(&join.ssid[0], &ssidie[2], join.ssidLength);
-+ if(strstr(&join.ssid[0],"5.1.4"))
-+ msleep(200);
-+#ifdef ROAM_OFFLOAD
-+ if((priv->vif->type == NL80211_IFTYPE_STATION)) {
-+ priv->ssid_length = join.ssidLength;
-+ memcpy(priv->ssid, &join.ssid[0], priv->ssid_length);
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+ }
-+
-+ if (priv->vif->p2p) {
-+ join.flags |= WSM_JOIN_FLAGS_P2P_GO;
-+ join.basicRateSet =
-+ xradio_rate_mask_to_wsm(hw_priv, 0xFF0);
-+ }
-+
-+ wsm_flush_tx(hw_priv);
-+
-+ /* Queue unjoin if not associated in 3 sec. */
-+ queue_delayed_work(hw_priv->workqueue,
-+ &priv->join_timeout, 3 * HZ);
-+ /*Stay Awake for Join Timeout*/
-+ xradio_pm_stay_awake(&hw_priv->pm_state, 3 * HZ);
-+
-+ xradio_disable_listening(priv);
-+
-+ //WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ 0, hw_priv->ba_tid_mask, priv->if_id));
-+ spin_lock_bh(&hw_priv->ba_lock);
-+ hw_priv->ba_ena = false;
-+ hw_priv->ba_cnt = 0;
-+ hw_priv->ba_acc = 0;
-+ hw_priv->ba_hist = 0;
-+ hw_priv->ba_cnt_rx = 0;
-+ hw_priv->ba_acc_rx = 0;
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+
-+ mgmt_policy.protectedMgmtEnable = 0;
-+ mgmt_policy.unprotectedMgmtFramesAllowed = 1;
-+ mgmt_policy.encryptionForAuthFrame = 1;
-+ wsm_set_protected_mgmt_policy(hw_priv, &mgmt_policy, priv->if_id);
-+
-+ if (wsm_join(hw_priv, &join, priv->if_id)) {
-+ memset(&priv->join_bssid[0],
-+ 0, sizeof(priv->join_bssid));
-+ xradio_queue_remove(queue, hw_priv->pending_frame_id);
-+ cancel_delayed_work_sync(&priv->join_timeout);
-+ } else {
-+ /* Upload keys */
-+ xradio_queue_requeue(queue, hw_priv->pending_frame_id,
-+ true);
-+ priv->join_status = XRADIO_JOIN_STATUS_STA;
-+
-+ /* Due to beacon filtering it is possible that the
-+ * AP's beacon is not known for the mac80211 stack.
-+ * Disable filtering temporary to make sure the stack
-+ * receives at least one */
-+ priv->disable_beacon_filter = true;
-+
-+ }
-+ xradio_update_filtering(priv);
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ cfg80211_put_bss(hw_priv->hw->wiphy,bss);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_join_timeout(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, join_timeout.work);
-+ sta_printk(XRADIO_DBG_WARN, "[WSM] Issue unjoin command (TMO).\n");
-+ wsm_lock_tx(priv->hw_priv);
-+ xradio_unjoin_work(&priv->unjoin_work);
-+}
-+
-+void xradio_unjoin_work(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, unjoin_work);
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ struct wsm_reset reset = {
-+ .reset_statistics = true,
-+ };
-+ bool is_htcapie = false;
-+ int i;
-+ struct xradio_vif *tmp_priv;
-+
-+ //add by yangfh.
-+ hw_priv->connet_time[priv->if_id] = 0;
-+#ifdef AP_HT_COMPAT_FIX
-+ priv->ht_compat_det &= ~1;
-+ priv->ht_compat_cnt = 0;
-+#endif
-+
-+ del_timer_sync(&hw_priv->ba_timer);
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if (unlikely(atomic_read(&hw_priv->scan.in_progress))) {
-+ if (atomic_xchg(&priv->delayed_unjoin, 1)) {
-+ sta_printk(XRADIO_DBG_NIY,
-+ "%s: Delayed unjoin "
-+ "is already scheduled.\n",
-+ __func__);
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ return;
-+ }
-+
-+ if (priv->join_status &&
-+ priv->join_status > XRADIO_JOIN_STATUS_STA) {
-+ sta_printk(XRADIO_DBG_ERROR,
-+ "%s: Unexpected: join status: %d\n",
-+ __func__, priv->join_status);
-+ BUG_ON(1);
-+ }
-+ if (priv->join_status) {
-+ cancel_work_sync(&priv->update_filtering_work);
-+ cancel_work_sync(&priv->set_beacon_wakeup_period_work);
-+ memset(&priv->join_bssid[0], 0, sizeof(priv->join_bssid));
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+
-+ /* Unjoin is a reset. */
-+ wsm_flush_tx(hw_priv);
-+ WARN_ON(wsm_keep_alive_period(hw_priv, 0, priv->if_id));
-+ WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
-+ WARN_ON(wsm_set_operational_mode(hw_priv, &defaultoperationalmode, priv->if_id));
-+ WARN_ON(wsm_set_output_power(hw_priv,
-+ hw_priv->output_power * 10, priv->if_id));
-+ priv->join_dtim_period = 0;
-+ priv->cipherType = 0;
-+ WARN_ON(xradio_setup_mac_pvif(priv));
-+ xradio_free_event_queue(hw_priv);
-+ cancel_work_sync(&hw_priv->event_handler);
-+ cancel_delayed_work_sync(&priv->connection_loss_work);
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ 0, hw_priv->ba_tid_mask, priv->if_id));
-+ priv->disable_beacon_filter = false;
-+ xradio_update_filtering(priv);
-+ priv->setbssparams_done = false;
-+ memset(&priv->association_mode, 0,
-+ sizeof(priv->association_mode));
-+ memset(&priv->bss_params, 0, sizeof(priv->bss_params));
-+ memset(&priv->firmware_ps_mode, 0,
-+ sizeof(priv->firmware_ps_mode));
-+ priv->htcap = false;
-+ xradio_for_each_vif(hw_priv, tmp_priv, i) {
-+ if (!tmp_priv)
-+ continue;
-+ if ((tmp_priv->join_status == XRADIO_JOIN_STATUS_STA) && tmp_priv->htcap)
-+ is_htcapie = true;
-+ }
-+
-+ if (is_htcapie) {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11N_THROTTLE;
-+ sta_printk(XRADIO_DBG_NIY, "UNJOIN HTCAP 11N %d\n",hw_priv->vif0_throttle);
-+ } else {
-+ hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
-+ hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
-+ sta_printk(XRADIO_DBG_NIY, "UNJOIN 11BG %d\n",hw_priv->vif0_throttle);
-+ }
-+ sta_printk(XRADIO_DBG_NIY, "Unjoin.\n");
-+ }
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+int xradio_enable_listening(struct xradio_vif *priv,
-+ struct ieee80211_channel *chan)
-+{
-+ /* TODO:COMBO: Channel is common to HW currently in mac80211.
-+ Change the code below once channel is made per VIF */
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ struct wsm_start start = {
-+ .mode = WSM_START_MODE_P2P_DEV | (priv->if_id << 4),
-+ .band = (chan->band == NL80211_BAND_5GHZ) ?
-+ WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G,
-+ .channelNumber = chan->hw_value,
-+ .beaconInterval = 100,
-+ .DTIMPeriod = 1,
-+ .probeDelay = 0,
-+ .basicRateSet = 0x0F,
-+ };
-+
-+
-+ if(priv->if_id != 2) {
-+ WARN_ON(priv->join_status > XRADIO_JOIN_STATUS_MONITOR);
-+ return 0;
-+ }
-+ if (priv->join_status == XRADIO_JOIN_STATUS_MONITOR)
-+ return 0;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_PASSIVE)
-+ priv->join_status = XRADIO_JOIN_STATUS_MONITOR;
-+
-+ WARN_ON(priv->join_status > XRADIO_JOIN_STATUS_MONITOR);
-+
-+ return wsm_start(hw_priv, &start, XRWL_GENERIC_IF_ID);
-+}
-+
-+int xradio_disable_listening(struct xradio_vif *priv)
-+{
-+ int ret;
-+ struct wsm_reset reset = {
-+ .reset_statistics = true,
-+ };
-+
-+
-+ if(priv->if_id != 2) {
-+ WARN_ON(priv->join_status > XRADIO_JOIN_STATUS_MONITOR);
-+ return 0;
-+ }
-+ priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
-+
-+ WARN_ON(priv->join_status > XRADIO_JOIN_STATUS_MONITOR);
-+
-+ if (priv->hw_priv->roc_if_id == -1)
-+ return 0;
-+
-+ ret = wsm_reset(priv->hw_priv, &reset, XRWL_GENERIC_IF_ID);
-+ return ret;
-+}
-+
-+/* TODO:COMBO:UAPSD will be supported only on one interface */
-+int xradio_set_uapsd_param(struct xradio_vif *priv,
-+ const struct wsm_edca_params *arg)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int ret;
-+ u16 uapsdFlags = 0;
-+
-+
-+ /* Here's the mapping AC [queue, bit]
-+ VO [0,3], VI [1, 2], BE [2, 1], BK [3, 0]*/
-+
-+ if (arg->params[0].uapsdEnable)
-+ uapsdFlags |= 1 << 3;
-+
-+ if (arg->params[1].uapsdEnable)
-+ uapsdFlags |= 1 << 2;
-+
-+ if (arg->params[2].uapsdEnable)
-+ uapsdFlags |= 1 << 1;
-+
-+ if (arg->params[3].uapsdEnable)
-+ uapsdFlags |= 1;
-+
-+ /* Currently pseudo U-APSD operation is not supported, so setting
-+ * MinAutoTriggerInterval, MaxAutoTriggerInterval and
-+ * AutoTriggerStep to 0 */
-+
-+ priv->uapsd_info.uapsdFlags = cpu_to_le16(uapsdFlags);
-+ priv->uapsd_info.minAutoTriggerInterval = 0;
-+ priv->uapsd_info.maxAutoTriggerInterval = 0;
-+ priv->uapsd_info.autoTriggerStep = 0;
-+
-+ ret = wsm_set_uapsd_info(hw_priv, &priv->uapsd_info,
-+ priv->if_id);
-+ return ret;
-+}
-+
-+void xradio_ba_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, ba_work);
-+ u8 tx_ba_tid_mask;
-+
-+
-+ /* TODO:COMBO: reenable this part of code */
-+/* if (priv->join_status != XRADIO_JOIN_STATUS_STA)
-+ return;
-+ if (!priv->setbssparams_done)
-+ return;*/
-+
-+ sta_printk(XRADIO_DBG_WARN, "BA work****\n");
-+ spin_lock_bh(&hw_priv->ba_lock);
-+// tx_ba_tid_mask = hw_priv->ba_ena ? hw_priv->ba_tid_mask : 0;
-+ tx_ba_tid_mask = hw_priv->ba_tid_mask;
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+
-+ wsm_lock_tx(hw_priv);
-+
-+ WARN_ON(wsm_set_block_ack_policy(hw_priv,
-+ tx_ba_tid_mask, hw_priv->ba_tid_mask, -1)); /*TODO:COMBO*/
-+
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+void xradio_ba_timer(struct timer_list *t)
-+{
-+ struct xradio_common *hw_priv = from_timer(hw_priv, t, ba_timer);
-+ bool ba_ena;
-+
-+
-+ spin_lock_bh(&hw_priv->ba_lock);
-+
-+ if (atomic_read(&hw_priv->scan.in_progress)) {
-+ hw_priv->ba_cnt = 0;
-+ hw_priv->ba_acc = 0;
-+ hw_priv->ba_cnt_rx = 0;
-+ hw_priv->ba_acc_rx = 0;
-+ goto skip_statistic_update;
-+ }
-+
-+ if (hw_priv->ba_cnt >= XRADIO_BLOCK_ACK_CNT &&
-+ (hw_priv->ba_acc / hw_priv->ba_cnt >= XRADIO_BLOCK_ACK_THLD ||
-+ (hw_priv->ba_cnt_rx >= XRADIO_BLOCK_ACK_CNT &&
-+ hw_priv->ba_acc_rx / hw_priv->ba_cnt_rx >=
-+ XRADIO_BLOCK_ACK_THLD)))
-+ ba_ena = true;
-+ else
-+ ba_ena = false;
-+
-+ hw_priv->ba_cnt = 0;
-+ hw_priv->ba_acc = 0;
-+ hw_priv->ba_cnt_rx = 0;
-+ hw_priv->ba_acc_rx = 0;
-+
-+ if (ba_ena != hw_priv->ba_ena) {
-+ if (ba_ena || ++hw_priv->ba_hist >= XRADIO_BLOCK_ACK_HIST) {
-+ hw_priv->ba_ena = ba_ena;
-+ hw_priv->ba_hist = 0;
-+#if 0
-+ sta_printk(XRADIO_DBG_NIY, "%s block ACK:\n",
-+ ba_ena ? "enable" : "disable");
-+ queue_work(hw_priv->workqueue, &hw_priv->ba_work);
-+#endif
-+ }
-+ } else if (hw_priv->ba_hist)
-+ --hw_priv->ba_hist;
-+
-+skip_statistic_update:
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+}
-+
-+int xradio_vif_setup(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+ int ret = 0;
-+
-+
-+ //reset channel change flag, yangfh 2015-5-15 17:12:14
-+ hw_priv->channel_changed = 0;
-+ /* Setup per vif workitems and locks */
-+ spin_lock_init(&priv->vif_lock);
-+ INIT_WORK(&priv->join_work, xradio_join_work);
-+ INIT_DELAYED_WORK(&priv->join_timeout, xradio_join_timeout);
-+ INIT_WORK(&priv->unjoin_work, xradio_unjoin_work);
-+ INIT_WORK(&priv->wep_key_work, xradio_wep_key_work);
-+ INIT_WORK(&priv->offchannel_work, xradio_offchannel_work);
-+ INIT_DELAYED_WORK(&priv->bss_loss_work, xradio_bss_loss_work);
-+ INIT_DELAYED_WORK(&priv->connection_loss_work, xradio_connection_loss_work);
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_NONE;
-+ spin_lock_init(&priv->bss_loss_lock);
-+ INIT_WORK(&priv->tx_failure_work, xradio_tx_failure_work);
-+ spin_lock_init(&priv->ps_state_lock);
-+ INIT_DELAYED_WORK(&priv->set_cts_work, xradio_set_cts_work);
-+ INIT_WORK(&priv->set_tim_work, xradio_set_tim_work);
-+ INIT_WORK(&priv->multicast_start_work, xradio_multicast_start_work);
-+ INIT_WORK(&priv->multicast_stop_work, xradio_multicast_stop_work);
-+ INIT_WORK(&priv->link_id_work, xradio_link_id_work);
-+ INIT_DELAYED_WORK(&priv->link_id_gc_work, xradio_link_id_gc_work);
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ INIT_WORK(&priv->linkid_reset_work, xradio_link_id_reset);
-+#endif
-+ INIT_WORK(&priv->update_filtering_work, xradio_update_filtering_work);
-+ INIT_DELAYED_WORK(&priv->pending_offchanneltx_work,
-+ xradio_pending_offchanneltx_work);
-+ INIT_WORK(&priv->set_beacon_wakeup_period_work,
-+ xradio_set_beacon_wakeup_period_work);
-+#ifdef AP_HT_CAP_UPDATE
-+ INIT_WORK(&priv->ht_oper_update_work, xradio_ht_oper_update_work);
-+#endif
-+ timer_setup(&priv->mcast_timeout, xradio_mcast_timeout, 0);
-+ priv->setbssparams_done = false;
-+ priv->power_set_true = 0;
-+ priv->user_power_set_true = 0;
-+ priv->user_pm_mode = 0;
-+
-+ /* Initialising the broadcast filter */
-+ memset(priv->broadcast_filter.MacAddr, 0xFF, ETH_ALEN);
-+ priv->broadcast_filter.nummacaddr = 1;
-+ priv->broadcast_filter.address_mode = 1;
-+ priv->broadcast_filter.filter_mode = 1;
-+ priv->htcap = false;
-+#ifdef AP_HT_COMPAT_FIX
-+ priv->ht_compat_det = 0;
-+ priv->ht_compat_cnt = 0;
-+#endif
-+
-+ sta_printk(XRADIO_DBG_ALWY, "!!!%s: id=%d, type=%d, p2p=%d\n",
-+ __func__, priv->if_id, priv->vif->type, priv->vif->p2p);
-+
-+ atomic_set(&priv->enabled, 1);
-+
-+ /* default EDCA */
-+ WSM_EDCA_SET(&priv->edca, 0, 0x0002, 0x0003, 0x0007,
-+ 47, 0xc8, false);
-+ WSM_EDCA_SET(&priv->edca, 1, 0x0002, 0x0007, 0x000f,
-+ 94, 0xc8, false);
-+
-+// if(priv->vif->p2p == true) {
-+ WSM_EDCA_SET(&priv->edca, 2, 0x0002, 0x0003, 0x0007,
-+ 0, 0xc8, false);
-+ sta_printk(XRADIO_DBG_MSG, "EDCA params Best effort for sta/p2p is " \
-+ "aifs=%u, cw_min=%u, cw_max=%u \n",
-+ priv->edca.params[2].aifns, priv->edca.params[2].cwMin,
-+ priv->edca.params[2].cwMax);
-+#if 0
-+ }else {
-+ WSM_EDCA_SET(&priv->edca, 2, 0x0003, 0x000f, 0x03ff,
-+ 0, 0xc8, false);
-+ sta_printk(XRADIO_DBG_MSG, "EDCA params Best effort for sta is " \
-+ "aifs=%u, cw_min=%u, cw_max=%u \n",
-+ priv->edca.params[2].aifns, priv->edca.params[2].cwMin,
-+ priv->edca.params[2].cwMax);
-+ }
-+#endif
-+ WSM_EDCA_SET(&priv->edca, 3, 0x0007, 0x000f, 0x03ff,
-+ 0, 0xc8, false);
-+
-+ ret = wsm_set_edca_params(hw_priv, &priv->edca, priv->if_id);
-+ if (WARN_ON(ret))
-+ goto out;
-+
-+ ret = xradio_set_uapsd_param(priv, &priv->edca);
-+ if (WARN_ON(ret))
-+ goto out;
-+
-+ memset(priv->bssid, ~0, ETH_ALEN);
-+ priv->wep_default_key_id = -1;
-+ priv->cipherType = 0;
-+ priv->cqm_link_loss_count = XRADIO_LINK_LOSS_THOLD_DEF;
-+ priv->cqm_beacon_loss_count = XRADIO_BSS_LOSS_THOLD_DEF;
-+
-+ /* Temporary configuration - beacon filter table */
-+ __xradio_bf_configure(priv);
-+
-+out:
-+ return ret;
-+}
-+
-+int xradio_setup_mac_pvif(struct xradio_vif *priv)
-+{
-+ int ret = 0;
-+ /* NOTE: There is a bug in FW: it reports signal
-+ * as RSSI if RSSI subscription is enabled.
-+ * It's not enough to set WSM_RCPI_RSSI_USE_RSSI. */
-+ /* NOTE2: RSSI based reports have been switched to RCPI, since
-+ * FW has a bug and RSSI reported values are not stable,
-+ * what can leads to signal level oscilations in user-end applications */
-+ struct wsm_rcpi_rssi_threshold threshold = {
-+ .rssiRcpiMode = WSM_RCPI_RSSI_THRESHOLD_ENABLE |
-+ WSM_RCPI_RSSI_DONT_USE_UPPER |
-+ WSM_RCPI_RSSI_DONT_USE_LOWER,
-+ .rollingAverageCount = 16,
-+ };
-+
-+
-+ /* Remember the decission here to make sure, we will handle
-+ * the RCPI/RSSI value correctly on WSM_EVENT_RCPI_RSS */
-+ if (threshold.rssiRcpiMode & WSM_RCPI_RSSI_USE_RSSI)
-+ priv->cqm_use_rssi = true;
-+
-+
-+ /* Configure RSSI/SCPI reporting as RSSI. */
-+ ret = wsm_set_rcpi_rssi_threshold(priv->hw_priv, &threshold, priv->if_id);
-+ return ret;
-+}
-+
-+void xradio_rem_chan_timeout(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, rem_chan_timeout.work);
-+ int ret, if_id;
-+ struct xradio_vif *priv;
-+
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ if(TES_P2P_0002_state == TES_P2P_0002_STATE_GET_PKTID) {
-+ sta_printk(XRADIO_DBG_WARN, "[Restart rem_chan_timeout:Timeout]\n");
-+ return;
-+ }
-+#endif
-+
-+ if (atomic_read(&hw_priv->remain_on_channel) == 0) {
-+ return;
-+ }
-+ ieee80211_remain_on_channel_expired(hw_priv->hw);
-+
-+ mutex_lock(&hw_priv->conf_mutex);
-+ if_id = hw_priv->roc_if_id;
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_ERROR, "ROC TO IN %d\n", if_id);
-+#endif
-+ priv = __xrwl_hwpriv_to_vifpriv(hw_priv, if_id);
-+ ret = WARN_ON(__xradio_flush(hw_priv, false, if_id));
-+ if (!ret) {
-+ xradio_disable_listening(priv);
-+ }
-+ atomic_set(&hw_priv->remain_on_channel, 0);
-+ hw_priv->roc_if_id = -1;
-+
-+#ifdef ROC_DEBUG
-+ sta_printk(XRADIO_DBG_ERROR, "ROC TO OUT %d\n", if_id);
-+#endif
-+
-+ mutex_unlock(&hw_priv->conf_mutex);
-+ up(&hw_priv->scan.lock);
-+}
-+const u8 *xradio_get_ie(u8 *start, size_t len, u8 ie)
-+{
-+ u8 *end, *pos;
-+
-+
-+ pos = start;
-+ if (pos == NULL)
-+ return NULL;
-+ end = pos + len;
-+
-+ while (pos + 1 < end) {
-+ if (pos + 2 + pos[1] > end)
-+ break;
-+ if (pos[0] == ie)
-+ return pos;
-+ pos += 2 + pos[1];
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * xradio_set_macaddrfilter -called when tesmode command
-+ * is for setting mac address filter
-+ *
-+ * @hw: the hardware
-+ * @data: incoming data
-+ *
-+ * Returns: 0 on success or non zero value on failure
-+ */
-+int xradio_set_macaddrfilter(struct xradio_common *hw_priv, struct xradio_vif *priv, u8 *data)
-+{
-+ struct wsm_mac_addr_filter *mac_addr_filter = NULL;
-+ struct wsm_mac_addr_info *addr_info = NULL;
-+ u8 action_mode = 0, no_of_mac_addr = 0, i = 0;
-+ int ret = 0;
-+ u16 macaddrfiltersize = 0;
-+
-+
-+ /* Retrieving Action Mode */
-+ action_mode = data[0];
-+ /* Retrieving number of address entries */
-+ no_of_mac_addr = data[1];
-+
-+ addr_info = (struct wsm_mac_addr_info *)&data[2];
-+
-+ /* Computing sizeof Mac addr filter */
-+ macaddrfiltersize = sizeof(*mac_addr_filter) + \
-+ (no_of_mac_addr * sizeof(struct wsm_mac_addr_info));
-+
-+ mac_addr_filter = kzalloc(macaddrfiltersize, GFP_KERNEL);
-+ if (!mac_addr_filter) {
-+ ret = -ENOMEM;
-+ goto exit_p;
-+ }
-+ mac_addr_filter->action_mode = action_mode;
-+ mac_addr_filter->numfilter = no_of_mac_addr;
-+
-+ for (i = 0; i < no_of_mac_addr; i++) {
-+ mac_addr_filter->macaddrfilter[i].address_mode = \
-+ addr_info[i].address_mode;
-+ memcpy(mac_addr_filter->macaddrfilter[i].MacAddr, \
-+ addr_info[i].MacAddr , ETH_ALEN);
-+ mac_addr_filter->macaddrfilter[i].filter_mode = \
-+ addr_info[i].filter_mode;
-+ }
-+ ret = WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_MAC_ADDR_FILTER, \
-+ mac_addr_filter, macaddrfiltersize, priv->if_id));
-+
-+ kfree(mac_addr_filter);
-+exit_p:
-+ return ret;
-+}
-+
-+/**
-+ * xradio_set_arpreply -called for creating and
-+ * configuring arp response template frame
-+ *
-+ * @hw: the hardware
-+ *
-+ * Returns: 0 on success or non zero value on failure
-+ */
-+int xradio_set_arpreply(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-+{
-+ struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
-+ struct xradio_common *hw_priv = (struct xradio_common *)hw->priv;
-+ u32 framehdrlen, encrypthdr, encrypttailsize, framebdylen = 0;
-+ bool encrypt = false;
-+ int ret = 0;
-+ u8 *template_frame = NULL;
-+ struct ieee80211_hdr_3addr *dot11hdr = NULL;
-+ struct ieee80211_snap_hdr *snaphdr = NULL;
-+ struct arphdr *arp_hdr = NULL;
-+
-+
-+ template_frame = kzalloc(MAX_ARP_REPLY_TEMPLATE_SIZE, GFP_KERNEL);
-+ if (!template_frame) {
-+ sta_printk(XRADIO_DBG_ERROR, "Template frame memory failed\n");
-+ ret = -ENOMEM;
-+ goto exit_p;
-+ }
-+ dot11hdr = (struct ieee80211_hdr_3addr *)&template_frame[4];
-+
-+ framehdrlen = sizeof(*dot11hdr);
-+ if ((priv->vif->type == NL80211_IFTYPE_AP) && priv->vif->p2p)
-+ priv->cipherType = WLAN_CIPHER_SUITE_CCMP;
-+ switch (priv->cipherType) {
-+
-+ case WLAN_CIPHER_SUITE_WEP40:
-+ case WLAN_CIPHER_SUITE_WEP104:
-+ sta_printk(XRADIO_DBG_NIY, "WEP\n");
-+ encrypthdr = WEP_ENCRYPT_HDR_SIZE;
-+ encrypttailsize = WEP_ENCRYPT_TAIL_SIZE;
-+ encrypt = 1;
-+ break;
-+
-+
-+ case WLAN_CIPHER_SUITE_TKIP:
-+ sta_printk(XRADIO_DBG_NIY, "WPA\n");
-+ encrypthdr = WPA_ENCRYPT_HDR_SIZE;
-+ encrypttailsize = WPA_ENCRYPT_TAIL_SIZE;
-+ encrypt = 1;
-+ break;
-+
-+ case WLAN_CIPHER_SUITE_CCMP:
-+ sta_printk(XRADIO_DBG_NIY, "WPA2\n");
-+ encrypthdr = WPA2_ENCRYPT_HDR_SIZE;
-+ encrypttailsize = WPA2_ENCRYPT_TAIL_SIZE;
-+ encrypt = 1;
-+ break;
-+
-+ case WLAN_CIPHER_SUITE_SMS4:
-+ sta_printk(XRADIO_DBG_NIY, "WAPI\n");
-+ encrypthdr = WAPI_ENCRYPT_HDR_SIZE;
-+ encrypttailsize = WAPI_ENCRYPT_TAIL_SIZE;
-+ encrypt = 1;
-+ break;
-+
-+ default:
-+ encrypthdr = 0;
-+ encrypttailsize = 0;
-+ encrypt = 0;
-+ break;
-+ }
-+
-+ framehdrlen += encrypthdr;
-+ /* Filling the 802.11 Hdr */
-+ dot11hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA);
-+ if (priv->vif->type == NL80211_IFTYPE_STATION)
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
-+ else
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
-+
-+ if (encrypt)
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_WEP);
-+
-+ if (priv->vif->bss_conf.qos) {
-+ sta_printk(XRADIO_DBG_NIY, "QOS Enabled\n");
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_QOS_DATAGRP);
-+ *(u16 *)(dot11hdr + 1) = 0x0;
-+ framehdrlen += 2;
-+ } else {
-+ dot11hdr->frame_control |= cpu_to_le16(IEEE80211_STYPE_DATA);
-+ }
-+
-+ memcpy(dot11hdr->addr1, priv->vif->bss_conf.bssid, ETH_ALEN);
-+ memcpy(dot11hdr->addr2, priv->vif->addr, ETH_ALEN);
-+ memcpy(dot11hdr->addr3, priv->vif->bss_conf.bssid, ETH_ALEN);
-+
-+ /* Filling the LLC/SNAP Hdr */
-+ snaphdr = (struct ieee80211_snap_hdr *)((u8 *)dot11hdr + framehdrlen);
-+ memcpy(snaphdr, (struct ieee80211_snap_hdr *)rfc1042_header, \
-+ sizeof(*snaphdr));
-+ *(u16 *)(++snaphdr) = cpu_to_be16(ETH_P_ARP);
-+ /* Updating the framebdylen with snaphdr and LLC hdr size */
-+ framebdylen = sizeof(*snaphdr) + 2;
-+
-+ /* Filling the ARP Reply Payload */
-+ arp_hdr = (struct arphdr *)((u8 *)dot11hdr + framehdrlen + framebdylen);
-+ arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER);
-+ arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP);
-+ arp_hdr->ar_hln = ETH_ALEN;
-+ arp_hdr->ar_pln = 4;
-+ arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY);
-+
-+ /* Updating the frmbdylen with Arp Reply Hdr and Arp payload size(20) */
-+ framebdylen += sizeof(*arp_hdr) + 20;
-+
-+ /* Updating the framebdylen with Encryption Tail Size */
-+ framebdylen += encrypttailsize;
-+
-+ /* Filling the Template Frame Hdr */
-+ template_frame[0] = WSM_FRAME_TYPE_ARP_REPLY; /* Template frame type */
-+ template_frame[1] = 0xFF; /* Rate to be fixed */
-+ ((u16 *)&template_frame[2])[0] = framehdrlen + framebdylen;
-+
-+ ret = WARN_ON(wsm_write_mib(hw_priv, WSM_MIB_ID_TEMPLATE_FRAME, \
-+ template_frame, (framehdrlen+framebdylen+4),
-+ priv->if_id));
-+ kfree(template_frame);
-+exit_p:
-+ return ret;
-+}
-+
-+#ifdef ROAM_OFFLOAD
-+/**
-+ * xradio_testmode_event -send asynchronous event
-+ * to userspace
-+ *
-+ * @wiphy: the wiphy
-+ * @msg_id: XR msg ID
-+ * @data: data to be sent
-+ * @len: data length
-+ * @gfp: allocation flag
-+ *
-+ * Returns: 0 on success or non zero value on failure
-+ */
-+int xradio_testmode_event(struct wiphy *wiphy, const u32 msg_id,
-+ const void *data, int len, gfp_t gfp)
-+{
-+ struct sk_buff *skb = NULL;
-+
-+
-+ skb = cfg80211_testmode_alloc_event_skb(wiphy,
-+ nla_total_size(len+sizeof(msg_id)), gfp);
-+
-+ if (!skb)
-+ return -ENOMEM;
-+
-+ cfg80211_testmode_event(skb, gfp);
-+ return 0;
-+}
-+#endif /*ROAM_OFFLOAD*/
-diff --git a/drivers/net/wireless/xradio/sta.h b/drivers/net/wireless/xradio/sta.h
-new file mode 100644
-index 0000000..42ea2f6
---- /dev/null
-+++ b/drivers/net/wireless/xradio/sta.h
-@@ -0,0 +1,122 @@
-+/*
-+ * sta interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef STA_H_INCLUDED
-+#define STA_H_INCLUDED
-+
-+
-+#ifdef XRADIO_USE_LONG_KEEP_ALIVE_PERIOD
-+#define XRADIO_KEEP_ALIVE_PERIOD (28)
-+#else
-+/*For Samsung, it is defined as 4*/
-+#define XRADIO_KEEP_ALIVE_PERIOD (4)
-+#endif
-+
-+#ifdef XRADIO_USE_LONG_DTIM_PERIOD
-+#define XRADIO_BSS_LOSS_THOLD_DEF 30
-+#define XRADIO_LINK_LOSS_THOLD_DEF 50
-+#else
-+#define XRADIO_BSS_LOSS_THOLD_DEF 20
-+#define XRADIO_LINK_LOSS_THOLD_DEF 40
-+#endif
-+
-+/* ******************************************************************** */
-+/* mac80211 API */
-+
-+int xradio_start(struct ieee80211_hw *dev);
-+void xradio_stop(struct ieee80211_hw *dev);
-+int xradio_add_interface(struct ieee80211_hw *dev, struct ieee80211_vif *vif);
-+void xradio_remove_interface(struct ieee80211_hw *dev, struct ieee80211_vif *vif);
-+int xradio_change_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ enum nl80211_iftype new_type,
-+ bool p2p);
-+int xradio_config(struct ieee80211_hw *dev, u32 changed);
-+int xradio_change_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ enum nl80211_iftype new_type,
-+ bool p2p);
-+void xradio_configure_filter(struct ieee80211_hw *dev,
-+ unsigned int changed_flags,
-+ unsigned int *total_flags,
-+ u64 multicast);
-+int xradio_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
-+ u16 queue, const struct ieee80211_tx_queue_params *params);
-+int xradio_get_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_low_level_stats *stats);
-+/* Not more a part of interface?
-+int xradio_get_tx_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_tx_queue_stats *stats);
-+*/
-+int xradio_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
-+
-+void xradio_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop);
-+
-+
-+int xradio_remain_on_channel(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_channel *chan,
-+ int duration, enum ieee80211_roc_type type);
-+int xradio_cancel_remain_on_channel(struct ieee80211_hw *hw);
-+int xradio_set_arpreply(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-+u64 xradio_prepare_multicast(struct ieee80211_hw *hw,
-+ struct netdev_hw_addr_list *mc_list);
-+int xradio_set_pm(struct xradio_vif *priv, const struct wsm_set_pm *arg);
-+void xradio_set_data_filter(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ void *data,
-+ int len);
-+
-+/* ******************************************************************** */
-+/* WSM callbacks */
-+
-+/* void xradio_set_pm_complete_cb(struct xradio_common *hw_priv,
-+ struct wsm_set_pm_complete *arg); */
-+void xradio_channel_switch_cb(struct xradio_common *hw_priv);
-+
-+/* ******************************************************************** */
-+/* WSM events */
-+
-+void xradio_free_event_queue(struct xradio_common *hw_priv);
-+void xradio_event_handler(struct work_struct *work);
-+void xradio_bss_loss_work(struct work_struct *work);
-+void xradio_connection_loss_work(struct work_struct *work);
-+void xradio_keep_alive_work(struct work_struct *work);
-+void xradio_tx_failure_work(struct work_struct *work);
-+
-+/* ******************************************************************** */
-+/* Internal API */
-+
-+int xradio_setup_mac(struct xradio_common *hw_priv);
-+void xradio_join_work(struct work_struct *work);
-+void xradio_join_timeout(struct work_struct *work);
-+void xradio_unjoin_work(struct work_struct *work);
-+void xradio_offchannel_work(struct work_struct *work);
-+void xradio_wep_key_work(struct work_struct *work);
-+void xradio_update_filtering(struct xradio_vif *priv);
-+void xradio_update_filtering_work(struct work_struct *work);
-+int __xradio_flush(struct xradio_common *hw_priv, bool drop, int if_id);
-+void xradio_set_beacon_wakeup_period_work(struct work_struct *work);
-+int xradio_enable_listening(struct xradio_vif *priv, struct ieee80211_channel *chan);
-+int xradio_disable_listening(struct xradio_vif *priv);
-+int xradio_set_uapsd_param(struct xradio_vif *priv, const struct wsm_edca_params *arg);
-+void xradio_ba_work(struct work_struct *work);
-+void xradio_ba_timer(struct timer_list *t);
-+const u8 *xradio_get_ie(u8 *start, size_t len, u8 ie);
-+int xradio_vif_setup(struct xradio_vif *priv);
-+int xradio_setup_mac_pvif(struct xradio_vif *priv);
-+void xradio_iterate_vifs(void *data, u8 *mac, struct ieee80211_vif *vif);
-+void xradio_rem_chan_timeout(struct work_struct *work);
-+int xradio_set_macaddrfilter(struct xradio_common *hw_priv, struct xradio_vif *priv, u8 *data);
-+#ifdef ROAM_OFFLOAD
-+int xradio_testmode_event(struct wiphy *wiphy, const u32 msg_id,
-+ const void *data, int len, gfp_t gfp);
-+#endif /*ROAM_OFFLOAD*/
-+#endif
-diff --git a/drivers/net/wireless/xradio/tx.c b/drivers/net/wireless/xradio/tx.c
-new file mode 100644
-index 0000000..72c04ef
---- /dev/null
-+++ b/drivers/net/wireless/xradio/tx.c
-@@ -0,0 +1,1455 @@
-+/*
-+ * Datapath implementation for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "wsm.h"
-+#include "bh.h"
-+#include "ap.h"
-+#include "sta.h"
-+#include "sdio.h"
-+#include "common.h"
-+#include "p2p.h"
-+
-+#define B_RATE_INDEX 0 //11b rate for important short frames in 2.4G.
-+#define AG_RATE_INDEX 6 //11a/g rate for important short frames in 5G.
-+#define XRADIO_INVALID_RATE_ID (0xFF)
-+
-+/* rate should fall quickly to avoid dropping frames by aps.
-+ * Add by yangfh 2014-9-22 13:39:57
-+ */
-+#define HIGH_RATE_MAX_RETRY 7
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+#include
-+#endif
-+
-+//for test yangfh
-+extern u32 tx_retrylimit;
-+extern u32 tx_over_limit;
-+extern u32 tx_lower_limit;
-+extern int retry_mis;
-+
-+static const struct ieee80211_rate *
-+xradio_get_tx_rate(const struct xradio_common *hw_priv,
-+ const struct ieee80211_tx_rate *rate);
-+
-+/* ******************************************************************** */
-+/* TX policy cache implementation */
-+
-+static void tx_policy_dump(struct tx_policy *policy)
-+{
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] "
-+ "%.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X"
-+ "%.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X"
-+ "%.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X: %d\n",
-+ policy->raw[0] & 0x0F, policy->raw[0] >> 4,
-+ policy->raw[1] & 0x0F, policy->raw[1] >> 4,
-+ policy->raw[2] & 0x0F, policy->raw[2] >> 4,
-+ policy->raw[3] & 0x0F, policy->raw[3] >> 4,
-+ policy->raw[4] & 0x0F, policy->raw[4] >> 4,
-+ policy->raw[5] & 0x0F, policy->raw[5] >> 4,
-+ policy->raw[6] & 0x0F, policy->raw[6] >> 4,
-+ policy->raw[7] & 0x0F, policy->raw[7] >> 4,
-+ policy->raw[8] & 0x0F, policy->raw[8] >> 4,
-+ policy->raw[9] & 0x0F, policy->raw[9] >> 4,
-+ policy->raw[10] & 0x0F, policy->raw[10] >> 4,
-+ policy->raw[11] & 0x0F, policy->raw[11] >> 4,
-+ policy->defined);
-+}
-+
-+static void xradio_check_go_neg_conf_success(struct xradio_common *hw_priv,
-+ u8 *action)
-+{
-+ if (action[2] == 0x50 && action[3] == 0x6F && action[4] == 0x9A &&
-+ action[5] == 0x09 && action[6] == 0x02) {
-+ if(action[17] == 0) {
-+ hw_priv->is_go_thru_go_neg = true;
-+ }
-+ else {
-+ hw_priv->is_go_thru_go_neg = false;
-+ }
-+ }
-+}
-+
-+static void xradio_check_prov_desc_req(struct xradio_common *hw_priv,
-+ u8 *action)
-+{
-+ if (action[2] == 0x50 && action[3] == 0x6F && action[4] == 0x9A &&
-+ action[5] == 0x09 && action[6] == 0x07) {
-+ hw_priv->is_go_thru_go_neg = false;
-+ }
-+}
-+
-+//modified by yangfh
-+static void tx_policy_build(const struct xradio_common *hw_priv,
-+ /* [out] */ struct tx_policy *policy,
-+ struct ieee80211_tx_rate *rates, size_t count)
-+{
-+ int i, j;
-+ struct ieee80211_rate * tmp_rate = NULL;
-+ unsigned limit = hw_priv->short_frame_max_tx_count;
-+ unsigned max_rates_cnt = count;
-+ unsigned total = 0;
-+ BUG_ON(rates[0].idx < 0);
-+ memset(policy, 0, sizeof(*policy));
-+
-+
-+ txrx_printk(XRADIO_DBG_NIY,"============================");
-+#if 0
-+ //debug yangfh
-+ for (i = 0; i < count; ++i) {
-+ if(rates[i].idx>=0) {
-+ tmp_rate = xradio_get_tx_rate(hw_priv, &rates[i]);
-+ txrx_printk(XRADIO_DBG_NIY,"[TX policy] Org %d.%dMps=%d",
-+ tmp_rate->bitrate/10, tmp_rate->bitrate%10, rates[i].count);
-+ }
-+ }
-+ txrx_printk(XRADIO_DBG_NIY,"----------------------------");
-+#endif
-+
-+ /* minstrel is buggy a little bit, so distille
-+ * incoming rates first.
-+ */
-+ /* Sort rates in descending order. */
-+ total = rates[0].count;
-+ for (i = 1; i < count; ++i) {
-+ if (rates[i].idx > rates[i-1].idx) {
-+ rates[i].idx = rates[i-1].idx>0?(rates[i-1].idx-1):-1;
-+ }
-+ if (rates[i].idx < 0 || i>=limit) {
-+ count = i;
-+ break;
-+ } else {
-+ total += rates[i].count;
-+ }
-+ }
-+
-+ /* Add lowest rate to the end when 11a/n.
-+ * Don't apply in 11b/g because p2p unsupport 1Mbps.
-+ * TODO: it's better to do this in rate control of mac80211.
-+ */
-+ if (((rates[0].flags & IEEE80211_TX_RC_MCS) ||
-+ hw_priv->channel->band == NL80211_BAND_5GHZ) &&
-+ count < max_rates_cnt && rates[count-1].idx != 0) {
-+ rates[count].idx = 0;
-+ rates[count].count = rates[0].count;
-+ rates[count].flags = rates[0].flags;
-+ total += rates[count].count;
-+ count++;
-+ }
-+
-+ /* adjust tx count to limit, rates should fall quickly
-+ * and lower rates should be more retry, because reorder
-+ * buffer of reciever will be timeout and clear probably.
-+ */
-+ if (count < 2) {
-+ rates[0].count = limit;
-+ total = limit;
-+ } else {
-+ u8 end_retry = 0; //the retry should be add to last rate.
-+ if (limit > HIGH_RATE_MAX_RETRY) {
-+ end_retry = limit - HIGH_RATE_MAX_RETRY;
-+ limit = HIGH_RATE_MAX_RETRY;
-+ }
-+ for (i = 0; (limit != total) && (i < 100); ++i) { //i<100 to avoid dead loop
-+ j = i % count;
-+ if(limit < total) {
-+ total += (rates[j].count > 1? -1 : 0);
-+ rates[j].count += (rates[j].count > 1? -1 : 0);
-+ } else {
-+ j = count - 1 - j;
-+ if (rates[j].count > 0) {
-+ total++;
-+ rates[j].count++;
-+ }
-+ }
-+ }
-+ if (end_retry) {
-+ rates[count-1].count += end_retry;
-+ limit += end_retry;
-+ }
-+ }
-+
-+ /* Eliminate duplicates. */
-+ total = rates[0].count;
-+ for (i = 0, j = 1; j < count; ++j) {
-+ if (rates[j].idx == rates[i].idx) {
-+ rates[i].count += rates[j].count;
-+ } else if (rates[j].idx > rates[i].idx) {
-+ break;
-+ } else {
-+ ++i;
-+ if (i != j)
-+ rates[i] = rates[j];
-+ }
-+ total += rates[j].count;
-+ }
-+ count = i + 1;
-+
-+ /* Re-fill policy trying to keep every requested rate and with
-+ * respect to the global max tx retransmission count.
-+ */
-+ if (limit < count)
-+ limit = count;
-+ if (total > limit) {
-+ for (i = 0; i < count; ++i) {
-+ int left = count - i - 1;
-+ if (rates[i].count > limit - left)
-+ rates[i].count = limit - left;
-+ limit -= rates[i].count;
-+ }
-+ }
-+
-+ /* HACK!!! Device has problems (at least) switching from
-+ * 54Mbps CTS to 1Mbps. This switch takes enormous amount
-+ * of time (100-200 ms), leading to valuable throughput drop.
-+ * As a workaround, additional g-rates are injected to the
-+ * policy.
-+ */
-+ if (count == 2 && !(rates[0].flags & IEEE80211_TX_RC_MCS) &&
-+ rates[0].idx > 4 && rates[0].count > 2 &&
-+ rates[1].idx < 2) {
-+ /* ">> 1" is an equivalent of "/ 2", but faster */
-+ int mid_rate = (rates[0].idx + 4) >> 1;
-+
-+ /* Decrease number of retries for the initial rate */
-+ rates[0].count -= 2;
-+
-+ if (mid_rate != 4) {
-+ /* Keep fallback rate at 1Mbps. */
-+ rates[3] = rates[1];
-+
-+ /* Inject 1 transmission on lowest g-rate */
-+ rates[2].idx = 4;
-+ rates[2].count = 1;
-+ rates[2].flags = rates[1].flags;
-+
-+ /* Inject 1 transmission on mid-rate */
-+ rates[1].idx = mid_rate;
-+ rates[1].count = 1;
-+
-+ /* Fallback to 1 Mbps is a really bad thing,
-+ * so let's try to increase probability of
-+ * successful transmission on the lowest g rate
-+ * even more */
-+ if (rates[0].count >= 3) {
-+ --rates[0].count;
-+ ++rates[2].count;
-+ }
-+
-+ /* Adjust amount of rates defined */
-+ count += 2;
-+ } else {
-+ /* Keep fallback rate at 1Mbps. */
-+ rates[2] = rates[1];
-+
-+ /* Inject 2 transmissions on lowest g-rate */
-+ rates[1].idx = 4;
-+ rates[1].count = 2;
-+
-+ /* Adjust amount of rates defined */
-+ count += 1;
-+ }
-+ }
-+
-+ tmp_rate = (struct ieee80211_rate *)xradio_get_tx_rate(hw_priv, &rates[0]);
-+ if(tmp_rate)
-+ policy->defined = tmp_rate->hw_value + 1;
-+
-+ for (i = 0; i < count; ++i) {
-+ register unsigned rateid, off, shift, retries;
-+
-+ tmp_rate = (struct ieee80211_rate *)xradio_get_tx_rate(hw_priv, &rates[i]);
-+ if(tmp_rate) {
-+ rateid = tmp_rate->hw_value;
-+ } else {
-+ break;
-+ }
-+ off = rateid >> 3; /* eq. rateid / 8 */
-+ shift = (rateid & 0x07) << 2; /* eq. (rateid % 8) * 4 */
-+
-+ retries = rates[i].count;
-+ if (unlikely(retries > 0x0F))
-+ rates[i].count = retries = 0x0F;
-+ policy->tbl[off] |= __cpu_to_le32(retries << shift);
-+ policy->retry_count += retries;
-+ txrx_printk(XRADIO_DBG_NIY,"[TX policy] %d.%dMps=%d",
-+ tmp_rate->bitrate/10, tmp_rate->bitrate%10, retries);
-+ }
-+
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] Dst Policy (%d): " \
-+ "%d:%d, %d:%d, %d:%d, %d:%d, %d:%d\n",
-+ count,
-+ rates[0].idx, rates[0].count,
-+ rates[1].idx, rates[1].count,
-+ rates[2].idx, rates[2].count,
-+ rates[3].idx, rates[3].count,
-+ rates[4].idx, rates[4].count);
-+}
-+
-+static inline bool tx_policy_is_equal(const struct tx_policy *wanted,
-+ const struct tx_policy *cached)
-+{
-+ size_t count = wanted->defined >> 1;
-+
-+ if (wanted->defined > cached->defined)
-+ return false;
-+ if (count) {
-+ if (memcmp(wanted->raw, cached->raw, count))
-+ return false;
-+ }
-+ if (wanted->defined & 1) {
-+ if ((wanted->raw[count] & 0x0F) != (cached->raw[count] & 0x0F))
-+ return false;
-+ }
-+ return true;
-+}
-+
-+static int tx_policy_find(struct tx_policy_cache *cache,
-+ const struct tx_policy *wanted)
-+{
-+ /* O(n) complexity. Not so good, but there's only 8 entries in
-+ * the cache.
-+ * Also lru helps to reduce search time. */
-+ struct tx_policy_cache_entry *it;
-+ /* Search for policy in "used" list */
-+ list_for_each_entry(it, &cache->used, link) {
-+ if (tx_policy_is_equal(wanted, &it->policy))
-+ return it - cache->cache;
-+ }
-+ /* Then - in "free list" */
-+ list_for_each_entry(it, &cache->free, link) {
-+ if (tx_policy_is_equal(wanted, &it->policy))
-+ return it - cache->cache;
-+ }
-+ return -1;
-+}
-+
-+static inline void tx_policy_use(struct tx_policy_cache *cache,
-+ struct tx_policy_cache_entry *entry)
-+{
-+ ++entry->policy.usage_count;
-+ list_move(&entry->link, &cache->used);
-+}
-+
-+static inline int tx_policy_release(struct tx_policy_cache *cache,
-+ struct tx_policy_cache_entry *entry)
-+{
-+ int ret = --entry->policy.usage_count;
-+ if (!ret)
-+ list_move(&entry->link, &cache->free);
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+/* External TX policy cache API */
-+
-+void tx_policy_init(struct xradio_common *hw_priv)
-+{
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+ int i;
-+
-+ memset(cache, 0, sizeof(*cache));
-+
-+ spin_lock_init(&cache->lock);
-+ INIT_LIST_HEAD(&cache->used);
-+ INIT_LIST_HEAD(&cache->free);
-+
-+ for (i = 0; i < TX_POLICY_CACHE_SIZE; ++i)
-+ list_add(&cache->cache[i].link, &cache->free);
-+}
-+
-+static int tx_policy_get(struct xradio_common *hw_priv,
-+ struct ieee80211_tx_rate *rates,
-+ u8 use_bg_rate, bool *renew)
-+{
-+ int idx;
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+ struct tx_policy wanted;
-+
-+
-+ if(use_bg_rate) {
-+ u8 rate = (u8)(use_bg_rate & 0x3f);
-+ u8 shitf = ((rate&0x7)<<2);
-+ u8 off = (rate>>3);
-+ memset(&wanted, 0, sizeof(wanted));
-+ wanted.defined = rate + 1;
-+ wanted.retry_count = (hw_priv->short_frame_max_tx_count&0xf);
-+ wanted.tbl[off] = wanted.retry_count<lock);
-+ idx = tx_policy_find(cache, &wanted);
-+ if (idx >= 0) {
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] Used TX policy: %d\n",
-+ idx);
-+ *renew = false;
-+ } else {
-+ struct tx_policy_cache_entry *entry;
-+ if (WARN_ON_ONCE(list_empty(&cache->free))) {
-+ spin_unlock_bh(&cache->lock);
-+ txrx_printk(XRADIO_DBG_ERROR, "[TX policy] no policy cache\n");
-+ return XRADIO_INVALID_RATE_ID;
-+ }
-+ /* If policy is not found create a new one
-+ * using the oldest entry in "free" list */
-+ *renew = true;
-+ entry = list_entry(cache->free.prev,
-+ struct tx_policy_cache_entry, link);
-+ entry->policy = wanted;
-+ idx = entry - cache->cache;
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] New TX policy: %d\n",
-+ idx);
-+ tx_policy_dump(&entry->policy);
-+ }
-+ tx_policy_use(cache, &cache->cache[idx]);
-+ if (unlikely(list_empty(&cache->free))) {
-+ /* Lock TX queues. */
-+ txrx_printk(XRADIO_DBG_WARN, "[TX policy] policy cache used up\n");
-+ xradio_tx_queues_lock(hw_priv);
-+ }
-+ spin_unlock_bh(&cache->lock);
-+
-+ return idx;
-+}
-+
-+static void tx_policy_put(struct xradio_common *hw_priv, int idx)
-+{
-+ int usage, locked;
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+
-+ spin_lock_bh(&cache->lock);
-+ locked = list_empty(&cache->free);
-+ usage = tx_policy_release(cache, &cache->cache[idx]);
-+ if (unlikely(locked) && !usage) {
-+ /* Unlock TX queues. */
-+ xradio_tx_queues_unlock(hw_priv);
-+ }
-+ spin_unlock_bh(&cache->lock);
-+}
-+
-+/*
-+bool tx_policy_cache_full(struct xradio_common *hw_priv)
-+{
-+ bool ret;
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+ spin_lock_bh(&cache->lock);
-+ ret = list_empty(&cache->free);
-+ spin_unlock_bh(&cache->lock);
-+ return ret;
-+}
-+*/
-+extern u32 policy_upload;
-+extern u32 policy_num;
-+static int tx_policy_upload(struct xradio_common *hw_priv)
-+{
-+ struct tx_policy_cache *cache = &hw_priv->tx_policy_cache;
-+ int i;
-+ struct wsm_set_tx_rate_retry_policy arg = {
-+ .hdr = {
-+ .numTxRatePolicies = 0,
-+ }
-+ };
-+ int if_id = 0;
-+
-+ spin_lock_bh(&cache->lock);
-+ /* Upload only modified entries. */
-+ for (i = 0; i < TX_POLICY_CACHE_SIZE; ++i) {
-+ struct tx_policy *src = &cache->cache[i].policy;
-+ if (src->retry_count && !src->uploaded) {
-+ struct wsm_set_tx_rate_retry_policy_policy *dst =
-+ &arg.tbl[arg.hdr.numTxRatePolicies];
-+ dst->policyIndex = i;
-+ dst->shortRetryCount = hw_priv->short_frame_max_tx_count-1;
-+ //only RTS need use longRetryCount, should be short_frame.
-+ dst->longRetryCount = hw_priv->short_frame_max_tx_count-1;
-+
-+ /* BIT(2) - Terminate retries when Tx rate retry policy
-+ * finishes.
-+ * BIT(3) - Count initial frame transmission as part of
-+ * rate retry counting but not as a retry
-+ * attempt */
-+ dst->policyFlags = BIT(2) | BIT(3);
-+ memcpy(dst->rateCountIndices, src->tbl,
-+ sizeof(dst->rateCountIndices));
-+ src->uploaded = 1;
-+ ++arg.hdr.numTxRatePolicies;
-+ }
-+ }
-+ spin_unlock_bh(&cache->lock);
-+ atomic_set(&hw_priv->upload_count, 0);
-+
-+ txrx_printk(XRADIO_DBG_MSG, "[TX policy] Upload %d policies\n",
-+ arg.hdr.numTxRatePolicies);
-+
-+ /*TODO: COMBO*/
-+ return wsm_set_tx_rate_retry_policy(hw_priv, &arg, if_id);
-+}
-+
-+void tx_policy_upload_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, tx_policy_upload_work);
-+
-+ WARN_ON(tx_policy_upload(hw_priv));
-+ wsm_unlock_tx(hw_priv);
-+}
-+
-+/* ******************************************************************** */
-+/* xradio TX implementation */
-+
-+struct xradio_txinfo {
-+ struct sk_buff *skb;
-+ unsigned queue;
-+ struct ieee80211_tx_info *tx_info;
-+ const struct ieee80211_rate *rate;
-+ struct ieee80211_hdr *hdr;
-+ size_t hdrlen;
-+ const u8 *da;
-+ struct xradio_sta_priv *sta_priv;
-+ struct xradio_txpriv txpriv;
-+};
-+
-+u32 xradio_rate_mask_to_wsm(struct xradio_common *hw_priv, u32 rates)
-+{
-+ u32 ret = 0;
-+ int i;
-+ u32 n_bitrates =
-+ hw_priv->hw->wiphy->bands[hw_priv->channel->band]->n_bitrates;
-+ struct ieee80211_rate * bitrates =
-+ hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates;
-+
-+ for (i = 0; i < n_bitrates; ++i) {
-+ if (rates & BIT(i))
-+ ret |= BIT(bitrates[i].hw_value);
-+ }
-+ return ret;
-+}
-+
-+static const struct ieee80211_rate *
-+xradio_get_tx_rate(const struct xradio_common *hw_priv,
-+ const struct ieee80211_tx_rate *rate)
-+{
-+ if (rate->idx < 0)
-+ return NULL;
-+ if (rate->flags & IEEE80211_TX_RC_MCS)
-+ return &hw_priv->mcs_rates[rate->idx];
-+ return &hw_priv->hw->wiphy->bands[hw_priv->channel->band]->
-+ bitrates[rate->idx];
-+}
-+
-+inline static s8
-+xradio_get_rate_idx(const struct xradio_common *hw_priv, u8 flag, u16 hw_value)
-+{
-+ s16 ret = (s16)hw_value;
-+ if(flag & IEEE80211_TX_RC_MCS) { //11n
-+ if(hw_value <= hw_priv->mcs_rates[7].hw_value &&
-+ hw_value >= hw_priv->mcs_rates[0].hw_value)
-+ ret -= hw_priv->mcs_rates[0].hw_value;
-+ else
-+ ret = -1;
-+ } else { //11b/g
-+ if(hw_value>5 && hw_valuemcs_rates[0].hw_value) {
-+ ret -= hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates[0].hw_value;
-+ if(hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates[0].hw_value<5) //11a
-+ ret -= 2;
-+ } else if(hw_value<4) {
-+ ret -= hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates[0].hw_value;
-+ } else {
-+ ret = -1;
-+ }
-+ }
-+ return (s8)ret;
-+}
-+
-+static int
-+xradio_tx_h_calc_link_ids(struct xradio_vif *priv,
-+ struct ieee80211_tx_control *control,
-+ struct xradio_txinfo *t)
-+{
-+
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ if ((t->tx_info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
-+ (hw_priv->roc_if_id == priv->if_id))
-+ t->txpriv.offchannel_if_id = 2;
-+ else
-+ t->txpriv.offchannel_if_id = 0;
-+
-+ if (likely(control->sta && t->sta_priv->link_id))
-+ t->txpriv.raw_link_id =
-+ t->txpriv.link_id =
-+ t->sta_priv->link_id;
-+ else if (priv->mode != NL80211_IFTYPE_AP)
-+ t->txpriv.raw_link_id =
-+ t->txpriv.link_id = 0;
-+ else if (is_multicast_ether_addr(t->da)) {
-+ if (priv->enable_beacon) {
-+ t->txpriv.raw_link_id = 0;
-+ t->txpriv.link_id = priv->link_id_after_dtim;
-+ } else {
-+ t->txpriv.raw_link_id = 0;
-+ t->txpriv.link_id = 0;
-+ }
-+ } else {
-+ t->txpriv.link_id =
-+ xradio_find_link_id(priv, t->da);
-+ /* Do not assign valid link id for deauth/disassoc frame being
-+ transmitted to an unassociated STA */
-+ if (!(t->txpriv.link_id) &&
-+ (ieee80211_is_deauth(t->hdr->frame_control) ||
-+ ieee80211_is_disassoc(t->hdr->frame_control))) {
-+ t->txpriv.link_id = 0;
-+ } else {
-+ if (!t->txpriv.link_id)
-+ t->txpriv.link_id = xradio_alloc_link_id(priv, t->da);
-+ if (!t->txpriv.link_id) {
-+ txrx_printk(XRADIO_DBG_ERROR,
-+ "%s: No more link IDs available.\n", __func__);
-+ return -ENOENT;
-+ }
-+ }
-+ t->txpriv.raw_link_id = t->txpriv.link_id;
-+ }
-+ if (t->txpriv.raw_link_id)
-+ priv->link_id_db[t->txpriv.raw_link_id - 1].timestamp =
-+ jiffies;
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ if (control->sta &&
-+ (control->sta->uapsd_queues & BIT(t->queue)))
-+ t->txpriv.link_id = priv->link_id_uapsd;
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+ return 0;
-+}
-+
-+static void
-+xradio_tx_h_pm(struct xradio_vif *priv,
-+ struct xradio_txinfo *t)
-+{
-+ if (unlikely(ieee80211_is_auth(t->hdr->frame_control))) {
-+ u32 mask = ~BIT(t->txpriv.raw_link_id);
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->sta_asleep_mask &= mask;
-+ priv->pspoll_mask &= mask;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ }
-+}
-+
-+static void
-+xradio_tx_h_calc_tid(struct xradio_vif *priv,
-+ struct xradio_txinfo *t)
-+{
-+ if (ieee80211_is_data_qos(t->hdr->frame_control)) {
-+ u8 *qos = ieee80211_get_qos_ctl(t->hdr);
-+ t->txpriv.tid = qos[0] & IEEE80211_QOS_CTL_TID_MASK;
-+ } else if (ieee80211_is_data(t->hdr->frame_control)) {
-+ t->txpriv.tid = 0;
-+ }
-+}
-+
-+/* IV/ICV injection. */
-+/* TODO: Quite unoptimal. It's better co modify mac80211
-+ * to reserve space for IV */
-+static int
-+xradio_tx_h_crypt(struct xradio_vif *priv,
-+ struct xradio_txinfo *t)
-+{
-+ size_t iv_len;
-+ size_t icv_len;
-+ u8 *icv;
-+
-+ if (!t->tx_info->control.hw_key ||
-+ !(t->hdr->frame_control &
-+ __cpu_to_le32(IEEE80211_FCTL_PROTECTED)))
-+ return 0;
-+
-+ iv_len = t->tx_info->control.hw_key->iv_len;
-+ icv_len = t->tx_info->control.hw_key->icv_len;
-+
-+ if (t->tx_info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
-+ icv_len += 8; /* MIC */
-+
-+ if (unlikely((skb_headroom(t->skb) + skb_tailroom(t->skb) <
-+ iv_len + icv_len + WSM_TX_EXTRA_HEADROOM) ||
-+ (skb_headroom(t->skb) <
-+ iv_len + WSM_TX_EXTRA_HEADROOM))) {
-+ dev_dbg(priv->hw_priv->pdev,
-+ "no space allocated for crypto headers.\n"
-+ "headroom: %d, tailroom: %d, "
-+ "req_headroom: %d, req_tailroom: %d\n"
-+ "Please fix it in xradio_get_skb().\n",
-+ skb_headroom(t->skb), skb_tailroom(t->skb),
-+ iv_len + WSM_TX_EXTRA_HEADROOM, icv_len);
-+ return -ENOMEM;
-+ } else if (unlikely(skb_tailroom(t->skb) < icv_len)) {
-+ size_t offset = icv_len - skb_tailroom(t->skb);
-+ u8 *p;
-+ dev_dbg(priv->hw_priv->pdev,
-+ "Slowpath: tailroom is not big enough. "
-+ "Req: %d, got: %d.\n",
-+ icv_len, skb_tailroom(t->skb));
-+
-+ p = skb_push(t->skb, offset);
-+ memmove(p, &p[offset], t->skb->len - offset);
-+ skb_trim(t->skb, t->skb->len - offset);
-+ }
-+ /* ccmp pkt from umac to driver,it has iv room,,so ccmp pkt do not add iv room */
-+ if (t->tx_info->control.hw_key->cipher != WLAN_CIPHER_SUITE_CCMP){
-+ u8 *newhdr;
-+ newhdr = skb_push(t->skb, iv_len);
-+ memmove(newhdr, newhdr + iv_len, t->hdrlen);
-+ t->hdr = (struct ieee80211_hdr *) newhdr;
-+ }
-+ t->hdrlen += iv_len;
-+ icv = skb_put(t->skb, icv_len);
-+
-+ return 0;
-+}
-+
-+static int
-+xradio_tx_h_align(struct xradio_vif *priv, struct xradio_txinfo *t,
-+ u8 *flags)
-+{
-+ size_t offset = (size_t)t->skb->data & 3;
-+ u8 *newhdr;//add by dingxh
-+
-+
-+ if (!offset)
-+ return 0;
-+
-+ if (skb_headroom(t->skb) < offset) {
-+ txrx_printk(XRADIO_DBG_ERROR,
-+ "Bug: no space allocated "
-+ "for DMA alignment.\n"
-+ "headroom: %d\n",
-+ skb_headroom(t->skb));
-+ return -ENOMEM;
-+ }
-+ //offset = 1or3 process add by dingxh
-+ if (offset & 1) {
-+ newhdr = skb_push(t->skb, offset);
-+ memmove(newhdr, newhdr + offset, t->skb->len-offset);
-+ skb_trim(t->skb, t->skb->len-offset);
-+ t->hdr = (struct ieee80211_hdr *) newhdr;
-+ return 0;
-+ }
-+ //add by dingxh
-+ //offset=2 process
-+ skb_push(t->skb, offset);
-+ t->hdrlen += offset;
-+ t->txpriv.offset += offset;
-+ *flags |= WSM_TX_2BYTES_SHIFT;
-+ return 0;
-+}
-+
-+static int
-+xradio_tx_h_action(struct xradio_vif *priv, struct xradio_txinfo *t)
-+{
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)t->hdr;
-+
-+ if (ieee80211_is_action(t->hdr->frame_control) &&
-+ mgmt->u.action.category == WLAN_CATEGORY_BACK)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+/* Add WSM header */
-+static struct wsm_tx *
-+xradio_tx_h_wsm(struct xradio_vif *priv, struct xradio_txinfo *t)
-+{
-+ struct wsm_tx *wsm;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ if (skb_headroom(t->skb) < sizeof(struct wsm_tx)) {
-+ txrx_printk(XRADIO_DBG_ERROR,
-+ "Bug: no space allocated "
-+ "for WSM header.\n"
-+ "headroom: %d\n",
-+ skb_headroom(t->skb));
-+ return NULL;
-+ }
-+
-+ wsm = (struct wsm_tx *)skb_push(t->skb, sizeof(struct wsm_tx));
-+ t->txpriv.offset += sizeof(struct wsm_tx);
-+ memset(wsm, 0, sizeof(*wsm));
-+ wsm->hdr.len = __cpu_to_le16(t->skb->len);
-+ wsm->hdr.id = __cpu_to_le16(0x0004);
-+ wsm->queueId = (t->txpriv.raw_link_id << 2) | wsm_queue_id_to_wsm(t->queue);
-+ if (wsm->hdr.len > hw_priv->wsm_caps.sizeInpChBuf) {
-+ txrx_printk(XRADIO_DBG_ERROR,"%s,msg length too big=%d\n",
-+ __func__, wsm->hdr.len);
-+ wsm = NULL;
-+ }
-+
-+ return wsm;
-+}
-+
-+/* BT Coex specific handling */
-+static void
-+xradio_tx_h_bt(struct xradio_vif *priv, struct xradio_txinfo *t, struct wsm_tx *wsm)
-+{
-+ u8 priority = 0;
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ if (!hw_priv->is_BT_Present)
-+ return;
-+
-+ if (unlikely(ieee80211_is_nullfunc(t->hdr->frame_control)))
-+ priority = WSM_EPTA_PRIORITY_MGT;
-+ else if (ieee80211_is_data(t->hdr->frame_control)) {
-+ /* Skip LLC SNAP header (+6) */
-+ u8 *payload = &t->skb->data[t->hdrlen];
-+ u16 *ethertype = (u16 *) &payload[6];
-+ if (unlikely(*ethertype == __be16_to_cpu(ETH_P_PAE)))
-+ priority = WSM_EPTA_PRIORITY_EAPOL;
-+ } else if (unlikely(ieee80211_is_assoc_req(t->hdr->frame_control) ||
-+ ieee80211_is_reassoc_req(t->hdr->frame_control))) {
-+ struct ieee80211_mgmt *mgt_frame =
-+ (struct ieee80211_mgmt *)t->hdr;
-+
-+ if (mgt_frame->u.assoc_req.listen_interval <
-+ priv->listen_interval) {
-+ txrx_printk(XRADIO_DBG_MSG,
-+ "Modified Listen Interval to %d from %d\n",
-+ priv->listen_interval,
-+ mgt_frame->u.assoc_req.listen_interval);
-+ /* Replace listen interval derieved from
-+ * the one read from SDD */
-+ mgt_frame->u.assoc_req.listen_interval =
-+ priv->listen_interval;
-+ }
-+ }
-+
-+ if (likely(!priority)) {
-+ if (ieee80211_is_action(t->hdr->frame_control))
-+ priority = WSM_EPTA_PRIORITY_ACTION;
-+ else if (ieee80211_is_mgmt(t->hdr->frame_control))
-+ priority = WSM_EPTA_PRIORITY_MGT;
-+ else if ((wsm->queueId == WSM_QUEUE_VOICE))
-+ priority = WSM_EPTA_PRIORITY_VOICE;
-+ else if ((wsm->queueId == WSM_QUEUE_VIDEO))
-+ priority = WSM_EPTA_PRIORITY_VIDEO;
-+ else
-+ priority = WSM_EPTA_PRIORITY_DATA;
-+ }
-+
-+ txrx_printk(XRADIO_DBG_MSG, "[TX] EPTA priority %d.\n",
-+ priority);
-+
-+ wsm->flags |= priority << 1;
-+}
-+
-+static int
-+xradio_tx_h_rate_policy(struct xradio_common *hw_priv, struct xradio_txinfo *t,
-+ struct wsm_tx *wsm)
-+{
-+ bool tx_policy_renew = false;
-+ struct xradio_vif *priv =
-+ xrwl_get_vif_from_ieee80211(t->tx_info->control.vif);
-+
-+ t->txpriv.rate_id = tx_policy_get(hw_priv,
-+ t->tx_info->control.rates, t->txpriv.use_bg_rate,
-+ &tx_policy_renew);
-+ if (t->txpriv.rate_id == XRADIO_INVALID_RATE_ID)
-+ return -EFAULT;
-+
-+ wsm->flags |= t->txpriv.rate_id << 4;
-+ t->rate = xradio_get_tx_rate(hw_priv, &t->tx_info->control.rates[0]);
-+ if (t->txpriv.use_bg_rate)
-+ wsm->maxTxRate = (u8)(t->txpriv.use_bg_rate & 0x3f);
-+ else
-+ wsm->maxTxRate = t->rate->hw_value;
-+
-+ if (t->rate->flags & IEEE80211_TX_RC_MCS) {
-+ if (priv->association_mode.greenfieldMode)
-+ wsm->htTxParameters |=
-+ __cpu_to_le32(WSM_HT_TX_GREENFIELD);
-+ else
-+ wsm->htTxParameters |=
-+ __cpu_to_le32(WSM_HT_TX_MIXED);
-+ }
-+
-+ if (tx_policy_renew) {
-+ txrx_printk(XRADIO_DBG_MSG, "[TX] TX policy renew.\n");
-+ /* It's not so optimal to stop TX queues every now and then.
-+ * Maybe it's better to reimplement task scheduling with
-+ * a counter. */
-+ /* xradio_tx_queues_lock(priv); */
-+ /* Definetly better. TODO. */
-+ if (atomic_add_return(1, &hw_priv->upload_count) == 1) {
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue,
-+ &hw_priv->tx_policy_upload_work) <= 0) {
-+ atomic_set(&hw_priv->upload_count, 0);
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
-+static bool
-+xradio_tx_h_pm_state(struct xradio_vif *priv, struct xradio_txinfo *t)
-+{
-+ int was_buffered = 1;
-+
-+
-+ if (t->txpriv.link_id == priv->link_id_after_dtim &&
-+ !priv->buffered_multicasts) {
-+ priv->buffered_multicasts = true;
-+ if (priv->sta_asleep_mask)
-+ queue_work(priv->hw_priv->workqueue,
-+ &priv->multicast_start_work);
-+ }
-+
-+ if (t->txpriv.raw_link_id && t->txpriv.tid < XRADIO_MAX_TID)
-+ was_buffered = priv->link_id_db[t->txpriv.raw_link_id - 1]
-+ .buffered[t->txpriv.tid]++;
-+
-+ return !was_buffered;
-+}
-+
-+static void
-+xradio_tx_h_ba_stat(struct xradio_vif *priv,
-+ struct xradio_txinfo *t)
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+
-+ if (priv->join_status != XRADIO_JOIN_STATUS_STA)
-+ return;
-+ if (!xradio_is_ht(&hw_priv->ht_oper))
-+ return;
-+ if (!priv->setbssparams_done)
-+ return;
-+ if (!ieee80211_is_data(t->hdr->frame_control))
-+ return;
-+
-+ spin_lock_bh(&hw_priv->ba_lock);
-+ hw_priv->ba_acc += t->skb->len - t->hdrlen;
-+ if (!(hw_priv->ba_cnt_rx || hw_priv->ba_cnt)) {
-+ mod_timer(&hw_priv->ba_timer,
-+ jiffies + XRADIO_BLOCK_ACK_INTERVAL);
-+ }
-+ hw_priv->ba_cnt++;
-+ spin_unlock_bh(&hw_priv->ba_lock);
-+}
-+
-+static int
-+xradio_tx_h_skb_pad(struct xradio_common *priv,
-+ struct wsm_tx *wsm,
-+ struct sk_buff *skb)
-+{
-+ size_t len = __le16_to_cpu(wsm->hdr.len);
-+ size_t padded_len = sdio_align_len(priv, len);
-+
-+
-+ if (WARN_ON(skb_padto(skb, padded_len) != 0)) {
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+void xradio_tx(struct ieee80211_hw *dev, struct ieee80211_tx_control *control, struct sk_buff *skb)
-+{
-+ struct xradio_common *hw_priv = dev->priv;
-+ struct xradio_txinfo t = {
-+ .skb = skb,
-+ .queue = skb_get_queue_mapping(skb),
-+ .tx_info = IEEE80211_SKB_CB(skb),
-+ .hdr = (struct ieee80211_hdr *)skb->data,
-+ .txpriv.tid = XRADIO_MAX_TID,
-+ .txpriv.rate_id = XRADIO_INVALID_RATE_ID,
-+ .txpriv.use_bg_rate = 0,
-+ };
-+ struct ieee80211_sta *sta;
-+ struct wsm_tx *wsm;
-+ bool tid_update = 0;
-+ u8 flags = 0;
-+ int ret = 0;
-+ struct xradio_vif *priv;
-+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-+
-+ if (!skb->data)
-+ BUG_ON(1);
-+
-+ if (!(t.tx_info->control.vif)) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+ priv = xrwl_get_vif_from_ieee80211(t.tx_info->control.vif);
-+ if (!priv) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ if (atomic_read(&priv->enabled) == 0) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ //dhcp and 80211 frames are important, use b/g rate and delay scan.
-+ //it can make sense, such as accelerate connect.
-+ if (ieee80211_is_auth(frame->frame_control)) {
-+ hw_priv->connet_time[priv->if_id] = jiffies;
-+ } else if (ieee80211_is_data_present(frame->frame_control)) {
-+ /* since Umac had already alloc IV space in ccmp skb, so we need to add this iv_len as the new offset to LLC */
-+ u8* llc = NULL;
-+ if(t.tx_info->control.hw_key &&
-+ (t.hdr->frame_control & __cpu_to_le32(IEEE80211_FCTL_PROTECTED)) &&
-+ (t.tx_info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP))
-+ llc = skb->data+ieee80211_hdrlen(frame->frame_control) + t.tx_info->control.hw_key->iv_len;
-+ else
-+ llc = skb->data+ieee80211_hdrlen(frame->frame_control);
-+ if (is_dhcp(llc) || is_8021x(llc)) {
-+ t.txpriv.use_bg_rate =
-+ hw_priv->hw->wiphy->bands[hw_priv->channel->band]->bitrates[0].hw_value;
-+ if (priv->vif->p2p)
-+ t.txpriv.use_bg_rate = AG_RATE_INDEX;
-+ t.txpriv.use_bg_rate |= 0x80;
-+ }
-+ if (t.txpriv.use_bg_rate){
-+ hw_priv->connet_time[priv->if_id] = jiffies;
-+ }
-+ } else if (ieee80211_is_deauth(frame->frame_control) ||
-+ ieee80211_is_disassoc(frame->frame_control)) {
-+ hw_priv->connet_time[priv->if_id] = 0;
-+ }
-+
-+#ifdef AP_HT_COMPAT_FIX
-+ if (ieee80211_is_assoc_req(frame->frame_control) &&
-+ priv->if_id == 0 && !(priv->ht_compat_det & 0x10)) {
-+ xradio_remove_ht_ie(priv, skb);
-+ }
-+#endif
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+ xradio_frame_monitor(hw_priv,skb,true);
-+#endif
-+
-+ if (ieee80211_is_action(frame->frame_control) &&
-+ mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
-+ u8 *action = (u8*)&mgmt->u.action.category;
-+ xradio_check_go_neg_conf_success(hw_priv, action);
-+ xradio_check_prov_desc_req(hw_priv, action);
-+ }
-+
-+ t.txpriv.if_id = priv->if_id;
-+ t.hdrlen = ieee80211_hdrlen(t.hdr->frame_control);
-+ t.da = ieee80211_get_DA(t.hdr);
-+ t.sta_priv =
-+ (struct xradio_sta_priv *)&control->sta->drv_priv;
-+
-+ if (WARN_ON(t.queue >= 4)) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ //spin_lock_bh(&hw_priv->tx_queue[t.queue].lock);
-+ //if ((priv->if_id == 0) &&
-+ // (hw_priv->tx_queue[t.queue].num_queued_vif[0] >=
-+ // hw_priv->vif0_throttle)) {
-+ // spin_unlock_bh(&hw_priv->tx_queue[t.queue].lock);
-+ //
-+ // ret = __LINE__;
-+ // goto drop;
-+ //} else if ((priv->if_id == 1) &&
-+ // (hw_priv->tx_queue[t.queue].num_queued_vif[1] >=
-+ // hw_priv->vif1_throttle)) {
-+ // spin_unlock_bh(&hw_priv->tx_queue[t.queue].lock);
-+ //
-+ // ret = __LINE__;
-+ // goto drop;
-+ //}
-+ //spin_unlock_bh(&hw_priv->tx_queue[t.queue].lock);
-+
-+ ret = xradio_tx_h_calc_link_ids(priv, control, &t);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ dev_dbg(hw_priv->pdev, "vif %d: tx, %d bytes queue %d, link_id %d(%d).\n",
-+ priv->if_id, skb->len, t.queue, t.txpriv.link_id, t.txpriv.raw_link_id);
-+ if(ieee80211_is_assoc_resp(frame->frame_control)){
-+ dev_dbg(hw_priv->pdev, "vif %d: association response\n", priv->if_id);
-+ }
-+
-+ xradio_tx_h_pm(priv, &t);
-+ xradio_tx_h_calc_tid(priv, &t);
-+ ret = xradio_tx_h_crypt(priv, &t);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+ ret = xradio_tx_h_align(priv, &t, &flags);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+ ret = xradio_tx_h_action(priv, &t);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+ wsm = xradio_tx_h_wsm(priv, &t);
-+ if (!wsm) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ wsm->flags |= flags;
-+ xradio_tx_h_bt(priv, &t, wsm);
-+ ret = xradio_tx_h_rate_policy(hw_priv, &t, wsm);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ ret = xradio_tx_h_skb_pad(hw_priv, wsm, skb);
-+ if (ret) {
-+ ret = __LINE__;
-+ goto drop;
-+ }
-+
-+ rcu_read_lock();
-+ sta = rcu_dereference(control->sta);
-+
-+ xradio_tx_h_ba_stat(priv, &t);
-+ spin_lock_bh(&priv->ps_state_lock);
-+ {
-+ tid_update = xradio_tx_h_pm_state(priv, &t);
-+ BUG_ON(xradio_queue_put(&hw_priv->tx_queue[t.queue],
-+ t.skb, &t.txpriv));
-+#ifdef ROC_DEBUG
-+ txrx_printk(XRADIO_DBG_ERROR, "QPUT %x, %pM, if_id - %d\n",
-+ t.hdr->frame_control, t.da, priv->if_id);
-+#endif
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ if (tid_update && sta)
-+ ieee80211_sta_set_buffered(sta,
-+ t.txpriv.tid, true);
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+
-+ rcu_read_unlock();
-+
-+ xradio_bh_wakeup(hw_priv);
-+
-+ return;
-+
-+drop:
-+ dev_dbg(hw_priv->pdev, "dropped tx at line %d, fctl=0x%04x.\n", ret, frame->frame_control);
-+ xradio_skb_dtor(hw_priv, skb, &t.txpriv);
-+ return;
-+}
-+
-+void xradio_tx_confirm_cb(struct xradio_common *hw_priv,
-+ struct wsm_tx_confirm *arg)
-+{
-+ u8 queue_id = xradio_queue_get_queue_id(arg->packetID);
-+ struct xradio_queue *queue = &hw_priv->tx_queue[queue_id];
-+ struct sk_buff *skb;
-+ const struct xradio_txpriv *txpriv;
-+ struct xradio_vif *priv;
-+ u32 feedback_retry = 0;
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, arg->if_id);
-+ if (unlikely(!priv))
-+ return;
-+
-+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
-+ /* STA is stopped. */
-+ spin_unlock(&priv->vif_lock);
-+ return;
-+ }
-+
-+ if (WARN_ON(queue_id >= 4)) {
-+ spin_unlock(&priv->vif_lock);
-+ return;
-+ }
-+
-+ dev_dbg(hw_priv->pdev, "vif %d: tx confirm status=%d, retry=%d, lastRate=%d\n",
-+ priv->if_id, arg->status, arg->ackFailures, arg->txedRate);
-+
-+ if ((arg->status == WSM_REQUEUE) &&
-+ (arg->flags & WSM_TX_STATUS_REQUEUE)) {
-+ /* "Requeue" means "implicit suspend" */
-+ struct wsm_suspend_resume suspend = {
-+ .link_id = arg->link_id,
-+ .stop = 1,
-+ .multicast = !arg->link_id,
-+ .if_id = arg->if_id,
-+ };
-+ xradio_suspend_resume(priv, &suspend);
-+ txrx_printk(XRADIO_DBG_WARN, "Requeue for link_id %d (try %d)."
-+ " STAs asleep: 0x%.8X\n",
-+ arg->link_id,
-+ xradio_queue_get_generation(arg->packetID) + 1,
-+ priv->sta_asleep_mask);
-+
-+ WARN_ON(xradio_queue_requeue(queue,
-+ arg->packetID, true));
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ if (!arg->link_id) {
-+ priv->buffered_multicasts = true;
-+ if (priv->sta_asleep_mask) {
-+ queue_work(hw_priv->workqueue,
-+ &priv->multicast_start_work);
-+ }
-+ }
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ spin_unlock(&priv->vif_lock);
-+ } else if (!WARN_ON(xradio_queue_get_skb(
-+ queue, arg->packetID, &skb, &txpriv))) {
-+ struct ieee80211_tx_info *tx = IEEE80211_SKB_CB(skb);
-+ struct ieee80211_hdr *frame = (struct ieee80211_hdr *)&skb->data[txpriv->offset];
-+ int tx_count = arg->ackFailures;
-+ u8 ht_flags = 0;
-+ int i;
-+
-+ //yangfh add to reset if_0 in firmware when STA-unjoined,
-+ //fix the errors when switch APs in combo mode.
-+ if (unlikely(ieee80211_is_disassoc(frame->frame_control) ||
-+ ieee80211_is_deauth(frame->frame_control))) {
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ wms_send_deauth_to_self(hw_priv, priv);
-+ /* Shedule unjoin work */
-+ txrx_printk(XRADIO_DBG_WARN, "Issue unjoin command(TX) by self.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->unjoin_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+
-+ if (priv->association_mode.greenfieldMode)
-+ ht_flags |= IEEE80211_TX_RC_GREEN_FIELD;
-+
-+ //bss loss confirm.
-+ if (unlikely(priv->bss_loss_status == XRADIO_BSS_LOSS_CONFIRMING &&
-+ priv->bss_loss_confirm_id == arg->packetID)) {
-+ spin_lock(&priv->bss_loss_lock);
-+ priv->bss_loss_status = arg->status?
-+ XRADIO_BSS_LOSS_CONFIRMED : XRADIO_BSS_LOSS_NONE;
-+ spin_unlock(&priv->bss_loss_lock);
-+ }
-+
-+ if (likely(!arg->status)) {
-+ tx->flags |= IEEE80211_TX_STAT_ACK;
-+ priv->cqm_tx_failure_count = 0;
-+ ++tx_count;
-+
-+ if (arg->flags & WSM_TX_STATUS_AGGREGATION) {
-+ /* Do not report aggregation to mac80211:
-+ * it confuses minstrel a lot. */
-+ /* tx->flags |= IEEE80211_TX_STAT_AMPDU; */
-+ }
-+ } else {
-+ /* TODO: Update TX failure counters */
-+ if (unlikely(priv->cqm_tx_failure_thold &&
-+ (++priv->cqm_tx_failure_count >
-+ priv->cqm_tx_failure_thold))) {
-+ priv->cqm_tx_failure_thold = 0;
-+ queue_work(hw_priv->workqueue,
-+ &priv->tx_failure_work);
-+ }
-+ if (tx_count)
-+ ++tx_count;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+
-+ tx->status.ampdu_len = 1;
-+ tx->status.ampdu_ack_len = 1;
-+
-+ txrx_printk(XRADIO_DBG_NIY,"feedback:%08x, %08x, %08x.\n",
-+ arg->rate_try[2], arg->rate_try[1], arg->rate_try[0]);
-+ if(txpriv->use_bg_rate) { //bg rates
-+ tx->status.rates[0].count = arg->ackFailures+1;
-+ tx->status.rates[0].idx = 0;
-+ tx->status.rates[1].idx = -1;
-+ tx->status.rates[2].idx = -1;
-+ tx->status.rates[3].idx = -1;
-+ } else {
-+ int j;
-+ s8 txed_idx;
-+ register u8 rate_num=0, shift=0, retries=0;
-+ u8 flag = tx->status.rates[0].flags;
-+
-+ //get retry rate idx.
-+ for(i=2; i>=0;i--) {
-+ if(arg->rate_try[i]) {
-+ for(j=7; j>=0;j--) {
-+ shift = j<<2;
-+ retries = (arg->rate_try[i]>>shift)&0xf;
-+ if(retries) {
-+ feedback_retry += retries;
-+ txed_idx = xradio_get_rate_idx(hw_priv,flag,((i<<3)+j));
-+ txrx_printk(XRADIO_DBG_NIY, "rate_num=%d, hw=%d, idx=%d, "
-+ "retries=%d, flag=%d", rate_num, ((i<<3)+j),
-+ txed_idx, retries, flag);
-+ if(likely(txed_idx>=0)) {
-+ tx->status.rates[rate_num].idx = txed_idx;
-+ tx->status.rates[rate_num].count = retries;
-+ if (tx->status.rates[rate_num].flags & IEEE80211_TX_RC_MCS)
-+ tx->status.rates[rate_num].flags |= ht_flags;
-+ rate_num++;
-+ if(rate_num>=IEEE80211_TX_MAX_RATES) {
-+ i = -1;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+ //clear other rate.
-+ for (i=rate_num; i < IEEE80211_TX_MAX_RATES; ++i) {
-+ tx->status.rates[i].count = 0;
-+ tx->status.rates[i].idx = -1;
-+ }
-+ //get successful rate idx.
-+ if(!arg->status) {
-+ txed_idx = xradio_get_rate_idx(hw_priv, flag, arg->txedRate);
-+ if(rate_num == 0) {
-+ tx->status.rates[0].idx = txed_idx;
-+ tx->status.rates[0].count = 1;
-+ } else if(rate_num <= IEEE80211_TX_MAX_RATES){
-+ --rate_num;
-+ if(txed_idx == tx->status.rates[rate_num].idx) {
-+ tx->status.rates[rate_num].count += 1;
-+ } else if(rate_num<(IEEE80211_TX_MAX_RATES-1)){
-+ ++rate_num;
-+ tx->status.rates[rate_num].idx = txed_idx;
-+ tx->status.rates[rate_num].count = 1;
-+ } else if(txed_idx >=0) {
-+ tx->status.rates[rate_num].idx = txed_idx;
-+ tx->status.rates[rate_num].count = 1;
-+ }
-+ }
-+ }
-+ }
-+
-+ dev_dbg(hw_priv->pdev, "[TX policy] Ack: " \
-+ "%d:%d, %d:%d, %d:%d, %d:%d\n",
-+ tx->status.rates[0].idx, tx->status.rates[0].count,
-+ tx->status.rates[1].idx, tx->status.rates[1].count,
-+ tx->status.rates[2].idx, tx->status.rates[2].count,
-+ tx->status.rates[3].idx, tx->status.rates[3].count);
-+
-+
-+ xradio_queue_remove(queue, arg->packetID);
-+ }
-+}
-+
-+static void xradio_notify_buffered_tx(struct xradio_vif *priv,
-+ struct sk_buff *skb, int link_id, int tid)
-+{
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ struct ieee80211_sta *sta;
-+ struct ieee80211_hdr *hdr;
-+ u8 *buffered;
-+ u8 still_buffered = 0;
-+
-+
-+ if (link_id && tid < XRADIO_MAX_TID) {
-+ buffered = priv->link_id_db
-+ [link_id - 1].buffered;
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ if (!WARN_ON(!buffered[tid]))
-+ still_buffered = --buffered[tid];
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+ if (!still_buffered && tid < XRADIO_MAX_TID) {
-+ hdr = (struct ieee80211_hdr *) skb->data;
-+ rcu_read_lock();
-+ sta = ieee80211_find_sta(priv->vif, hdr->addr1);
-+ if (sta)
-+ ieee80211_sta_set_buffered(sta, tid, false);
-+ rcu_read_unlock();
-+ }
-+ }
-+#endif /* CONFIG_XRADIO_USE_EXTENSIONS */
-+}
-+
-+void xradio_skb_dtor(struct xradio_common *hw_priv,
-+ struct sk_buff *skb,
-+ const struct xradio_txpriv *txpriv)
-+{
-+ struct xradio_vif *priv =
-+ __xrwl_hwpriv_to_vifpriv(hw_priv, txpriv->if_id);
-+
-+
-+ skb_pull(skb, txpriv->offset);
-+ if (priv && txpriv->rate_id != XRADIO_INVALID_RATE_ID) {
-+ xradio_notify_buffered_tx(priv, skb,
-+ txpriv->raw_link_id, txpriv->tid);
-+ tx_policy_put(hw_priv, txpriv->rate_id);
-+ }
-+ ieee80211_tx_status(hw_priv->hw, skb);
-+}
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+/* Workaround for WFD test case 6.1.10 */
-+void xradio_link_id_reset(struct work_struct *work)
-+{
-+ struct xradio_vif *priv =
-+ container_of(work, struct xradio_vif, linkid_reset_work);
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+ int temp_linkid;
-+
-+
-+ if (!priv->action_linkid) {
-+ /* In GO mode we can receive ACTION frames without a linkID */
-+ temp_linkid = xradio_alloc_link_id(priv,
-+ &priv->action_frame_sa[0]);
-+ WARN_ON(!temp_linkid);
-+ if (temp_linkid) {
-+ /* Make sure we execute the WQ */
-+ flush_workqueue(hw_priv->workqueue);
-+ /* Release the link ID */
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->link_id_db[temp_linkid - 1].prev_status =
-+ priv->link_id_db[temp_linkid - 1].status;
-+ priv->link_id_db[temp_linkid - 1].status =
-+ XRADIO_LINK_RESET;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue,
-+ &priv->link_id_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ } else {
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->link_id_db[priv->action_linkid - 1].prev_status =
-+ priv->link_id_db[priv->action_linkid - 1].status;
-+ priv->link_id_db[priv->action_linkid - 1].status =
-+ XRADIO_LINK_RESET_REMAP;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->link_id_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ flush_workqueue(hw_priv->workqueue);
-+ }
-+}
-+#endif
-diff --git a/drivers/net/wireless/xradio/tx.h b/drivers/net/wireless/xradio/tx.h
-new file mode 100644
-index 0000000..e08bb71
---- /dev/null
-+++ b/drivers/net/wireless/xradio/tx.h
-@@ -0,0 +1,86 @@
-+/*
-+ * txrx interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_TXRX_H
-+#define XRADIO_TXRX_H
-+
-+#include
-+
-+/* extern */ struct ieee80211_hw;
-+/* extern */ struct sk_buff;
-+/* extern */ struct wsm_tx;
-+/* extern */ struct wsm_rx;
-+/* extern */ struct wsm_tx_confirm;
-+/* extern */ struct xradio_txpriv;
-+/* extern */ struct xradio_vif;
-+
-+struct tx_policy {
-+ union {
-+ __le32 tbl[3];
-+ u8 raw[12];
-+ };
-+ u8 defined; /* TODO: u32 or u8, profile and select best */
-+ u8 usage_count; /* --// -- */
-+ u8 retry_count; /* --// -- */
-+ u8 uploaded;
-+};
-+
-+struct tx_policy_cache_entry {
-+ struct tx_policy policy;
-+ struct list_head link;
-+};
-+
-+#define TX_POLICY_CACHE_SIZE (8)
-+struct tx_policy_cache {
-+ struct tx_policy_cache_entry cache[TX_POLICY_CACHE_SIZE];
-+ struct list_head used;
-+ struct list_head free;
-+ spinlock_t lock;
-+};
-+
-+/* ******************************************************************** */
-+/* TX policy cache */
-+/* Intention of TX policy cache is an overcomplicated WSM API.
-+ * Device does not accept per-PDU tx retry sequence.
-+ * It uses "tx retry policy id" instead, so driver code has to sync
-+ * linux tx retry sequences with a retry policy table in the device.
-+ */
-+void tx_policy_init(struct xradio_common *hw_priv);
-+void tx_policy_upload_work(struct work_struct *work);
-+
-+/* ******************************************************************** */
-+/* TX implementation */
-+
-+u32 xradio_rate_mask_to_wsm(struct xradio_common *hw_priv,
-+ u32 rates);
-+void xradio_tx(struct ieee80211_hw *dev, struct ieee80211_tx_control *control, struct sk_buff *skb);
-+void xradio_skb_dtor(struct xradio_common *hw_priv,
-+ struct sk_buff *skb,
-+ const struct xradio_txpriv *txpriv);
-+
-+/* ******************************************************************** */
-+/* WSM callbacks */
-+
-+void xradio_tx_confirm_cb(struct xradio_common *hw_priv,
-+ struct wsm_tx_confirm *arg);
-+
-+/* ******************************************************************** */
-+/* Timeout */
-+
-+void xradio_tx_timeout(struct work_struct *work);
-+
-+/* ******************************************************************** */
-+/* Workaround for WFD test case 6.1.10 */
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+void xradio_link_id_reset(struct work_struct *work);
-+#endif
-+
-+#endif /* XRADIO_TXRX_H */
-diff --git a/drivers/net/wireless/xradio/wsm.c b/drivers/net/wireless/xradio/wsm.c
-new file mode 100644
-index 0000000..3842116
---- /dev/null
-+++ b/drivers/net/wireless/xradio/wsm.c
-@@ -0,0 +1,3004 @@
-+/*
-+ * WSM host interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "xradio.h"
-+#include "wsm.h"
-+#include "bh.h"
-+#include "ap.h"
-+#include "sta.h"
-+#include "rx.h"
-+
-+#define WSM_CMD_TIMEOUT (2 * HZ) /* With respect to interrupt loss */
-+#define WSM_CMD_JOIN_TIMEOUT (7 * HZ) /* Join timeout is 5 sec. in FW */
-+#define WSM_CMD_START_TIMEOUT (7 * HZ)
-+#define WSM_CMD_RESET_TIMEOUT (3 * HZ) /* 2 sec. timeout was observed. */
-+#define WSM_CMD_DEFAULT_TIMEOUT (3 * HZ)
-+#define WSM_SKIP(buf, size) \
-+ do { \
-+ if (unlikely((buf)->data + size > (buf)->end)) \
-+ goto underflow; \
-+ (buf)->data += size; \
-+ } while (0)
-+
-+#define WSM_GET(buf, ptr, size) \
-+ do { \
-+ if (unlikely((buf)->data + size > (buf)->end)) \
-+ goto underflow; \
-+ memcpy(ptr, (buf)->data, size); \
-+ (buf)->data += size; \
-+ } while (0)
-+
-+#define __WSM_GET(buf, type, cvt) \
-+ ({ \
-+ type val; \
-+ if (unlikely((buf)->data + sizeof(type) > (buf)->end)) \
-+ goto underflow; \
-+ val = cvt(*(type *)(buf)->data); \
-+ (buf)->data += sizeof(type); \
-+ val; \
-+ })
-+
-+#define WSM_GET8(buf) __WSM_GET(buf, u8, (u8))
-+#define WSM_GET16(buf) __WSM_GET(buf, u16, __le16_to_cpu)
-+#define WSM_GET32(buf) __WSM_GET(buf, u32, __le32_to_cpu)
-+
-+#define WSM_PUT(buf, ptr, size) \
-+ do { \
-+ if (unlikely((buf)->data + size > (buf)->end)) \
-+ if (unlikely(wsm_buf_reserve((buf), size))) \
-+ goto nomem; \
-+ memcpy((buf)->data, ptr, size); \
-+ (buf)->data += size; \
-+ } while (0)
-+
-+#define __WSM_PUT(buf, val, type, cvt) \
-+ do { \
-+ if (unlikely((buf)->data + sizeof(type) > (buf)->end)) \
-+ if (unlikely(wsm_buf_reserve((buf), sizeof(type)))) \
-+ goto nomem; \
-+ *(type *)(buf)->data = cvt(val); \
-+ (buf)->data += sizeof(type); \
-+ } while (0)
-+
-+#define WSM_PUT8(buf, val) __WSM_PUT(buf, val, u8, (u8))
-+#define WSM_PUT16(buf, val) __WSM_PUT(buf, val, u16, __cpu_to_le16)
-+#define WSM_PUT32(buf, val) __WSM_PUT(buf, val, u32, __cpu_to_le32)
-+
-+static void wsm_buf_reset(struct wsm_buf *buf);
-+static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size);
-+static int get_interface_id_scanning(struct xradio_common *hw_priv);
-+
-+static int wsm_cmd_send(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf,
-+ void *arg, u16 cmd, long tmo, int if_id);
-+
-+static struct xradio_vif
-+ *wsm_get_interface_for_tx(struct xradio_common *hw_priv);
-+
-+static inline void wsm_cmd_lock(struct xradio_common *hw_priv)
-+{
-+ mutex_lock(&hw_priv->wsm_cmd_mux);
-+}
-+
-+static inline void wsm_cmd_unlock(struct xradio_common *hw_priv)
-+{
-+ mutex_unlock(&hw_priv->wsm_cmd_mux);
-+}
-+
-+static inline void wsm_oper_lock(struct xradio_common *hw_priv)
-+{
-+ mutex_lock(&hw_priv->wsm_oper_lock);
-+}
-+
-+static inline void wsm_oper_unlock(struct xradio_common *hw_priv)
-+{
-+ mutex_unlock(&hw_priv->wsm_oper_lock);
-+}
-+
-+/* ******************************************************************** */
-+/* WSM API implementation */
-+
-+static int wsm_generic_confirm(struct xradio_common *hw_priv,
-+ void *arg,
-+ struct wsm_buf *buf)
-+{
-+ u32 status = WSM_GET32(buf);
-+ if (status != WSM_STATUS_SUCCESS)
-+ return -EINVAL;
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+#ifdef XR_RRM//RadioResourceMeasurement
-+static int wsm_start_measure_requset(struct xradio_common *hw_priv,
-+ MEASUREMENT_PARAMETERS *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT(buf, arg, sizeof(*arg));
-+ ret = wsm_cmd_send(hw_priv, buf, arg, 0x000E, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+ nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+
-+}
-+
-+int wsm_11k_measure_requset(struct xradio_common *hw_priv,
-+ u8 measure_type,
-+ u16 ChannelNum,
-+ u16 Duration)
-+{
-+ int ret;
-+ u8 type, sub_type;
-+ MEASUREMENT_PARAMETERS rrm_paras;
-+ LMAC_MEAS_REQUEST *rrm_req = &rrm_paras.MeasurementRequest;
-+// LMAC_MEAS_CHANNEL_LOAD_PARAMS *rrm_req = &rrm_paras.MeasurementRequest;
-+ rrm_paras.TxPowerLevel = 0x11;
-+ rrm_paras.DurationMandatory = 0x22;
-+ rrm_paras.MeasurementRequestLength = 0x33;
-+
-+ type = (measure_type&0xf0)>>4;
-+ sub_type = measure_type&0xf;
-+ rrm_paras.MeasurementType = type;
-+// if (measure_type == ChannelLoadMeasurement) {
-+ if (type == ChannelLoadMeasurement) {
-+ rrm_req->ChannelLoadParams.Reserved = 0;
-+ rrm_req->ChannelLoadParams.ChannelLoadCCA = sub_type;
-+ rrm_req->ChannelLoadParams.ChannelNum = ChannelNum;
-+ //valid when channelload measure, interval bettween request&start
-+ rrm_req->ChannelLoadParams.RandomInterval = 0;
-+ //unit:1TU=1024us
-+ rrm_req->ChannelLoadParams.MeasurementDuration = Duration;
-+ rrm_req->ChannelLoadParams.MeasurementStartTimel = 0;
-+ rrm_req->ChannelLoadParams.MeasurementStartTimeh = 0;
-+ } else if (type == NoiseHistrogramMeasurement) {
-+ rrm_req->NoisHistogramParams.Reserved = 0;
-+ rrm_req->NoisHistogramParams.IpiRpi = sub_type;
-+ rrm_req->NoisHistogramParams.ChannelNum = ChannelNum;
-+ rrm_req->NoisHistogramParams.RandomInterval = 0;
-+ rrm_req->NoisHistogramParams.MeasurementDuration = Duration;
-+ rrm_req->NoisHistogramParams.MeasurementStartTimel = 0;
-+ rrm_req->NoisHistogramParams.MeasurementStartTimeh = 0;
-+ }
-+ ret = wsm_start_measure_requset(hw_priv, &rrm_paras, 0);
-+
-+ return ret;
-+}
-+
-+
-+#endif//RadioResourceMeasurement
-+int wsm_configuration(struct xradio_common *hw_priv,
-+ struct wsm_configuration *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT32(buf, arg->dot11MaxTransmitMsduLifeTime);
-+ WSM_PUT32(buf, arg->dot11MaxReceiveLifeTime);
-+ WSM_PUT32(buf, arg->dot11RtsThreshold);
-+
-+ /* DPD block. */
-+ WSM_PUT16(buf, arg->dpdData_size + 12);
-+ WSM_PUT16(buf, 1); /* DPD version */
-+ WSM_PUT(buf, arg->dot11StationId, ETH_ALEN);
-+ WSM_PUT16(buf, 5); /* DPD flags */
-+ WSM_PUT(buf, arg->dpdData, arg->dpdData_size);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, arg, 0x0009, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+static int wsm_configuration_confirm(struct xradio_common *hw_priv,
-+ struct wsm_configuration *arg,
-+ struct wsm_buf *buf)
-+{
-+ int i;
-+ int status;
-+
-+ status = WSM_GET32(buf);
-+ if (WARN_ON(status != WSM_STATUS_SUCCESS))
-+ return -EINVAL;
-+
-+ WSM_GET(buf, arg->dot11StationId, ETH_ALEN);
-+ arg->dot11FrequencyBandsSupported = WSM_GET8(buf);
-+ WSM_SKIP(buf, 1);
-+ arg->supportedRateMask = WSM_GET32(buf);
-+ for (i = 0; i < 2; ++i) {
-+ arg->txPowerRange[i].min_power_level = WSM_GET32(buf);
-+ arg->txPowerRange[i].max_power_level = WSM_GET32(buf);
-+ arg->txPowerRange[i].stepping = WSM_GET32(buf);
-+ }
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+void wsm_query_work(struct work_struct *work)
-+{
-+ struct xradio_common *hw_priv =
-+ container_of(work, struct xradio_common, query_work);
-+ u8 ret[100] = {0};
-+
-+
-+ *(u32*)&ret[0] = hw_priv->query_packetID;
-+ wsm_read_mib(hw_priv, WSM_MIB_ID_REQ_PKT_STATUS, (void*)&ret[0], sizeof(ret), 4);
-+ if(!ret[4]) {
-+ wsm_printk(XRADIO_DBG_ERROR,"QuerypktID=0x%08x, status=0x%x, retry=%d, flags=0x%x, PktDebug=0x%x\n" \
-+ "pktqueue=0x%x, ext1=%d, ext2=%d, ext3=%d, ext4=0x%x, ext5=0x%x\n",
-+ *(u32*)&ret[0], ret[6], ret[7], *(u32*)&ret[8], *(u32*)&ret[12],
-+ ret[44], ret[45], ret[46], ret[47], ret[48], ret[49]);
-+ wsm_printk(XRADIO_DBG_ERROR,"interdebug=0x%x, 0x%x, 0x%x, Soure=0x%x, 0x%x, 0x%x\n" \
-+ "interuse=%d, external=%d, TxOutstanding=%d, QueueStatus=0x%x, BA0=0x%x, BA1=0x%x\n" \
-+ "ScanStatus=0x%x, scanNULL=0x%x, wr_state=0x%x,0x%x,0x%x,0x%x," \
-+ "wr_cnt=%d, %d, %d, %d\n",
-+ *(u32*)&ret[16], *(u32*)&ret[20], *(u32*)&ret[24], ret[28], ret[29], ret[30],
-+ ret[32], ret[33], ret[34], ret[35], *(u32*)&ret[36], *(u32*)&ret[40],
-+ ret[50], ret[51], ret[52], ret[53], ret[54], ret[55],
-+ *(u16*)&ret[56], *(u16*)&ret[58], *(u16*)&ret[60], *(u16*)&ret[62]);
-+ } else {
-+ ret[5] = 0;
-+ wsm_printk(XRADIO_DBG_ERROR,"No req packid=0x%08x!\n", *(u32*)&ret[0]);
-+ }
-+ //hardware error occurs, try to restart wifi.
-+ if(ret[5] & 0x4) {
-+ wsm_printk(XRADIO_DBG_ERROR,"Hardware need to reset 0x%x.\n", ret[5]);
-+ hw_priv->bh_error = 1;
-+ wake_up(&hw_priv->bh_wq);
-+ }
-+ hw_priv->query_packetID = 0;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_reset(struct xradio_common *hw_priv, const struct wsm_reset *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ u16 cmd = 0x000A | WSM_TX_LINK_ID(arg->link_id);
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT32(buf, arg->reset_statistics ? 0 : 1);
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, cmd, WSM_CMD_RESET_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+struct wsm_mib {
-+ u16 mibId;
-+ void *buf;
-+ size_t buf_size;
-+};
-+
-+int wsm_read_mib(struct xradio_common *hw_priv, u16 mibId, void *_buf,
-+ size_t buf_size, size_t arg_size)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ struct wsm_mib mib_buf = {
-+ .mibId = mibId,
-+ .buf = _buf,
-+ .buf_size = buf_size,
-+ };
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT16(buf, mibId);
-+ WSM_PUT16(buf, arg_size);
-+ WSM_PUT(buf, _buf, arg_size);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, &mib_buf, 0x0005, WSM_CMD_TIMEOUT, -1);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+static int wsm_read_mib_confirm(struct xradio_common *hw_priv,
-+ struct wsm_mib *arg,
-+ struct wsm_buf *buf)
-+{
-+ u16 size;
-+ if (WARN_ON(WSM_GET32(buf) != WSM_STATUS_SUCCESS))
-+ return -EINVAL;
-+
-+ if (WARN_ON(WSM_GET16(buf) != arg->mibId))
-+ return -EINVAL;
-+
-+ size = WSM_GET16(buf);
-+ if (size > arg->buf_size)
-+ size = arg->buf_size;
-+
-+ WSM_GET(buf, arg->buf, size);
-+ arg->buf_size = size;
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_write_mib(struct xradio_common *hw_priv, u16 mibId, void *_buf,
-+ size_t buf_size, int if_id)
-+{
-+ int ret = 0;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ struct wsm_mib mib_buf = {
-+ .mibId = mibId,
-+ .buf = _buf,
-+ .buf_size = buf_size,
-+ };
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT16(buf, mibId);
-+ WSM_PUT16(buf, buf_size);
-+ WSM_PUT(buf, _buf, buf_size);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, &mib_buf, 0x0006, WSM_CMD_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+static int wsm_write_mib_confirm(struct xradio_common *hw_priv,
-+ struct wsm_mib *arg,
-+ struct wsm_buf *buf,
-+ int interface_link_id)
-+{
-+ int ret;
-+ int i;
-+ struct xradio_vif *priv;
-+ ret = wsm_generic_confirm(hw_priv, arg, buf);
-+ if (ret)
-+ return ret;
-+
-+ /*wsm_set_operational_mode confirm.*/
-+ if (arg->mibId == 0x1006) {
-+ const char *p = arg->buf;
-+ bool powersave_enabled = (p[0] & 0x0F) ? true : false;
-+
-+ /* update vif PM status. */
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
-+ if (priv) {
-+ xradio_enable_powersave(priv, powersave_enabled);
-+ spin_unlock(&priv->vif_lock);
-+ }
-+
-+ /* HW powersave base on vif except for generic vif. */
-+ spin_lock(&hw_priv->vif_list_lock);
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ powersave_enabled &= !!priv->powersave_enabled;
-+ }
-+ hw_priv->powersave_enabled = powersave_enabled;
-+ spin_unlock(&hw_priv->vif_list_lock);
-+
-+ }
-+ return 0;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_scan(struct xradio_common *hw_priv, const struct wsm_scan *arg,
-+ int if_id)
-+{
-+ int i;
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ if (unlikely(arg->numOfChannels > 48))
-+ return -EINVAL;
-+
-+ if (unlikely(arg->numOfSSIDs > WSM_SCAN_MAX_NUM_OF_SSIDS))
-+ return -EINVAL;
-+
-+ if (unlikely(arg->band > 1))
-+ return -EINVAL;
-+
-+ wsm_oper_lock(hw_priv);
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->band);
-+ WSM_PUT8(buf, arg->scanType);
-+ WSM_PUT8(buf, arg->scanFlags);
-+ WSM_PUT8(buf, arg->maxTransmitRate);
-+ WSM_PUT32(buf, arg->autoScanInterval);
-+ WSM_PUT8(buf, arg->numOfProbeRequests);
-+ WSM_PUT8(buf, arg->numOfChannels);
-+ WSM_PUT8(buf, arg->numOfSSIDs);
-+ WSM_PUT8(buf, arg->probeDelay);
-+
-+ for (i = 0; i < arg->numOfChannels; ++i) {
-+ WSM_PUT16(buf, arg->ch[i].number);
-+ WSM_PUT16(buf, 0);
-+ WSM_PUT32(buf, arg->ch[i].minChannelTime);
-+ WSM_PUT32(buf, arg->ch[i].maxChannelTime);
-+ WSM_PUT32(buf, 0);
-+ }
-+
-+ for (i = 0; i < arg->numOfSSIDs; ++i) {
-+ WSM_PUT32(buf, arg->ssids[i].length);
-+ WSM_PUT(buf, &arg->ssids[i].ssid[0],
-+ sizeof(arg->ssids[i].ssid));
-+ }
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0007, WSM_CMD_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ if (ret)
-+ wsm_oper_unlock(hw_priv);
-+
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_oper_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_stop_scan(struct xradio_common *hw_priv, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ wsm_cmd_lock(hw_priv);
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0008, WSM_CMD_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+}
-+
-+
-+static int wsm_tx_confirm(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf,
-+ int interface_link_id)
-+{
-+ struct wsm_tx_confirm tx_confirm;
-+
-+ tx_confirm.packetID = WSM_GET32(buf);
-+ tx_confirm.status = WSM_GET32(buf);
-+ tx_confirm.txedRate = WSM_GET8(buf);
-+ tx_confirm.ackFailures = WSM_GET8(buf);
-+ tx_confirm.flags = WSM_GET16(buf);
-+ tx_confirm.rate_try[0] = WSM_GET32(buf);
-+ tx_confirm.rate_try[1] = WSM_GET32(buf);
-+ tx_confirm.rate_try[2] = WSM_GET32(buf);
-+ tx_confirm.mediaDelay = WSM_GET32(buf);
-+ tx_confirm.txQueueDelay = WSM_GET32(buf);
-+
-+ if (is_hardware_xradio(hw_priv)) {
-+ /* TODO:COMBO:linkID will be stored in packetID*/
-+ /* TODO:COMBO: Extract traffic resumption map */
-+ tx_confirm.if_id = xradio_queue_get_if_id(tx_confirm.packetID);
-+ tx_confirm.link_id = xradio_queue_get_link_id(
-+ tx_confirm.packetID);
-+ } else {
-+ tx_confirm.link_id = interface_link_id;
-+ tx_confirm.if_id = 0;
-+ }
-+
-+ wsm_release_vif_tx_buffer(hw_priv, tx_confirm.if_id, 1);
-+
-+ xradio_tx_confirm_cb(hw_priv, &tx_confirm);
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+static int wsm_multi_tx_confirm(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf, int interface_link_id)
-+{
-+ struct xradio_vif *priv;
-+ int ret;
-+ int count;
-+ int i;
-+
-+ count = WSM_GET32(buf);
-+ if (WARN_ON(count <= 0))
-+ return -EINVAL;
-+ else if (count > 1) {
-+ ret = wsm_release_tx_buffer(hw_priv, count - 1);
-+ if (ret < 0)
-+ return ret;
-+ else if (ret > 0)
-+ xradio_bh_wakeup(hw_priv);
-+ }
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
-+ if (priv) {
-+ spin_unlock(&priv->vif_lock);
-+ }
-+ for (i = 0; i < count; ++i) {
-+ ret = wsm_tx_confirm(hw_priv, buf, interface_link_id);
-+ if (ret)
-+ return ret;
-+ }
-+ return ret;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+/* ******************************************************************** */
-+
-+static int wsm_join_confirm(struct xradio_common *hw_priv,
-+ struct wsm_join *arg,
-+ struct wsm_buf *buf)
-+{
-+ if (WSM_GET32(buf) != WSM_STATUS_SUCCESS)
-+ return -EINVAL;
-+ arg->minPowerLevel = WSM_GET32(buf);
-+ arg->maxPowerLevel = WSM_GET32(buf);
-+
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+int wsm_join(struct xradio_common *hw_priv, struct wsm_join *arg,
-+ int if_id)
-+/*TODO: combo: make it work per vif.*/
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_oper_lock(hw_priv);
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->mode);
-+ WSM_PUT8(buf, arg->band);
-+ WSM_PUT16(buf, arg->channelNumber);
-+ WSM_PUT(buf, &arg->bssid[0], sizeof(arg->bssid));
-+ WSM_PUT16(buf, arg->atimWindow);
-+ WSM_PUT8(buf, arg->preambleType);
-+ WSM_PUT8(buf, arg->probeForJoin);
-+ WSM_PUT8(buf, arg->dtimPeriod);
-+ WSM_PUT8(buf, arg->flags);
-+ WSM_PUT32(buf, arg->ssidLength);
-+ WSM_PUT(buf, &arg->ssid[0], sizeof(arg->ssid));
-+ WSM_PUT32(buf, arg->beaconInterval);
-+ WSM_PUT32(buf, arg->basicRateSet);
-+
-+ hw_priv->tx_burst_idx = -1;
-+ ret = wsm_cmd_send(hw_priv, buf, arg, 0x000B, WSM_CMD_JOIN_TIMEOUT,
-+ if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_oper_unlock(hw_priv); /*confirm, not indcation.*/
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_oper_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_set_bss_params(struct xradio_common *hw_priv,
-+ const struct wsm_set_bss_params *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT8(buf, arg->beaconLostCount);
-+ WSM_PUT16(buf, arg->aid);
-+ WSM_PUT32(buf, arg->operationalRateSet);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0011, WSM_CMD_TIMEOUT,
-+ if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_add_key(struct xradio_common *hw_priv, const struct wsm_add_key *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT(buf, arg, sizeof(*arg));
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x000C, WSM_CMD_TIMEOUT,
-+ if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_remove_key(struct xradio_common *hw_priv,
-+ const struct wsm_remove_key *arg, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->entryIndex);
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT16(buf, 0);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x000D, WSM_CMD_TIMEOUT,
-+ if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_set_tx_queue_params(struct xradio_common *hw_priv,
-+ const struct wsm_set_tx_queue_params *arg,
-+ u8 id, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ u8 queue_id_to_wmm_aci[] = {3, 2, 0, 1};
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, queue_id_to_wmm_aci[id]);
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT8(buf, arg->ackPolicy);
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT32(buf, arg->maxTransmitLifetime);
-+ WSM_PUT16(buf, arg->allowedMediumTime);
-+ WSM_PUT16(buf, 0);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0012, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_set_edca_params(struct xradio_common *hw_priv,
-+ const struct wsm_edca_params *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ /* Implemented according to specification. */
-+
-+ WSM_PUT16(buf, arg->params[3].cwMin);
-+ WSM_PUT16(buf, arg->params[2].cwMin);
-+ WSM_PUT16(buf, arg->params[1].cwMin);
-+ WSM_PUT16(buf, arg->params[0].cwMin);
-+
-+ WSM_PUT16(buf, arg->params[3].cwMax);
-+ WSM_PUT16(buf, arg->params[2].cwMax);
-+ WSM_PUT16(buf, arg->params[1].cwMax);
-+ WSM_PUT16(buf, arg->params[0].cwMax);
-+
-+ WSM_PUT8(buf, arg->params[3].aifns);
-+ WSM_PUT8(buf, arg->params[2].aifns);
-+ WSM_PUT8(buf, arg->params[1].aifns);
-+ WSM_PUT8(buf, arg->params[0].aifns);
-+
-+ WSM_PUT16(buf, arg->params[3].txOpLimit);
-+ WSM_PUT16(buf, arg->params[2].txOpLimit);
-+ WSM_PUT16(buf, arg->params[1].txOpLimit);
-+ WSM_PUT16(buf, arg->params[0].txOpLimit);
-+
-+ WSM_PUT32(buf, arg->params[3].maxReceiveLifetime);
-+ WSM_PUT32(buf, arg->params[2].maxReceiveLifetime);
-+ WSM_PUT32(buf, arg->params[1].maxReceiveLifetime);
-+ WSM_PUT32(buf, arg->params[0].maxReceiveLifetime);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0013, WSM_CMD_TIMEOUT, if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_switch_channel(struct xradio_common *hw_priv,
-+ const struct wsm_switch_channel *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_lock_tx(hw_priv);
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->channelMode);
-+ WSM_PUT8(buf, arg->channelSwitchCount);
-+ WSM_PUT16(buf, arg->newChannelNumber);
-+
-+ hw_priv->channel_switch_in_progress = 1;
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0016, WSM_CMD_TIMEOUT, if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ if (ret) {
-+ wsm_unlock_tx(hw_priv);
-+ hw_priv->channel_switch_in_progress = 0;
-+ }
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_unlock_tx(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_set_pm(struct xradio_common *hw_priv, const struct wsm_set_pm *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_oper_lock(hw_priv);
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->pmMode);
-+ WSM_PUT8(buf, arg->fastPsmIdlePeriod);
-+ WSM_PUT8(buf, arg->apPsmChangePeriod);
-+ WSM_PUT8(buf, arg->minAutoPsPollPeriod);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0010, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ if (ret)
-+ wsm_oper_unlock(hw_priv);
-+
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ wsm_oper_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_start(struct xradio_common *hw_priv, const struct wsm_start *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT8(buf, arg->mode);
-+ WSM_PUT8(buf, arg->band);
-+ WSM_PUT16(buf, arg->channelNumber);
-+ WSM_PUT32(buf, arg->CTWindow);
-+ WSM_PUT32(buf, arg->beaconInterval);
-+ WSM_PUT8(buf, arg->DTIMPeriod);
-+ WSM_PUT8(buf, arg->preambleType);
-+ WSM_PUT8(buf, arg->probeDelay);
-+ WSM_PUT8(buf, arg->ssidLength);
-+ WSM_PUT(buf, arg->ssid, sizeof(arg->ssid));
-+ WSM_PUT32(buf, arg->basicRateSet);
-+
-+ hw_priv->tx_burst_idx = -1;
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0017, WSM_CMD_START_TIMEOUT,
-+ if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+#if 0
-+/* This API is no longer present in WSC */
-+/* ******************************************************************** */
-+
-+int wsm_beacon_transmit(struct xradio_common *hw_priv,
-+ const struct wsm_beacon_transmit *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT32(buf, arg->enableBeaconing ? 1 : 0);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0018, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+#endif
-+
-+/* ******************************************************************** */
-+
-+int wsm_start_find(struct xradio_common *hw_priv, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0019, WSM_CMD_TIMEOUT, if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_stop_find(struct xradio_common *hw_priv, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x001A, WSM_CMD_TIMEOUT, if_id);
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_map_link(struct xradio_common *hw_priv, const struct wsm_map_link *arg,
-+ int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+ u16 cmd = 0x001C;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT(buf, &arg->mac_addr[0], sizeof(arg->mac_addr));
-+
-+ if (is_hardware_xradio(hw_priv)) {
-+ WSM_PUT8(buf, arg->unmap);
-+ WSM_PUT8(buf, arg->link_id);
-+ } else {
-+ cmd |= WSM_TX_LINK_ID(arg->link_id);
-+ WSM_PUT16(buf, 0);
-+ }
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, cmd, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+}
-+
-+/* ******************************************************************** */
-+
-+int wsm_update_ie(struct xradio_common *hw_priv,
-+ const struct wsm_update_ie *arg, int if_id)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(hw_priv);
-+
-+ WSM_PUT16(buf, arg->what);
-+ WSM_PUT16(buf, arg->count);
-+ WSM_PUT(buf, arg->ies, arg->length);
-+
-+ ret = wsm_cmd_send(hw_priv, buf, NULL, 0x001B, WSM_CMD_TIMEOUT, if_id);
-+
-+ wsm_cmd_unlock(hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(hw_priv);
-+ return -ENOMEM;
-+
-+}
-+/* ******************************************************************** */
-+#ifdef MCAST_FWDING
-+/* 3.66 */
-+static int wsm_give_buffer_confirm(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ wsm_printk(XRADIO_DBG_MSG, "HW Buf count %d\n", hw_priv->hw_bufs_used);
-+ if (!hw_priv->hw_bufs_used)
-+ wake_up(&hw_priv->bh_evt_wq);
-+
-+ return 0;
-+}
-+
-+/* 3.65 */
-+int wsm_init_release_buffer_request(struct xradio_common *hw_priv, u8 index)
-+{
-+ struct wsm_buf *buf = &hw_priv->wsm_release_buf[index];
-+ u16 cmd = 0x0022; /* Buffer Request */
-+ u8 flags;
-+ size_t buf_len;
-+
-+ wsm_buf_init(buf);
-+
-+ flags = index ? 0: 0x1;
-+
-+ WSM_PUT8(buf, flags);
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT16(buf, 0);
-+
-+ buf_len = buf->data - buf->begin;
-+
-+ /* Fill HI message header */
-+ ((__le16 *)buf->begin)[0] = __cpu_to_le16(buf_len);
-+ ((__le16 *)buf->begin)[1] = __cpu_to_le16(cmd);
-+
-+ return 0;
-+nomem:
-+ return -ENOMEM;
-+}
-+
-+/* 3.65 fixed memory leakage by yangfh*/
-+int wsm_deinit_release_buffer(struct xradio_common *hw_priv)
-+{
-+ struct wsm_buf *buf = NULL;
-+ int i, err = 0;
-+
-+ for (i = 0; i < WSM_MAX_BUF; i++) {
-+ buf = &hw_priv->wsm_release_buf[i];
-+ if(likely(buf)) {
-+ if(likely(buf->begin))
-+ kfree(buf->begin);
-+ buf->begin = buf->data = buf->end = NULL;
-+ } else {
-+ err++;
-+ }
-+ }
-+ if(err) wsm_printk(XRADIO_DBG_ERROR, "%s, NULL buf=%d!\n", __func__, err);
-+ return 0;
-+}
-+
-+/* 3.68 */
-+static int wsm_request_buffer_confirm(struct xradio_vif *priv,
-+ u8 *arg,
-+ struct wsm_buf *buf)
-+{
-+ u8 count;
-+ u32 sta_asleep_mask = 0;
-+ int i;
-+ u32 mask = 0;
-+ u32 change_mask = 0;
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+
-+ /* There is no status field in this message */
-+ sta_asleep_mask = WSM_GET32(buf);
-+ count = WSM_GET8(buf);
-+ count -= 1; /* Current workaround for FW issue */
-+
-+ spin_lock_bh(&priv->ps_state_lock);
-+ change_mask = (priv->sta_asleep_mask ^ sta_asleep_mask);
-+ wsm_printk(XRADIO_DBG_MSG, "CM %x, HM %x, FWM %x\n", change_mask,priv->sta_asleep_mask, sta_asleep_mask);
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+ if (change_mask) {
-+ struct ieee80211_sta *sta;
-+ int ret = 0;
-+
-+
-+ for (i = 0; i < MAX_STA_IN_AP_MODE ; ++i) {
-+
-+ if(XRADIO_LINK_HARD != priv->link_id_db[i].status)
-+ continue;
-+
-+ mask = BIT(i + 1);
-+
-+ /* If FW state and host state for this link are different then notify OMAC */
-+ if(change_mask & mask) {
-+ wsm_printk(XRADIO_DBG_MSG, "PS State Changed %d for sta %pM\n", (sta_asleep_mask & mask) ? 1:0, priv->link_id_db[i].mac);
-+ rcu_read_lock();
-+ sta = ieee80211_find_sta(priv->vif, priv->link_id_db[i].mac);
-+ if (!sta) {
-+ wsm_printk(XRADIO_DBG_MSG, "WRBC - could not find sta %pM\n",
-+ priv->link_id_db[i].mac);
-+ } else {
-+ ret = ieee80211_sta_ps_transition_ni(sta, (sta_asleep_mask & mask) ? true: false);
-+ wsm_printk(XRADIO_DBG_MSG, "PS State NOTIFIED %d\n", ret);
-+ WARN_ON(ret);
-+ }
-+ rcu_read_unlock();
-+ }
-+ }
-+ /* Replace STA mask with one reported by FW */
-+ spin_lock_bh(&priv->ps_state_lock);
-+ priv->sta_asleep_mask = sta_asleep_mask;
-+ spin_unlock_bh(&priv->ps_state_lock);
-+ }
-+
-+ wsm_printk(XRADIO_DBG_MSG, "WRBC - HW Buf count %d SleepMask %d\n",
-+ hw_priv->hw_bufs_used, sta_asleep_mask);
-+ hw_priv->buf_released = 0;
-+ WARN_ON(count != (hw_priv->wsm_caps.numInpChBufs - 1));
-+
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+/* 3.67 */
-+int wsm_request_buffer_request(struct xradio_vif *priv,
-+ u8 *arg)
-+{
-+ int ret;
-+ struct wsm_buf *buf = &priv->hw_priv->wsm_cmd_buf;
-+
-+ wsm_cmd_lock(priv->hw_priv);
-+
-+ WSM_PUT8(buf, (*arg));
-+ WSM_PUT8(buf, 0);
-+ WSM_PUT16(buf, 0);
-+
-+ ret = wsm_cmd_send(priv->hw_priv, buf, arg, 0x0023, WSM_CMD_JOIN_TIMEOUT,priv->if_id);
-+
-+ wsm_cmd_unlock(priv->hw_priv);
-+ return ret;
-+
-+nomem:
-+ wsm_cmd_unlock(priv->hw_priv);
-+ return -ENOMEM;
-+}
-+
-+#endif
-+
-+int wsm_set_keepalive_filter(struct xradio_vif *priv, bool enable)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ priv->rx_filter.keepalive = enable;
-+ return wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
-+}
-+
-+int wsm_set_probe_responder(struct xradio_vif *priv, bool enable)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+
-+ priv->rx_filter.probeResponder = enable;
-+ return wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
-+}
-+/* ******************************************************************** */
-+/* WSM indication events implementation */
-+
-+static int wsm_startup_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ u16 status;
-+ static const char * const fw_types[] = {
-+ "ETF",
-+ "WFM",
-+ "WSM",
-+ "HI test",
-+ "Platform test"
-+ };
-+
-+ hw_priv->wsm_caps.numInpChBufs = WSM_GET16(buf);
-+ hw_priv->wsm_caps.sizeInpChBuf = WSM_GET16(buf);
-+ hw_priv->wsm_caps.hardwareId = WSM_GET16(buf);
-+ hw_priv->wsm_caps.hardwareSubId = WSM_GET16(buf);
-+ status = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareCap = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareType = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareApiVer = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareBuildNumber = WSM_GET16(buf);
-+ hw_priv->wsm_caps.firmwareVersion = WSM_GET16(buf);
-+ WSM_GET(buf, &hw_priv->wsm_caps.fw_label[0], WSM_FW_LABEL);
-+ hw_priv->wsm_caps.fw_label[WSM_FW_LABEL+1] = 0; /* Do not trust FW too much. */
-+
-+ if (WARN_ON(status))
-+ return -EINVAL;
-+
-+ if (WARN_ON(hw_priv->wsm_caps.firmwareType > 4))
-+ return -EINVAL;
-+
-+ dev_info(hw_priv->pdev,
-+ " Input buffers: %d x %d bytes\n"
-+ " Hardware: %d.%d\n"
-+ " %s firmware ver: %d, build: %d,"
-+ " api: %d, cap: 0x%.4X\n",
-+ hw_priv->wsm_caps.numInpChBufs,
-+ hw_priv->wsm_caps.sizeInpChBuf,
-+ hw_priv->wsm_caps.hardwareId,
-+ hw_priv->wsm_caps.hardwareSubId,
-+ fw_types[hw_priv->wsm_caps.firmwareType],
-+ hw_priv->wsm_caps.firmwareVersion,
-+ hw_priv->wsm_caps.firmwareBuildNumber,
-+ hw_priv->wsm_caps.firmwareApiVer,
-+ hw_priv->wsm_caps.firmwareCap);
-+
-+ dev_info(hw_priv->pdev, "Firmware Label:%s\n", &hw_priv->wsm_caps.fw_label[0]);
-+
-+ hw_priv->wsm_caps.firmwareReady = 1;
-+
-+ wake_up(&hw_priv->wsm_startup_done);
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+//add by yangfh 2014-10-31 16:58:53
-+void wms_send_deauth_to_self(struct xradio_common *hw_priv, struct xradio_vif *priv)
-+{
-+ struct sk_buff *skb = NULL;
-+ struct ieee80211_mgmt *deauth = NULL;
-+
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ int i = 0;
-+ wsm_printk(XRADIO_DBG_WARN, "AP mode, send_deauth_to_self\n");
-+ for (i = 0; ilink_id_db[i].status == XRADIO_LINK_HARD) {
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, 64);
-+ deauth = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ if(!deauth) {
-+ WARN_ON(1);
-+ return;
-+ }
-+ deauth->frame_control =
-+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
-+ deauth->duration = 0;
-+ memcpy(deauth->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(deauth->sa, priv->link_id_db[i].mac, ETH_ALEN);
-+ memcpy(deauth->bssid, priv->vif->addr, ETH_ALEN);
-+ deauth->seq_ctrl = 0;
-+ deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+ }
-+ } else if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ wsm_printk(XRADIO_DBG_WARN, "STA mode, send_deauth_to_self\n");
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, 64);
-+ deauth = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ if(!deauth) {
-+ WARN_ON(1);
-+ return;
-+ }
-+ deauth->frame_control =
-+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
-+ deauth->duration = 0;
-+ memcpy(deauth->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(deauth->sa, priv->join_bssid, ETH_ALEN);
-+ memcpy(deauth->bssid, priv->join_bssid, ETH_ALEN);
-+ deauth->seq_ctrl = 0;
-+ deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+}
-+
-+void wms_send_disassoc_to_self(struct xradio_common *hw_priv, struct xradio_vif *priv)
-+{
-+ struct sk_buff *skb = NULL;
-+ struct ieee80211_mgmt *disassoc = NULL;
-+ if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
-+ int i = 0;
-+ wsm_printk(XRADIO_DBG_WARN, "AP mode, wms_send_disassoc_to_self\n");
-+ for (i = 0; ilink_id_db[i].status == XRADIO_LINK_HARD) {
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, 64);
-+ disassoc = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ if(!disassoc) {
-+ WARN_ON(1);
-+ return;
-+ }
-+ disassoc->frame_control =
-+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC);
-+ disassoc->duration = 0;
-+ memcpy(disassoc->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(disassoc->sa, priv->link_id_db[i].mac, ETH_ALEN);
-+ memcpy(disassoc->bssid, priv->vif->addr, ETH_ALEN);
-+ disassoc->seq_ctrl = 0;
-+ disassoc->u.disassoc.reason_code = WLAN_REASON_DISASSOC_STA_HAS_LEFT;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+ }
-+ } else if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ wsm_printk(XRADIO_DBG_WARN, "STA mode, wms_send_disassoc_to_self\n");
-+ skb = dev_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
-+ if (!skb)
-+ return;
-+ skb_reserve(skb, 64);
-+ disassoc = (struct ieee80211_mgmt *)skb_put(skb, sizeof(struct ieee80211_mgmt));
-+ if(!disassoc) {
-+ WARN_ON(1);
-+ return;
-+ }
-+ disassoc->frame_control =
-+ cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC);
-+ disassoc->duration = 0;
-+ memcpy(disassoc->da, priv->vif->addr, ETH_ALEN);
-+ memcpy(disassoc->sa, priv->join_bssid, ETH_ALEN);
-+ memcpy(disassoc->bssid, priv->join_bssid, ETH_ALEN);
-+ disassoc->seq_ctrl = 0;
-+ disassoc->u.disassoc.reason_code = WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY;
-+ ieee80211_rx_irqsafe(priv->hw, skb);
-+ }
-+}
-+
-+static int wsm_receive_indication(struct xradio_common *hw_priv,
-+ int interface_link_id,
-+ struct wsm_buf *buf,
-+ struct sk_buff **skb_p)
-+{
-+ struct xradio_vif *priv;
-+ struct wsm_rx rx;
-+ struct ieee80211_hdr *hdr;
-+ size_t hdr_len;
-+
-+ hw_priv->rx_timestamp = jiffies;
-+
-+ rx.status = WSM_GET32(buf);
-+ rx.channelNumber = WSM_GET16(buf);
-+ rx.rxedRate = WSM_GET8(buf);
-+ rx.rcpiRssi = WSM_GET8(buf);
-+ rx.flags = WSM_GET32(buf);
-+
-+ /* TODO:COMBO: Frames received from scanning are received
-+ * with interface ID == 2 */
-+ if (is_hardware_xradio(hw_priv)) {
-+ if (interface_link_id == XRWL_GENERIC_IF_ID) {
-+ /* Frames received in response to SCAN
-+ * Request */
-+ interface_link_id =
-+ get_interface_id_scanning(hw_priv);
-+ if (interface_link_id == -1) {
-+ interface_link_id = hw_priv->roc_if_id;
-+ }
-+#ifdef ROAM_OFFLOAD
-+ if (hw_priv->auto_scanning) {
-+ interface_link_id = hw_priv->scan.if_id;
-+ }
-+#endif/*ROAM_OFFLOAD*/
-+ }
-+ /* linkid (peer sta id is encoded in bit 25-28 of
-+ flags field */
-+ rx.link_id = ((rx.flags & (0xf << 25)) >> 25);
-+ rx.if_id = interface_link_id;
-+ } else {
-+ rx.link_id = interface_link_id;
-+ rx.if_id = 0;
-+ }
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, rx.if_id);
-+ if (!priv) {
-+ dev_dbg(hw_priv->pdev, "got frame on a vif we don't have, dropped\n");
-+ return 0;
-+ }
-+ //remove wsm hdr of skb
-+ hdr_len = buf->data - buf->begin;
-+ skb_pull(*skb_p, hdr_len);
-+
-+ /* FW Workaround: Drop probe resp or
-+ beacon when RSSI is 0 */
-+ hdr = (struct ieee80211_hdr *) (*skb_p)->data;
-+
-+ if (!rx.rcpiRssi &&
-+ (ieee80211_is_probe_resp(hdr->frame_control) ||
-+ ieee80211_is_beacon(hdr->frame_control))) {
-+ spin_unlock(&priv->vif_lock);
-+ return 0;
-+ }
-+
-+ /* If no RSSI subscription has been made,
-+ * convert RCPI to RSSI here */
-+ if (!priv->cqm_use_rssi)
-+ rx.rcpiRssi = rx.rcpiRssi / 2 - 110;
-+
-+ if (!rx.status && unlikely(ieee80211_is_deauth(hdr->frame_control))) {
-+ if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
-+ /* Shedule unjoin work */
-+ dev_dbg(hw_priv->pdev,
-+ "Issue unjoin command (RX).\n");
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue,
-+ &priv->unjoin_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+ xradio_rx_cb(priv, &rx, skb_p);
-+ if (*skb_p)
-+ skb_push(*skb_p, hdr_len);
-+ spin_unlock(&priv->vif_lock);
-+
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+
-+static int wsm_event_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf,
-+ int interface_link_id)
-+{
-+ int first;
-+ struct xradio_wsm_event *event = NULL;
-+ struct xradio_vif *priv;
-+
-+ if (!is_hardware_xradio(hw_priv))
-+ interface_link_id = 0;
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
-+
-+ if (unlikely(!priv)) {
-+ dev_warn(hw_priv->pdev, "Event: %d(%d) for removed "
-+ "interface, ignoring\n", __le32_to_cpu(WSM_GET32(buf)),
-+ __le32_to_cpu(WSM_GET32(buf)));
-+ return 0;
-+ }
-+
-+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
-+ /* STA is stopped. */
-+ return 0;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+
-+ event = kzalloc(sizeof(struct xradio_wsm_event), GFP_KERNEL);
-+ if (event == NULL) {
-+ dev_err(hw_priv->pdev, "xr_kzalloc failed!");
-+ return -EINVAL;
-+ }
-+
-+ event->evt.eventId = __le32_to_cpu(WSM_GET32(buf));
-+ event->evt.eventData = __le32_to_cpu(WSM_GET32(buf));
-+ event->if_id = interface_link_id;
-+
-+ dev_dbg(hw_priv->pdev, "Event: %d(%d)\n",
-+ event->evt.eventId, event->evt.eventData);
-+
-+ spin_lock(&hw_priv->event_queue_lock);
-+ first = list_empty(&hw_priv->event_queue);
-+ list_add_tail(&event->link, &hw_priv->event_queue);
-+ spin_unlock(&hw_priv->event_queue_lock);
-+
-+ if (first)
-+ queue_work(hw_priv->workqueue, &hw_priv->event_handler);
-+
-+ return 0;
-+
-+underflow:
-+ kfree(event);
-+ return -EINVAL;
-+}
-+
-+#define PRINT_11K_MEASRURE 1
-+static int wsm_measure_cmpl_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ MEASUREMENT_COMPLETE measure_cmpl;
-+ u8 cca_chanload;
-+ u32 buf_len = 0;
-+ u32 *data;
-+
-+ LMAC_MEAS_CHANNEL_LOAD_RESULTS *chanload_res;
-+ LMAC_MEAS_NOISE_HISTOGRAM_RESULTS *noise_res;
-+ WSM_GET(buf, &measure_cmpl, 12);
-+
-+ switch (measure_cmpl.MeasurementType) {
-+ case ChannelLoadMeasurement:
-+ buf_len = sizeof(LMAC_MEAS_CHANNEL_LOAD_RESULTS);
-+ break;
-+ case NoiseHistrogramMeasurement:
-+ buf_len = sizeof(LMAC_MEAS_NOISE_HISTOGRAM_RESULTS);
-+ break;
-+ case BeaconReport:
-+ buf_len = sizeof(LMAC_MEAS_BEACON_RESULTS);
-+ break;
-+ case STAstatisticsReport:
-+ buf_len = sizeof(LMAC_MEAS_STA_STATS_RESULTS);
-+ break;
-+ case LinkMeasurement:
-+ buf_len = sizeof(LMAC_MEAS_LINK_MEASUREMENT_RESULTS);
-+ break;
-+ }
-+ wsm_printk(XRADIO_DBG_ERROR, "[11K]buf_len = %d\n", buf_len);
-+ WSM_GET(buf, &measure_cmpl.MeasurementReport, buf_len);
-+
-+ data = (u32 *)(&measure_cmpl);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[0]=%08x\n", data[0]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[1]=%08x\n", data[1]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[2]=%08x\n", data[2]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[3]=%08x\n", data[3]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[4]=%08x\n", data[4]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[5]=%08x\n", data[5]);
-+// wsm_printk(XRADIO_DBG_ERROR, "[***HL***]data[6]=%08x\n", data[6]);
-+ wsm_printk(XRADIO_DBG_ERROR, "[***HL***]MeasurementType=%0d\n", measure_cmpl.MeasurementType);
-+
-+ if (measure_cmpl.Status == WSM_STATUS_SUCCESS){
-+ switch (measure_cmpl.MeasurementType) {
-+ case ChannelLoadMeasurement:
-+ chanload_res = &measure_cmpl.MeasurementReport.ChannelLoadResults;
-+ cca_chanload = (chanload_res->ChannelLoadCCA == MEAS_CCA) ?
-+ chanload_res->CCAbusyFraction :
-+ chanload_res->ChannelLoad;
-+ #ifdef PRINT_11K_MEASRURE
-+ wsm_printk(XRADIO_DBG_ERROR, "[11K] ChannelLoadMeasurement Result:\n"\
-+ "ChannelLoadCCA = %d\n"\
-+ "ChannelNum = %d\n"\
-+ "Duration = %d\n"\
-+ "Fraction = %d\n", \
-+ chanload_res->ChannelLoadCCA,\
-+ chanload_res->ChannelNum,\
-+ chanload_res->MeasurementDuration,\
-+ cca_chanload
-+ );
-+ #endif
-+ break;
-+ case NoiseHistrogramMeasurement:
-+ noise_res = &measure_cmpl.MeasurementReport.NoiseHistogramResults;
-+// IpiRpi = (noise_res->IpiRpi == MEAS_RPI) ?
-+// chanload_res->CCAbusyFraction :
-+// chanload_res->ChannelLoad;
-+ #ifdef PRINT_11K_MEASRURE
-+ wsm_printk(XRADIO_DBG_ERROR, "[11K] NoiseHistogramResults:\n"\
-+ "IpiRpi = %d\n"\
-+ "ChannelNum = %d\n"\
-+ "PI_0__Density = %d\n"\
-+ "PI_1__Density = %d\n"\
-+ "PI_2__Density = %d\n"\
-+ "PI_3__Density = %d\n"\
-+ "PI_4__Density = %d\n"\
-+ "PI_5__Density = %d\n"\
-+ "PI_6__Density = %d\n"\
-+ "PI_7__Density = %d\n"\
-+ "PI_8__Density = %d\n"\
-+ "PI_9__Density = %d\n"\
-+ "PI_10_Density = %d\n", \
-+ noise_res->IpiRpi,\
-+ noise_res->ChannelNum,\
-+ noise_res->PI_0_Density,\
-+ noise_res->PI_1_Density,\
-+ noise_res->PI_2_Density,\
-+ noise_res->PI_3_Density,\
-+ noise_res->PI_4_Density,\
-+ noise_res->PI_5_Density,\
-+ noise_res->PI_6_Density,\
-+ noise_res->PI_7_Density,\
-+ noise_res->PI_8_Density,\
-+ noise_res->PI_9_Density,\
-+ noise_res->PI_10_Density
-+ );
-+ #endif
-+ break;
-+ case BeaconReport:
-+ break;
-+ case STAstatisticsReport:
-+ break;
-+ case LinkMeasurement:
-+ break;
-+ }
-+ } else {
-+ wsm_printk(XRADIO_DBG_ERROR, "11K Measure(type=%d) Fail\n", measure_cmpl.MeasurementType);
-+ }
-+
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+/* TODO:COMBO:Make this perVIFF once mac80211 support is available */
-+static int wsm_channel_switch_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ wsm_unlock_tx(hw_priv); /* Re-enable datapath */
-+ WARN_ON(WSM_GET32(buf));
-+
-+ hw_priv->channel_switch_in_progress = 0;
-+ wake_up(&hw_priv->channel_switch_done);
-+
-+
-+ xradio_channel_switch_cb(hw_priv);
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+
-+static int wsm_set_pm_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ wsm_oper_unlock(hw_priv);
-+ return 0;
-+}
-+
-+static int wsm_scan_complete_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ struct wsm_scan_complete arg;
-+#ifdef ROAM_OFFLOAD
-+ if(hw_priv->auto_scanning == 0)
-+ wsm_oper_unlock(hw_priv);
-+#else
-+ wsm_oper_unlock(hw_priv);
-+#endif /*ROAM_OFFLOAD*/
-+
-+ arg.status = WSM_GET32(buf);
-+ arg.psm = WSM_GET8(buf);
-+ arg.numChannels = WSM_GET8(buf);
-+ xradio_scan_complete_cb(hw_priv, &arg);
-+
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+
-+static int wsm_find_complete_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ /* TODO: Implement me. */
-+ //STUB();
-+ return 0;
-+}
-+
-+static int wsm_suspend_resume_indication(struct xradio_common *hw_priv,
-+ int interface_link_id,
-+ struct wsm_buf *buf)
-+{
-+ u32 flags;
-+ struct wsm_suspend_resume arg;
-+ struct xradio_vif *priv;
-+
-+ if (is_hardware_xradio(hw_priv)) {
-+ int i;
-+ arg.if_id = interface_link_id;
-+ /* TODO:COMBO: Extract bitmap from suspend-resume
-+ * TX indication */
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ if (priv->join_status ==
-+ XRADIO_JOIN_STATUS_AP) {
-+ arg.if_id = priv->if_id;
-+ break;
-+ }
-+ arg.link_id = 0;
-+ }
-+ } else {
-+ arg.if_id = 0;
-+ arg.link_id = interface_link_id;
-+ }
-+
-+ flags = WSM_GET32(buf);
-+ arg.stop = !(flags & 1);
-+ arg.multicast = !!(flags & 8);
-+ arg.queue = (flags >> 1) & 3;
-+
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, arg.if_id);
-+ if (unlikely(!priv)) {
-+ wsm_printk(XRADIO_DBG_MSG, "suspend-resume indication"
-+ " for removed interface!\n");
-+ return 0;
-+ }
-+ xradio_suspend_resume(priv, &arg);
-+ spin_unlock(&priv->vif_lock);
-+
-+ return 0;
-+
-+underflow:
-+ return -EINVAL;
-+}
-+
-+
-+/* ******************************************************************** */
-+/* WSM TX */
-+
-+int wsm_cmd_send(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf,
-+ void *arg, u16 cmd, long tmo, int if_id)
-+{
-+ size_t buf_len = buf->data - buf->begin;
-+ int ret;
-+
-+ if (cmd == 0x0006 || cmd == 0x0005) /* Write/Read MIB */
-+ wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X [MIB: 0x%.4X] (%d)\n",
-+ cmd, __le16_to_cpu(((__le16 *)buf->begin)[2]),
-+ buf_len);
-+ else
-+ wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X (%d)\n", cmd, buf_len);
-+
-+ if (unlikely(hw_priv->bh_error)) {
-+ wsm_buf_reset(buf);
-+ wsm_printk(XRADIO_DBG_ERROR, "bh error!>>> 0x%.4X (%d)\n", cmd, buf_len);
-+ return -ETIMEDOUT;
-+ }
-+
-+ /* Fill HI message header */
-+ /* BH will add sequence number */
-+
-+ /* TODO:COMBO: Add if_id from to the WSM header */
-+ /* if_id == -1 indicates that command is HW specific,
-+ * eg. wsm_configuration which is called during driver initialzation
-+ * (mac80211 .start callback called when first ifce is created. )*/
-+
-+ /* send hw specific commands on if 0 */
-+ if (if_id == -1)
-+ if_id = 0;
-+
-+ ((__le16 *)buf->begin)[0] = __cpu_to_le16(buf_len);
-+ ((__le16 *)buf->begin)[1] = __cpu_to_le16(cmd |
-+ ((is_hardware_xradio(hw_priv)) ? (if_id << 6) : 0));
-+
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ BUG_ON(hw_priv->wsm_cmd.ptr);
-+ hw_priv->wsm_cmd.done = 0;
-+ hw_priv->wsm_cmd.ptr = buf->begin;
-+ hw_priv->wsm_cmd.len = buf_len;
-+ hw_priv->wsm_cmd.arg = arg;
-+ hw_priv->wsm_cmd.cmd = cmd;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+
-+ xradio_bh_wakeup(hw_priv);
-+
-+ if (unlikely(hw_priv->bh_error)) {
-+ /* Do not wait for timeout if BH is dead. Exit immediately. */
-+ ret = 0;
-+ } else {
-+ unsigned long wsm_cmd_max_tmo;
-+
-+ /* Give start cmd a little more time */
-+ if (unlikely(tmo == WSM_CMD_START_TIMEOUT))
-+ wsm_cmd_max_tmo = WSM_CMD_START_TIMEOUT;
-+ else
-+ wsm_cmd_max_tmo = WSM_CMD_DEFAULT_TIMEOUT;
-+
-+ /*Set max timeout.*/
-+ wsm_cmd_max_tmo = jiffies + wsm_cmd_max_tmo;
-+
-+ /* Firmware prioritizes data traffic over control confirm.
-+ * Loop below checks if data was RXed and increases timeout
-+ * accordingly. */
-+ do {
-+ /* It's safe to use unprotected access to wsm_cmd.done here */
-+ ret = wait_event_timeout(hw_priv->wsm_cmd_wq, hw_priv->wsm_cmd.done, tmo);
-+
-+ /* check time since last rxed and max timeout.*/
-+ } while (!ret &&
-+ time_before_eq(jiffies, hw_priv->rx_timestamp+tmo) &&
-+ time_before(jiffies, wsm_cmd_max_tmo));
-+
-+ }
-+
-+ if (unlikely(ret == 0)) {
-+ u16 raceCheck;
-+
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ raceCheck = hw_priv->wsm_cmd.cmd;
-+ hw_priv->wsm_cmd.arg = NULL;
-+ hw_priv->wsm_cmd.ptr = NULL;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+
-+ dev_err(hw_priv->pdev, "***CMD timeout!>>> 0x%.4X (%d), buf_use=%d, bh_state=%d\n",
-+ cmd, buf_len, hw_priv->hw_bufs_used, hw_priv->bh_error);
-+ /* Race condition check to make sure _confirm is not called
-+ * after exit of _send */
-+ if (raceCheck == 0xFFFF) {
-+ /* If wsm_handle_rx got stuck in _confirm we will hang
-+ * system there. It's better than silently currupt
-+ * stack or heap, isn't it? */
-+ BUG_ON(wait_event_timeout(
-+ hw_priv->wsm_cmd_wq,
-+ hw_priv->wsm_cmd.done,
-+ WSM_CMD_LAST_CHANCE_TIMEOUT) <= 0);
-+ }
-+
-+ /* Kill BH thread to report the error to the top layer. */
-+ hw_priv->bh_error = 1;
-+#ifdef BH_USE_SEMAPHORE
-+ up(&hw_priv->bh_sem);
-+#else
-+ wake_up(&hw_priv->bh_wq);
-+#endif
-+ ret = -ETIMEDOUT;
-+ } else {
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ BUG_ON(!hw_priv->wsm_cmd.done);
-+ ret = hw_priv->wsm_cmd.ret;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ }
-+ wsm_buf_reset(buf);
-+ return ret;
-+}
-+
-+/* ******************************************************************** */
-+/* WSM TX port control */
-+
-+void wsm_lock_tx(struct xradio_common *hw_priv)
-+{
-+ down(&hw_priv->tx_lock_sem);
-+ atomic_add(1, &hw_priv->tx_lock);
-+ /* always check event if wsm_vif_lock_tx.*/
-+ if (wsm_flush_tx(hw_priv))
-+ wsm_printk(XRADIO_DBG_MSG, "TX is locked.\n");
-+ up(&hw_priv->tx_lock_sem);
-+}
-+
-+void wsm_vif_lock_tx(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+ down(&hw_priv->tx_lock_sem);
-+ if (atomic_add_return(1, &hw_priv->tx_lock) == 1) {
-+ if (wsm_vif_flush_tx(priv))
-+ wsm_printk(XRADIO_DBG_MSG, "TX is locked for"
-+ " if_id %d.\n", priv->if_id);
-+ }
-+ up(&hw_priv->tx_lock_sem);
-+}
-+
-+void wsm_lock_tx_async(struct xradio_common *hw_priv)
-+{
-+ if (atomic_add_return(1, &hw_priv->tx_lock) == 1)
-+ wsm_printk(XRADIO_DBG_MSG, "TX is locked (async).\n");
-+}
-+
-+bool wsm_flush_tx(struct xradio_common *hw_priv)
-+{
-+ long timeout = WSM_CMD_LAST_CHANCE_TIMEOUT;
-+
-+ /* Flush must be called with TX lock held. */
-+ BUG_ON(!atomic_read(&hw_priv->tx_lock));
-+
-+ /* First check if we really need to do something.
-+ * It is safe to use unprotected access, as hw_bufs_used
-+ * can only decrements. */
-+ if (!hw_priv->hw_bufs_used)
-+ return true;
-+
-+ if (hw_priv->bh_error) {
-+ /* In case of failure do not wait for magic. */
-+ wsm_printk(XRADIO_DBG_ERROR, "Fatal error occured, "
-+ "will not flush TX.\n");
-+ return false;
-+ } else {
-+ /* Get "oldest" frame, if any frames stuck in firmware,
-+ query all of them until max timeout. */
-+ int num = hw_priv->hw_bufs_used + 1;
-+ while (xradio_query_txpkt_timeout(hw_priv, XRWL_ALL_IFS,
-+ 0xffffffff, &timeout)) {
-+ if (timeout < 0 || !num) {
-+ /* Hmmm... Not good. Frame had stuck in firmware. */
-+ wsm_printk(XRADIO_DBG_ERROR,
-+ "%s:hw_bufs_used=%d, num=%d, timeout=%ld\n",
-+ __func__, hw_priv->hw_bufs_used, num, timeout);
-+ hw_priv->bh_error = 1;
-+#ifdef BH_USE_SEMAPHORE
-+ up(&hw_priv->bh_sem);
-+#else
-+ wake_up(&hw_priv->bh_wq);
-+#endif
-+ return false;
-+ } else if (wait_event_timeout(hw_priv->bh_evt_wq,
-+ !hw_priv->hw_bufs_used, timeout) > 0) {
-+ return true;
-+ }
-+ --num;
-+ }
-+ if (hw_priv->hw_bufs_used)
-+ wsm_printk(XRADIO_DBG_ERROR, "%s:No pengding, but hw_bufs_used=%d\n",
-+ __func__, hw_priv->hw_bufs_used);
-+ /* Ok, everything is flushed. */
-+ return true;
-+ }
-+}
-+
-+bool wsm_vif_flush_tx(struct xradio_vif *priv)
-+{
-+ struct xradio_common *hw_priv = priv->hw_priv;
-+ long timeout = WSM_CMD_LAST_CHANCE_TIMEOUT;
-+ int if_id = priv->if_id;
-+
-+ /* Flush must be called with TX lock held. */
-+ BUG_ON(!atomic_read(&hw_priv->tx_lock));
-+
-+ /* First check if we really need to do something.
-+ * It is safe to use unprotected access, as hw_bufs_used
-+ * can only decrements. */
-+ if (!hw_priv->hw_bufs_used_vif[if_id])
-+ return true;
-+
-+ if (hw_priv->bh_error) {
-+ /* In case of failure do not wait for magic. */
-+ wsm_printk(XRADIO_DBG_ERROR, "Fatal error occured, "
-+ "will not flush TX.\n");
-+ return false;
-+ } else {
-+ /* Get "oldest" frame, if any frames stuck in firmware,
-+ query all of them until max timeout. */
-+ int num = hw_priv->hw_bufs_used_vif[if_id] + 1;
-+ while (xradio_query_txpkt_timeout(hw_priv, if_id, 0xffffffff, &timeout)) {
-+ if (timeout < 0 || !num) {
-+ /* Hmmm... Not good. Frame had stuck in firmware. */
-+ wsm_printk(XRADIO_DBG_ERROR, "%s: if_id=%d, hw_bufs_used_vif=%d, num=%d\n",
-+ __func__, if_id, hw_priv->hw_bufs_used_vif[priv->if_id],
-+ num);
-+ hw_priv->bh_error = 1;
-+ #ifdef BH_USE_SEMAPHORE
-+ up(&hw_priv->bh_sem);
-+ #else
-+ wake_up(&hw_priv->bh_wq);
-+ #endif
-+ return false;
-+ } else if (wait_event_timeout(hw_priv->bh_evt_wq,
-+ !hw_priv->hw_bufs_used_vif[if_id], timeout) > 0) {
-+ return true;
-+ }
-+ --num;
-+ }
-+ if (hw_priv->hw_bufs_used_vif[if_id])
-+ wsm_printk(XRADIO_DBG_ERROR, "%s:No pengding, but hw_bufs_used_vif=%d\n",
-+ __func__, hw_priv->hw_bufs_used_vif[priv->if_id]);
-+ /* Ok, everything is flushed. */
-+ return true;
-+ }
-+}
-+
-+
-+void wsm_unlock_tx(struct xradio_common *hw_priv)
-+{
-+ int tx_lock;
-+ if (hw_priv->bh_error)
-+ wsm_printk(XRADIO_DBG_ERROR, "bh_error=%d, wsm_unlock_tx is unsafe\n",
-+ hw_priv->bh_error);
-+ else {
-+ tx_lock = atomic_sub_return(1, &hw_priv->tx_lock);
-+ if (tx_lock < 0) {
-+ BUG_ON(1);
-+ } else if (tx_lock == 0) {
-+ xradio_bh_wakeup(hw_priv);
-+ wsm_printk(XRADIO_DBG_MSG, "TX is unlocked.\n");
-+ }
-+ }
-+}
-+
-+/* ******************************************************************** */
-+/* WSM RX */
-+
-+int wsm_handle_exception(struct xradio_common *hw_priv, u8 *data, size_t len)
-+{
-+ struct wsm_buf buf;
-+ u32 reason;
-+ u32 reg[18];
-+ char fname[48];
-+ int i = 0;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ struct xradio_vif *priv = NULL;
-+#endif
-+
-+ static const char * const reason_str[] = {
-+ "undefined instruction",
-+ "prefetch abort",
-+ "data abort",
-+ "unknown error",
-+ };
-+
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ /* Send the event upwards on the FW exception */
-+ xradio_pm_stay_awake(&hw_priv->pm_state, 3*HZ);
-+
-+ spin_lock(&hw_priv->vif_list_lock);
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (!priv)
-+ continue;
-+ //ieee80211_driver_hang_notify(priv->vif, GFP_KERNEL);
-+ }
-+ spin_unlock(&hw_priv->vif_list_lock);
-+#endif
-+
-+ buf.begin = buf.data = data;
-+ buf.end = &buf.begin[len];
-+
-+ reason = WSM_GET32(&buf);
-+ for (i = 0; i < ARRAY_SIZE(reg); ++i)
-+ reg[i] = WSM_GET32(&buf);
-+ WSM_GET(&buf, fname, sizeof(fname));
-+
-+ if (reason < 4) {
-+ dev_err(hw_priv->pdev, "Firmware exception: %s.\n",
-+ reason_str[reason]);
-+ } else {
-+ dev_err(hw_priv->pdev, "Firmware assert at %.*s, line %d, reason=0x%x\n",
-+ sizeof(fname), fname, reg[1], reg[2]);
-+ }
-+
-+ for (i = 0; i < 12; i += 4) {
-+ dev_err(hw_priv->pdev, "Firmware:" \
-+ "R%d: 0x%.8X, R%d: 0x%.8X, R%d: 0x%.8X, R%d: 0x%.8X,\n",
-+ i + 0, reg[i + 0], i + 1, reg[i + 1],
-+ i + 2, reg[i + 2], i + 3, reg[i + 3]);
-+ }
-+ dev_err(hw_priv->pdev, "Firmware:" \
-+ "R12: 0x%.8X, SP: 0x%.8X, LR: 0x%.8X, PC: 0x%.8X,\n",
-+ reg[i + 0], reg[i + 1], reg[i + 2], reg[i + 3]);
-+ i += 4;
-+ dev_err(hw_priv->pdev, "Firmware:CPSR: 0x%.8X, SPSR: 0x%.8X\n",
-+ reg[i + 0], reg[i + 1]);
-+
-+ return 0;
-+
-+underflow:
-+ dev_err(hw_priv->pdev, "Firmware exception.\n");
-+ print_hex_dump_bytes("Exception: ", DUMP_PREFIX_NONE, data, len);
-+ return -EINVAL;
-+}
-+
-+static int wsm_debug_indication(struct xradio_common *hw_priv,
-+ struct wsm_buf *buf)
-+{
-+ //for only one debug item.
-+ u32 dbg_id, buf_data=0;
-+ u16 dbg_buf_len;
-+ u8 dbg_len;
-+ u8 *dbg_buf;
-+ dbg_id = WSM_GET32(buf);
-+
-+ dbg_buf_len = buf->end - buf->data;
-+
-+ if (dbg_id == 5) {
-+ do {
-+ dbg_buf_len = buf->end - buf->data;
-+ dbg_len = WSM_GET8(buf);
-+ if (dbg_len > dbg_buf_len - sizeof(dbg_len)) {
-+ wsm_printk(XRADIO_DBG_ERROR, "[FW]dbg_len = %d\n", dbg_len);
-+ wsm_printk(XRADIO_DBG_ERROR, "[FW]dbg_buf_len = %d\n", dbg_buf_len);
-+ wsm_printk(XRADIO_DBG_ERROR, "[FW]debug ind err\n");
-+ //ret = -EINVAL;
-+ //return ret;
-+
-+
-+ break;
-+ }
-+
-+ dbg_buf = buf->data;
-+ //print it;
-+ wsm_printk(XRADIO_DBG_ALWY, "[FW-LOG] %s", dbg_buf);
-+ //
-+ buf->data += dbg_len;
-+
-+ } while (buf->data < buf->end);
-+ } else {
-+ if (dbg_buf_len >= 4) {
-+ buf_data = WSM_GET32(buf);
-+ wsm_printk(XRADIO_DBG_ALWY, "[FW-DEBUG] DbgId = %d, data = %d", dbg_id, buf_data);
-+ } else {
-+ wsm_printk(XRADIO_DBG_ALWY, "[FW-DEBUG] DbgId = %d", dbg_id);
-+ }
-+ }
-+
-+ return 0;
-+
-+underflow:
-+ WARN_ON(1);
-+ return -EINVAL;
-+}
-+
-+int wsm_handle_rx(struct xradio_common *hw_priv, int id,
-+ struct wsm_hdr *wsm, struct sk_buff **skb_p)
-+{
-+ int ret = 0;
-+ struct wsm_buf wsm_buf;
-+ /* struct xradio_vif *priv = NULL; MRK: unused variable, see if 0 below */
-+ /* int i = 0; MRK: unused variable, see if 0 below */
-+ int interface_link_id = (id >> 6) & 0x0F;
-+#ifdef ROAM_OFFLOAD
-+#if 0
-+ struct xradio_vif *priv;
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
-+ if (unlikely(!priv)) {
-+ WARN_ON(1);
-+ return 0;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+#endif
-+#endif/*ROAM_OFFLOAD*/
-+
-+ /* Strip link id. */
-+ id &= ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX);
-+
-+ wsm_buf.begin = (u8 *)&wsm[0];
-+ wsm_buf.data = (u8 *)&wsm[1];
-+ wsm_buf.end = &wsm_buf.begin[__le32_to_cpu(wsm->len)];
-+
-+ wsm_printk(XRADIO_DBG_MSG, "<<< 0x%.4X (%d)\n", id,
-+ wsm_buf.end - wsm_buf.begin);
-+
-+#if defined(DGB_XRADIO_HWT)
-+/***************************for HWT ********************************/
-+ if (id == 0x0424) {
-+ u16 TestID = *(u16 *)(wsm_buf.data);
-+ if (TestID == 1) //test frame confirm.
-+ wsm_hwt_tx_confirm(hw_priv, &wsm_buf);
-+ else {
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ hw_priv->wsm_cmd.ret = *((u16 *)(wsm_buf.data) + 1);
-+ hw_priv->wsm_cmd.done = 1;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ wake_up(&hw_priv->wsm_cmd_wq);
-+ wsm_printk(XRADIO_DBG_ALWY, "HWT TestID=0x%x Confirm ret=%d\n",
-+ *(u16 *)(wsm_buf.data), hw_priv->wsm_cmd.ret);
-+ }
-+ return 0;
-+ } else if (id == 0x0824) {
-+ u16 TestID = *(u16 *)(wsm_buf.data);
-+ switch (TestID) {
-+ case 2: //recieve a test frame.
-+ wsm_hwt_rx_frames(hw_priv, &wsm_buf);
-+ break;
-+ case 3: //enc test result.
-+ wsm_hwt_enc_results(hw_priv, &wsm_buf);
-+ break;
-+ case 4: //mic test result.
-+ wsm_hwt_mic_results(hw_priv, &wsm_buf);
-+ break;
-+ default:
-+ wsm_printk(XRADIO_DBG_ERROR, "HWT ERROR Indication TestID=0x%x\n", TestID);
-+ break;
-+ }
-+ return 0;
-+ }
-+/***************************for HWT ********************************/
-+#endif //DGB_XRADIO_HWT
-+
-+ if (id == 0x404) {
-+ ret = wsm_tx_confirm(hw_priv, &wsm_buf, interface_link_id);
-+#ifdef MCAST_FWDING
-+#if 1
-+ } else if (id == 0x422) {
-+ ret = wsm_give_buffer_confirm(hw_priv, &wsm_buf);
-+#endif
-+#endif
-+
-+ } else if (id == 0x41E) {
-+ ret = wsm_multi_tx_confirm(hw_priv, &wsm_buf,
-+ interface_link_id);
-+ } else if (id & 0x0400) {
-+ void *wsm_arg;
-+ u16 wsm_cmd;
-+
-+ /* Do not trust FW too much. Protection against repeated
-+ * response and race condition removal (see above). */
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ wsm_arg = hw_priv->wsm_cmd.arg;
-+ wsm_cmd = hw_priv->wsm_cmd.cmd &
-+ ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX);
-+ hw_priv->wsm_cmd.cmd = 0xFFFF;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+
-+ if (WARN_ON((id & ~0x0400) != wsm_cmd)) {
-+ /* Note that any non-zero is a fatal retcode. */
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ switch (id) {
-+ case 0x0409:
-+ /* Note that wsm_arg can be NULL in case of timeout in
-+ * wsm_cmd_send(). */
-+ if (likely(wsm_arg))
-+ ret = wsm_configuration_confirm(hw_priv,
-+ wsm_arg,
-+ &wsm_buf);
-+ break;
-+ case 0x0405:
-+ if (likely(wsm_arg))
-+ ret = wsm_read_mib_confirm(hw_priv, wsm_arg,
-+ &wsm_buf);
-+ break;
-+ case 0x0406:
-+ if (likely(wsm_arg))
-+ ret = wsm_write_mib_confirm(hw_priv, wsm_arg,
-+ &wsm_buf,
-+ interface_link_id);
-+ break;
-+ case 0x040B:
-+ if (likely(wsm_arg))
-+ ret = wsm_join_confirm(hw_priv, wsm_arg, &wsm_buf);
-+ if (ret)
-+ wsm_printk(XRADIO_DBG_WARN, "Join confirm Failed!\n");
-+ break;
-+ case 0x040E: /* 11K measure*/
-+ if (likely(wsm_arg))
-+ ret = wsm_generic_confirm(hw_priv, wsm_arg, &wsm_buf);
-+ if (ret)
-+ wsm_printk(XRADIO_DBG_ERROR, "[***HL***]11K Confirm Error\n");
-+
-+ break;
-+
-+#ifdef MCAST_FWDING
-+ case 0x0423: /* req buffer cfm*/
-+ if (likely(wsm_arg)){
-+ xradio_for_each_vif(hw_priv, priv, i) {
-+ if (priv && (priv->join_status == XRADIO_JOIN_STATUS_AP))
-+ ret = wsm_request_buffer_confirm(priv,
-+ wsm_arg, &wsm_buf);
-+ }
-+ }
-+ break;
-+#endif
-+ case 0x0407: /* start-scan */
-+#ifdef ROAM_OFFLOAD
-+ if (hw_priv->auto_scanning) {
-+ if (atomic_read(&hw_priv->scan.in_progress)) {
-+ hw_priv->auto_scanning = 0;
-+ }
-+ else {
-+ wsm_oper_unlock(hw_priv);
-+ up(&hw_priv->scan.lock);
-+ }
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+ case 0x0408: /* stop-scan */
-+ case 0x040A: /* wsm_reset */
-+ case 0x040C: /* add_key */
-+ case 0x040D: /* remove_key */
-+ case 0x0410: /* wsm_set_pm */
-+ case 0x0411: /* set_bss_params */
-+ case 0x0412: /* set_tx_queue_params */
-+ case 0x0413: /* set_edca_params */
-+ case 0x0416: /* switch_channel */
-+ case 0x0417: /* start */
-+ case 0x0418: /* beacon_transmit */
-+ case 0x0419: /* start_find */
-+ case 0x041A: /* stop_find */
-+ case 0x041B: /* update_ie */
-+ case 0x041C: /* map_link */
-+ WARN_ON(wsm_arg != NULL);
-+ ret = wsm_generic_confirm(hw_priv, wsm_arg, &wsm_buf);
-+ if (ret)
-+ wsm_printk(XRADIO_DBG_ERROR,
-+ "wsm_generic_confirm "
-+ "failed for request 0x%.4X.\n",
-+ id & ~0x0400);
-+ break;
-+ default:
-+ BUG_ON(1);
-+ }
-+
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ hw_priv->wsm_cmd.ret = ret;
-+ hw_priv->wsm_cmd.done = 1;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ ret = 0; /* Error response from device should ne stop BH. */
-+
-+ wake_up(&hw_priv->wsm_cmd_wq);
-+ } else if (id & 0x0800) {
-+ switch (id) {
-+ case 0x0801:
-+ ret = wsm_startup_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x0804:
-+ ret = wsm_receive_indication(hw_priv, interface_link_id,
-+ &wsm_buf, skb_p);
-+ break;
-+ case 0x0805:
-+ ret = wsm_event_indication(hw_priv, &wsm_buf,
-+ interface_link_id);
-+ break;
-+ case 0x0807:
-+ wsm_printk(XRADIO_DBG_ERROR, "[11K]wsm_measure_cmpl_indication\n");
-+// wsm_printk(XRADIO_DBG_ERROR, "[11K]wsm->len = %d\n",wsm->len);
-+
-+ ret = wsm_measure_cmpl_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x080A:
-+ ret = wsm_channel_switch_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x0809:
-+ ret = wsm_set_pm_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x0806:
-+#ifdef ROAM_OFFLOAD
-+ if(hw_priv->auto_scanning && hw_priv->frame_rcvd) {
-+ struct xradio_vif *priv;
-+ hw_priv->frame_rcvd = 0;
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
-+ if (unlikely(!priv)) {
-+ WARN_ON(1);
-+ return 0;
-+ }
-+ spin_unlock(&priv->vif_lock);
-+ if (hw_priv->beacon) {
-+ struct wsm_scan_complete *scan_cmpl = \
-+ (struct wsm_scan_complete *) \
-+ ((u8 *)wsm + sizeof(struct wsm_hdr));
-+ struct ieee80211_rx_status *rhdr = \
-+ IEEE80211_SKB_RXCB(hw_priv->beacon);
-+ rhdr->signal = (s8)scan_cmpl->reserved;
-+ if (!priv->cqm_use_rssi) {
-+ rhdr->signal = rhdr->signal / 2 - 110;
-+ }
-+ if (!hw_priv->beacon_bkp)
-+ hw_priv->beacon_bkp = \
-+ skb_copy(hw_priv->beacon, GFP_ATOMIC);
-+ ieee80211_rx_irqsafe(hw_priv->hw, hw_priv->beacon);
-+ hw_priv->beacon = hw_priv->beacon_bkp;
-+
-+ hw_priv->beacon_bkp = NULL;
-+ }
-+ wsm_printk(XRADIO_DBG_MSG, \
-+ "Send Testmode Event.\n");
-+ xradio_testmode_event(priv->hw->wiphy,
-+ NL80211_CMD_NEW_SCAN_RESULTS, 0,
-+ 0, GFP_KERNEL);
-+
-+ }
-+#endif /*ROAM_OFFLOAD*/
-+ ret = wsm_scan_complete_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x080B:
-+ ret = wsm_find_complete_indication(hw_priv, &wsm_buf);
-+ break;
-+ case 0x080C:
-+ ret = wsm_suspend_resume_indication(hw_priv,
-+ interface_link_id, &wsm_buf);
-+ break;
-+ case 0x080E:
-+ wsm_printk(XRADIO_DBG_MSG, "wsm_debug_indication");
-+ ret = wsm_debug_indication(hw_priv, &wsm_buf);
-+ break;
-+
-+ default:
-+ wsm_printk(XRADIO_DBG_ERROR, "unknown Indmsg ID=0x%04x,len=%d\n",
-+ wsm->id, wsm->len);
-+ break;
-+ }
-+ } else {
-+ WARN_ON(1);
-+ ret = -EINVAL;
-+ }
-+out:
-+ return ret;
-+}
-+
-+static bool wsm_handle_tx_data(struct xradio_vif *priv,
-+ const struct wsm_tx *wsm,
-+ const struct ieee80211_tx_info *tx_info,
-+ struct xradio_txpriv *txpriv,
-+ struct xradio_queue *queue)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ bool handled = false;
-+ const struct ieee80211_hdr *frame =
-+ (struct ieee80211_hdr *) &((u8 *)wsm)[txpriv->offset];
-+ __le16 fctl = frame->frame_control;
-+ enum {
-+ doProbe,
-+ doDrop,
-+ doJoin,
-+ doOffchannel,
-+ doWep,
-+ doTx,
-+ } action = doTx;
-+
-+ hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ frame = (struct ieee80211_hdr *) &((u8 *)wsm)[txpriv->offset];
-+ fctl = frame->frame_control;
-+
-+ switch (priv->mode) {
-+ case NL80211_IFTYPE_STATION:
-+ if (unlikely(priv->bss_loss_status == XRADIO_BSS_LOSS_CHECKING &&
-+ priv->join_status == XRADIO_JOIN_STATUS_STA) &&
-+ ieee80211_is_data(fctl)) {
-+ spin_lock(&priv->bss_loss_lock);
-+ priv->bss_loss_confirm_id = wsm->packetID;
-+ priv->bss_loss_status = XRADIO_BSS_LOSS_CONFIRMING;
-+ spin_unlock(&priv->bss_loss_lock);
-+ } else if (unlikely((priv->join_status <= XRADIO_JOIN_STATUS_MONITOR) ||
-+ memcmp(frame->addr1, priv->join_bssid,sizeof(priv->join_bssid)))) {
-+ if (ieee80211_is_auth(fctl))
-+ action = doJoin;
-+ else if ((ieee80211_is_deauth(fctl) || ieee80211_is_disassoc(fctl))&&
-+ priv->join_status < XRADIO_JOIN_STATUS_MONITOR)
-+ action = doDrop; //no need to send deauth when STA-unjoined, yangfh 2014-10-31 16:32:16.
-+ else if (ieee80211_is_probe_req(fctl))
-+ action = doTx;
-+ else if (memcmp(frame->addr1, priv->join_bssid,
-+ sizeof(priv->join_bssid)) &&
-+ (priv->join_status ==
-+ XRADIO_JOIN_STATUS_STA) &&
-+ (ieee80211_is_data(fctl))) {
-+ action = doDrop;
-+ }
-+ else if (priv->join_status >=
-+ XRADIO_JOIN_STATUS_MONITOR)
-+ action = doTx;
-+ else if (get_interface_id_scanning(hw_priv) != -1) {
-+ wsm_printk(XRADIO_DBG_WARN, "Scan ONGOING dropping"
-+ " offchannel eligible frame.\n");
-+ action = doDrop;
-+ } else {
-+ if (ieee80211_is_probe_resp(fctl))
-+ action = doDrop;
-+ else
-+ action = doOffchannel;
-+ wsm_printk(XRADIO_DBG_WARN, "Offchannel fctl=0x%04x", fctl);
-+ }
-+ }
-+ break;
-+ case NL80211_IFTYPE_AP:
-+ if (unlikely(!priv->join_status))
-+ action = doDrop;
-+ else if (unlikely(!(BIT(txpriv->raw_link_id) &
-+ (BIT(0) | priv->link_id_map)))) {
-+ wsm_printk(XRADIO_DBG_WARN,
-+ "A frame with expired link id "
-+ "is dropped.\n");
-+ action = doDrop;
-+ }
-+ if (xradio_queue_get_generation(wsm->packetID) >
-+ XRADIO_MAX_REQUEUE_ATTEMPTS) {
-+ /* HACK!!! WSM324 firmware has tendency to requeue
-+ * multicast frames in a loop, causing performance
-+ * drop and high power consumption of the driver.
-+ * In this situation it is better just to drop
-+ * the problematic frame. */
-+ wsm_printk(XRADIO_DBG_WARN,
-+ "Too many attempts "
-+ "to requeue a frame. "
-+ "Frame is dropped, fctl=0x%04x.\n", fctl);
-+ action = doDrop;
-+ }
-+ break;
-+ case NL80211_IFTYPE_ADHOC:
-+ case NL80211_IFTYPE_MESH_POINT:
-+ //STUB();
-+ case NL80211_IFTYPE_MONITOR:
-+ default:
-+ action = doDrop;
-+ break;
-+ }
-+
-+ if (action == doTx) {
-+ if (unlikely(ieee80211_is_probe_req(fctl))) {
-+ action = doProbe;
-+ } else if ((fctl & __cpu_to_le32(IEEE80211_FCTL_PROTECTED)) &&
-+ tx_info->control.hw_key &&
-+ unlikely(tx_info->control.hw_key->keyidx !=
-+ priv->wep_default_key_id) &&
-+ (tx_info->control.hw_key->cipher ==
-+ WLAN_CIPHER_SUITE_WEP40 ||
-+ tx_info->control.hw_key->cipher ==
-+ WLAN_CIPHER_SUITE_WEP104)) {
-+ action = doWep;
-+ }
-+ }
-+
-+ switch (action) {
-+ case doProbe:
-+ {
-+ /* An interesting FW "feature". Device filters
-+ * probe responses.
-+ * The easiest way to get it back is to convert
-+ * probe request into WSM start_scan command. */
-+ wsm_printk(XRADIO_DBG_MSG, \
-+ "Convert probe request to scan.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
-+ queue_delayed_work(hw_priv->workqueue,
-+ &hw_priv->scan.probe_work, 0);
-+ handled = true;
-+ }
-+ break;
-+ case doDrop:
-+ {
-+ /* See detailed description of "join" below.
-+ * We are dropping everything except AUTH in non-joined mode. */
-+ wsm_printk(XRADIO_DBG_MSG, "Drop frame (0x%.4X).\n", fctl);
-+ BUG_ON(xradio_queue_remove(queue,
-+ __le32_to_cpu(wsm->packetID)));
-+ handled = true;
-+ }
-+ break;
-+ case doJoin:
-+ {
-+ /* p2p should disconnect when sta try to join a different channel AP,
-+ * because no good performance in this case.
-+ */
-+ struct xradio_vif *p2p_tmp_vif = __xrwl_hwpriv_to_vifpriv(hw_priv, 1);
-+ if (priv->if_id == 0 && p2p_tmp_vif) {
-+ if (p2p_tmp_vif->join_status >= XRADIO_JOIN_STATUS_STA &&
-+ hw_priv->channel_changed) {
-+ wsm_printk(XRADIO_DBG_WARN, "combo with different channels, p2p disconnect.\n");
-+ wms_send_disassoc_to_self(hw_priv, p2p_tmp_vif);
-+ }
-+ }
-+
-+ /* There is one more interesting "feature"
-+ * in FW: it can't do RX/TX before "join".
-+ * "Join" here is not an association,
-+ * but just a syncronization between AP and STA.
-+ * priv->join_status is used only in bh thread and does
-+ * not require protection */
-+ wsm_printk(XRADIO_DBG_NIY, "Issue join command.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
-+ if (queue_work(hw_priv->workqueue, &priv->join_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ handled = true;
-+ }
-+ break;
-+ case doOffchannel:
-+ {
-+ wsm_printk(XRADIO_DBG_MSG, "Offchannel TX request.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
-+ if (queue_work(hw_priv->workqueue, &priv->offchannel_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ handled = true;
-+ }
-+ break;
-+ case doWep:
-+ {
-+ wsm_printk(XRADIO_DBG_MSG, "Issue set_default_wep_key.\n");
-+ wsm_lock_tx_async(hw_priv);
-+ priv->wep_default_key_id = tx_info->control.hw_key->keyidx;
-+ hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
-+ if (queue_work(hw_priv->workqueue, &priv->wep_key_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ handled = true;
-+ }
-+ break;
-+ case doTx:
-+ {
-+#if 0
-+ /* Kept for history. If you want to implement wsm->more,
-+ * make sure you are able to send a frame after that. */
-+ wsm->more = (count > 1) ? 1 : 0;
-+ if (wsm->more) {
-+ /* HACK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-+ * It's undocumented in WSM spec, but XRADIO hangs
-+ * if 'more' is set and no TX is performed due to TX
-+ * buffers limitation. */
-+ if (priv->hw_bufs_used + 1 ==
-+ priv->wsm_caps.numInpChBufs)
-+ wsm->more = 0;
-+ }
-+
-+ /* BUG!!! FIXME: we can't use 'more' at all: we don't know
-+ * future. It could be a request from upper layer with TX lock
-+ * requirements (scan, for example). If "more" is set device
-+ * will not send data and wsm_tx_lock() will fail...
-+ * It's not obvious how to fix this deadlock. Any ideas?
-+ * As a workaround more is set to 0. */
-+ wsm->more = 0;
-+#endif /* 0 */
-+
-+ if (ieee80211_is_deauth(fctl) &&
-+ priv->mode != NL80211_IFTYPE_AP) {
-+ /* Shedule unjoin work */
-+ wsm_printk(XRADIO_DBG_WARN, "Issue unjoin command(TX).\n");
-+#if 0
-+ wsm->more = 0;
-+#endif /* 0 */
-+ wsm_lock_tx_async(hw_priv);
-+ if (queue_work(hw_priv->workqueue, &priv->unjoin_work) <= 0)
-+ wsm_unlock_tx(hw_priv);
-+ }
-+ }
-+ break;
-+ }
-+ return handled;
-+}
-+
-+static int xradio_get_prio_queue(struct xradio_vif *priv,
-+ u32 link_id_map, int *total)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ static u32 urgent;
-+ struct wsm_edca_queue_params *edca;
-+ unsigned score, best = -1;
-+ int winner = -1;
-+ int queued;
-+ int i;
-+ urgent = BIT(priv->link_id_after_dtim) | BIT(priv->link_id_uapsd);
-+
-+ /* search for a winner using edca params */
-+ for (i = 0; i < 4; ++i) {
-+ queued = xradio_queue_get_num_queued(priv,
-+ &hw_priv->tx_queue[i],
-+ link_id_map);
-+ if (!queued)
-+ continue;
-+ *total += queued;
-+ edca = &priv->edca.params[i];
-+ score = ((edca->aifns + edca->cwMin) << 16) +
-+ (edca->cwMax - edca->cwMin) *
-+ (prandom_u32() & 0xFFFF);
-+ if (score < best && (winner < 0 || i != 3)) {
-+ best = score;
-+ winner = i;
-+ }
-+ }
-+
-+ /* override winner if bursting */
-+ if (winner >= 0 && hw_priv->tx_burst_idx >= 0 &&
-+ winner != hw_priv->tx_burst_idx &&
-+ !xradio_queue_get_num_queued(priv,
-+ &hw_priv->tx_queue[winner],
-+ link_id_map & urgent) &&
-+ xradio_queue_get_num_queued(priv,
-+ &hw_priv->tx_queue[hw_priv->tx_burst_idx],
-+ link_id_map))
-+ winner = hw_priv->tx_burst_idx;
-+
-+ return winner;
-+}
-+
-+static int wsm_get_tx_queue_and_mask(struct xradio_vif *priv,
-+ struct xradio_queue **queue_p,
-+ u32 *tx_allowed_mask_p,
-+ bool *more)
-+{
-+ struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
-+ int idx;
-+ u32 tx_allowed_mask;
-+ int total = 0;
-+
-+ /* Search for a queue with multicast frames buffered */
-+ if (priv->tx_multicast) {
-+ tx_allowed_mask = BIT(priv->link_id_after_dtim);
-+ idx = xradio_get_prio_queue(priv,
-+ tx_allowed_mask, &total);
-+ if (idx >= 0) {
-+ *more = total > 1;
-+ goto found;
-+ }
-+ }
-+
-+ /* Search for unicast traffic */
-+ tx_allowed_mask = ~priv->sta_asleep_mask;
-+ tx_allowed_mask |= BIT(priv->link_id_uapsd);
-+ if (priv->sta_asleep_mask) {
-+ tx_allowed_mask |= priv->pspoll_mask;
-+ tx_allowed_mask &= ~BIT(priv->link_id_after_dtim);
-+ } else {
-+ tx_allowed_mask |= BIT(priv->link_id_after_dtim);
-+ }
-+ idx = xradio_get_prio_queue(priv,
-+ tx_allowed_mask, &total);
-+ if (idx < 0)
-+ return -ENOENT;
-+
-+found:
-+ *queue_p = &hw_priv->tx_queue[idx];
-+ *tx_allowed_mask_p = tx_allowed_mask;
-+ return 0;
-+}
-+
-+int wsm_get_tx(struct xradio_common *hw_priv, u8 **data,
-+ size_t *tx_len, int *burst, int *vif_selected)
-+{
-+ struct wsm_tx *wsm = NULL;
-+ struct ieee80211_tx_info *tx_info;
-+ struct xradio_queue *queue = NULL;
-+ int queue_num;
-+ u32 tx_allowed_mask = 0;
-+ struct xradio_txpriv *txpriv = NULL;
-+ /*
-+ * Count was intended as an input for wsm->more flag.
-+ * During implementation it was found that wsm->more
-+ * is not usable, see details above. It is kept just
-+ * in case you would like to try to implement it again.
-+ */
-+ int count = 0;
-+ int if_pending = 1;
-+
-+ /* More is used only for broadcasts. */
-+ bool more = false;
-+
-+ if (hw_priv->wsm_cmd.ptr) {
-+ ++count;
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ BUG_ON(!hw_priv->wsm_cmd.ptr);
-+ *data = hw_priv->wsm_cmd.ptr;
-+ *tx_len = hw_priv->wsm_cmd.len;
-+ *burst = 1;
-+ *vif_selected = -1;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ } else {
-+ for (;;) {
-+ int ret;
-+ struct xradio_vif *priv;
-+#if 0
-+ int num_pending_vif0, num_pending_vif1;
-+#endif
-+ if (atomic_add_return(0, &hw_priv->tx_lock))
-+ break;
-+ /* Keep one buffer reserved for commands. Note
-+ that, hw_bufs_used has already been incremented
-+ before reaching here. */
-+ if (hw_priv->hw_bufs_used >=
-+ hw_priv->wsm_caps.numInpChBufs)
-+ break;
-+ priv = wsm_get_interface_for_tx(hw_priv);
-+ /* go to next interface ID to select next packet */
-+ hw_priv->if_id_selected ^= 1;
-+
-+ /* There might be no interface before add_interface
-+ * call */
-+ if (!priv) {
-+ if (if_pending) {
-+ if_pending = 0;
-+ continue;
-+ }
-+ break;
-+ }
-+
-+#if 0
-+ if (((priv->if_id == 0) &&
-+ (hw_priv->hw_bufs_used_vif[0] >=
-+ XRWL_FW_VIF0_THROTTLE)) ||
-+ ((priv->if_id == 1) &&
-+ (hw_priv->hw_bufs_used_vif[1] >=
-+ XRWL_FW_VIF1_THROTTLE))) {
-+ spin_unlock(&priv->vif_lock);
-+ if (if_pending) {
-+ if_pending = 0;
-+ continue;
-+ }
-+ break;
-+ }
-+#endif
-+
-+ /* This can be removed probably: xradio_vif will not
-+ * be in hw_priv->vif_list (as returned from
-+ * wsm_get_interface_for_tx) until it's fully
-+ * enabled, so statement above will take case of that*/
-+ if (!atomic_read(&priv->enabled)) {
-+ spin_unlock(&priv->vif_lock);
-+ break;
-+ }
-+
-+ /* TODO:COMBO: Find the next interface for which
-+ * packet needs to be found */
-+ spin_lock_bh(&priv->ps_state_lock);
-+ ret = wsm_get_tx_queue_and_mask(priv, &queue,
-+ &tx_allowed_mask, &more);
-+ queue_num = queue - hw_priv->tx_queue;
-+
-+ if (priv->buffered_multicasts &&
-+ (ret || !more) &&
-+ (priv->tx_multicast ||
-+ !priv->sta_asleep_mask)) {
-+ priv->buffered_multicasts = false;
-+ if (priv->tx_multicast) {
-+ priv->tx_multicast = false;
-+ queue_work(hw_priv->workqueue,
-+ &priv->multicast_stop_work);
-+ }
-+ }
-+
-+ spin_unlock_bh(&priv->ps_state_lock);
-+
-+ if (ret) {
-+ spin_unlock(&priv->vif_lock);
-+ if (if_pending == 1) {
-+ if_pending = 0;
-+ continue;
-+ }
-+ break;
-+ }
-+
-+ if (xradio_queue_get(queue,
-+ priv->if_id,
-+ tx_allowed_mask,
-+ &wsm, &tx_info, &txpriv)) {
-+ spin_unlock(&priv->vif_lock);
-+ if_pending = 0;
-+ continue;
-+ }
-+
-+// #ifdef ROC_DEBUG
-+// {
-+// struct ieee80211_hdr *hdr =
-+// (struct ieee80211_hdr *)
-+// &((u8 *)wsm)[txpriv->offset];
-+//
-+// wsm_printk(XRADIO_DBG_ERROR, "QGET-1 %x, off_id %d,"
-+// " if_id %d\n",
-+// hdr->frame_control,
-+// txpriv->offchannel_if_id,
-+// priv->if_id);
-+// }
-+// #else
-+// {
-+// struct ieee80211_hdr *hdr =
-+// (struct ieee80211_hdr *)
-+// &((u8 *)wsm)[txpriv->offset];
-+//
-+// wsm_printk(XRADIO_DBG_ERROR, "QGET-1 %x, off_id %d,"
-+// " if_id %d\n",
-+// hdr->frame_control,
-+// txpriv->raw_if_id,
-+// priv->if_id);
-+// }
-+// #endif
-+
-+ if (wsm_handle_tx_data(priv, wsm,
-+ tx_info, txpriv, queue)) {
-+ spin_unlock(&priv->vif_lock);
-+ if_pending = 0;
-+ continue; /* Handled by WSM */
-+ }
-+
-+ wsm->hdr.id &= __cpu_to_le16(
-+ ~WSM_TX_IF_ID(WSM_TX_IF_ID_MAX));
-+ if (txpriv->offchannel_if_id)
-+ wsm->hdr.id |= cpu_to_le16(
-+ WSM_TX_IF_ID(txpriv->offchannel_if_id));
-+ else
-+ wsm->hdr.id |= cpu_to_le16(
-+ WSM_TX_IF_ID(priv->if_id));
-+
-+ *vif_selected = priv->if_id;
-+// #ifdef ROC_DEBUG
-+// /* remand the roc debug. */
-+// {
-+// struct ieee80211_hdr *hdr =
-+// (struct ieee80211_hdr *)
-+// &((u8 *)wsm)[txpriv->offset];
-+//
-+// wsm_printk(XRADIO_DBG_ERROR, "QGET-2 %x, off_id %d,"
-+// " if_id %d\n",
-+// hdr->frame_control,
-+// txpriv->offchannel_if_id,
-+// priv->if_id);
-+// }
-+// #else
-+// {
-+// struct ieee80211_hdr *hdr =
-+// (struct ieee80211_hdr *)
-+// &((u8 *)wsm)[txpriv->offset];
-+//
-+// wsm_printk(XRADIO_DBG_ERROR, "QGET-2 %x, off_id %d,"
-+// " if_id %d\n",
-+// hdr->frame_control,
-+// txpriv->raw_if_id,
-+// priv->if_id);
-+// }
-+// #endif
-+
-+ priv->pspoll_mask &= ~BIT(txpriv->raw_link_id);
-+
-+ *data = (u8 *)wsm;
-+ *tx_len = __le16_to_cpu(wsm->hdr.len);
-+
-+ /* allow bursting if txop is set */
-+ if (priv->edca.params[queue_num].txOpLimit)
-+ *burst = min(*burst,
-+ (int)xradio_queue_get_num_queued(priv,
-+ queue, tx_allowed_mask) + 1);
-+ else
-+ *burst = 1;
-+
-+ /* store index of bursting queue */
-+ if (*burst > 1)
-+ hw_priv->tx_burst_idx = queue_num;
-+ else
-+ hw_priv->tx_burst_idx = -1;
-+
-+ if (more) {
-+ struct ieee80211_hdr *hdr =
-+ (struct ieee80211_hdr *)
-+ &((u8 *)wsm)[txpriv->offset];
-+ if(strstr(&priv->ssid[0], "6.1.12")) {
-+ if(hdr->addr1[0] & 0x01 ) {
-+ hdr->frame_control |=
-+ cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-+ }
-+ }
-+ else {
-+ /* more buffered multicast/broadcast frames
-+ * ==> set MoreData flag in IEEE 802.11 header
-+ * to inform PS STAs */
-+ hdr->frame_control |=
-+ cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-+ }
-+ }
-+ wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X (%d) %p %c\n",
-+ 0x0004, *tx_len, *data,
-+ wsm->more ? 'M' : ' ');
-+ ++count;
-+ spin_unlock(&priv->vif_lock);
-+ break;
-+ }
-+ }
-+
-+ return count;
-+}
-+
-+void wsm_txed(struct xradio_common *hw_priv, u8 *data)
-+{
-+ if (data == hw_priv->wsm_cmd.ptr) {
-+ spin_lock(&hw_priv->wsm_cmd.lock);
-+ hw_priv->wsm_cmd.ptr = NULL;
-+ spin_unlock(&hw_priv->wsm_cmd.lock);
-+ }
-+}
-+
-+/* ******************************************************************** */
-+/* WSM buffer */
-+
-+void wsm_buf_init(struct wsm_buf *buf)
-+{
-+ int size = (SDIO_BLOCK_SIZE<<1); //for sdd file big than SDIO_BLOCK_SIZE
-+ BUG_ON(buf->begin);
-+ buf->begin = kmalloc(size, GFP_KERNEL);
-+ buf->end = buf->begin ? &buf->begin[size] : buf->begin;
-+ wsm_buf_reset(buf);
-+}
-+
-+void wsm_buf_deinit(struct wsm_buf *buf)
-+{
-+ if(buf->begin)
-+ kfree(buf->begin);
-+ buf->begin = buf->data = buf->end = NULL;
-+}
-+
-+static void wsm_buf_reset(struct wsm_buf *buf)
-+{
-+ if (buf->begin) {
-+ buf->data = &buf->begin[4];
-+ *(u32 *)buf->begin = 0;
-+ } else
-+ buf->data = buf->begin;
-+}
-+
-+static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size)
-+{
-+ size_t pos = buf->data - buf->begin;
-+ size_t size = pos + extra_size;
-+
-+
-+ if (size & (SDIO_BLOCK_SIZE - 1)) {
-+ size &= SDIO_BLOCK_SIZE;
-+ size += SDIO_BLOCK_SIZE;
-+ }
-+
-+ buf->begin = krealloc(buf->begin, size, GFP_KERNEL);
-+ if (buf->begin) {
-+ buf->data = &buf->begin[pos];
-+ buf->end = &buf->begin[size];
-+ return 0;
-+ } else {
-+ buf->end = buf->data = buf->begin;
-+ return -ENOMEM;
-+ }
-+}
-+
-+static struct xradio_vif
-+ *wsm_get_interface_for_tx(struct xradio_common *hw_priv)
-+{
-+ struct xradio_vif *priv = NULL, *i_priv;
-+ int i = hw_priv->if_id_selected;
-+
-+ if ( 1 /*TODO:COMBO*/) {
-+ spin_lock(&hw_priv->vif_list_lock);
-+ i_priv = hw_priv->vif_list[i] ?
-+ xrwl_get_vif_from_ieee80211(hw_priv->vif_list[i]) : NULL;
-+ if (i_priv) {
-+ priv = i_priv;
-+ spin_lock(&priv->vif_lock);
-+ }
-+ /* TODO:COMBO:
-+ * Find next interface based on TX bitmap announced by the FW
-+ * Find next interface based on load balancing */
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ } else {
-+ priv = xrwl_hwpriv_to_vifpriv(hw_priv, 0);
-+ }
-+
-+ return priv;
-+}
-+
-+static inline int get_interface_id_scanning(struct xradio_common *hw_priv)
-+{
-+ if (hw_priv->scan.req || hw_priv->scan.direct_probe)
-+ return hw_priv->scan.if_id;
-+ else
-+ return -1;
-+}
-diff --git a/drivers/net/wireless/xradio/wsm.h b/drivers/net/wireless/xradio/wsm.h
-new file mode 100644
-index 0000000..8056abc
---- /dev/null
-+++ b/drivers/net/wireless/xradio/wsm.h
-@@ -0,0 +1,2354 @@
-+/*
-+ * wsm interfaces for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_WSM_H_INCLUDED
-+#define XRADIO_WSM_H_INCLUDED
-+
-+#include
-+
-+struct xradio_common;
-+
-+/* Bands */
-+/* Radio band 2.412 -2.484 GHz. */
-+#define WSM_PHY_BAND_2_4G (0)
-+
-+/* Radio band 4.9375-5.8250 GHz. */
-+#define WSM_PHY_BAND_5G (1)
-+
-+/* Transmit rates */
-+/* 1 Mbps ERP-DSSS */
-+#define WSM_TRANSMIT_RATE_1 (0)
-+
-+/* 2 Mbps ERP-DSSS */
-+#define WSM_TRANSMIT_RATE_2 (1)
-+
-+/* 5.5 Mbps ERP-CCK, ERP-PBCC (Not supported) */
-+/* #define WSM_TRANSMIT_RATE_5 (2) */
-+
-+/* 11 Mbps ERP-CCK, ERP-PBCC (Not supported) */
-+/* #define WSM_TRANSMIT_RATE_11 (3) */
-+
-+/* 22 Mbps ERP-PBCC (Not supported) */
-+/* #define WSM_TRANSMIT_RATE_22 (4) */
-+
-+/* 33 Mbps ERP-PBCC (Not supported) */
-+/* #define WSM_TRANSMIT_RATE_33 (5) */
-+
-+/* 6 Mbps (3 Mbps) ERP-OFDM, BPSK coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_6 (6)
-+
-+/* 9 Mbps (4.5 Mbps) ERP-OFDM, BPSK coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_9 (7)
-+
-+/* 12 Mbps (6 Mbps) ERP-OFDM, QPSK coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_12 (8)
-+
-+/* 18 Mbps (9 Mbps) ERP-OFDM, QPSK coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_18 (9)
-+
-+/* 24 Mbps (12 Mbps) ERP-OFDM, 16QAM coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_24 (10)
-+
-+/* 36 Mbps (18 Mbps) ERP-OFDM, 16QAM coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_36 (11)
-+
-+/* 48 Mbps (24 Mbps) ERP-OFDM, 64QAM coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_48 (12)
-+
-+/* 54 Mbps (27 Mbps) ERP-OFDM, 64QAM coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_54 (13)
-+
-+/* 6.5 Mbps HT-OFDM, BPSK coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_HT_6 (14)
-+
-+/* 13 Mbps HT-OFDM, QPSK coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_HT_13 (15)
-+
-+/* 19.5 Mbps HT-OFDM, QPSK coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_HT_19 (16)
-+
-+/* 26 Mbps HT-OFDM, 16QAM coding rate 1/2 */
-+#define WSM_TRANSMIT_RATE_HT_26 (17)
-+
-+/* 39 Mbps HT-OFDM, 16QAM coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_HT_39 (18)
-+
-+/* 52 Mbps HT-OFDM, 64QAM coding rate 2/3 */
-+#define WSM_TRANSMIT_RATE_HT_52 (19)
-+
-+/* 58.5 Mbps HT-OFDM, 64QAM coding rate 3/4 */
-+#define WSM_TRANSMIT_RATE_HT_58 (20)
-+
-+/* 65 Mbps HT-OFDM, 64QAM coding rate 5/6 */
-+#define WSM_TRANSMIT_RATE_HT_65 (21)
-+
-+/* Scan types */
-+/* Foreground scan */
-+#define WSM_SCAN_TYPE_FOREGROUND (0)
-+
-+/* Background scan */
-+#define WSM_SCAN_TYPE_BACKGROUND (1)
-+
-+/* Auto scan */
-+#define WSM_SCAN_TYPE_AUTO (2)
-+
-+/* Scan flags */
-+/* Forced background scan means if the station cannot */
-+/* enter the power-save mode, it shall force to perform a */
-+/* background scan. Only valid when ScanType is */
-+/* background scan. */
-+#define WSM_SCAN_FLAG_FORCE_BACKGROUND (BIT(0))
-+
-+/* The WLAN device scans one channel at a time so */
-+/* that disturbance to the data traffic is minimized. */
-+#define WSM_SCAN_FLAG_SPLIT_METHOD (BIT(1))
-+
-+/* Preamble Type. Long if not set. */
-+#define WSM_SCAN_FLAG_SHORT_PREAMBLE (BIT(2))
-+
-+/* 11n Tx Mode. Mixed if not set. */
-+#define WSM_SCAN_FLAG_11N_GREENFIELD (BIT(3))
-+
-+#define WSM_FLAG_MAC_INSTANCE_1 (BIT(4))
-+
-+#define WSM_FLAG_MAC_INSTANCE_0 (~(BIT(4)))
-+
-+/* Scan constraints */
-+/* Maximum number of channels to be scanned. */
-+#define WSM_SCAN_MAX_NUM_OF_CHANNELS (48)
-+
-+/* The maximum number of SSIDs that the device can scan for. */
-+#define WSM_SCAN_MAX_NUM_OF_SSIDS (2)
-+
-+/* Power management modes */
-+/* 802.11 Active mode */
-+#define WSM_PSM_ACTIVE (0)
-+
-+/* 802.11 PS mode */
-+#define WSM_PSM_PS BIT(0)
-+
-+/* Fast Power Save bit */
-+#define WSM_PSM_FAST_PS_FLAG BIT(7)
-+
-+/* Dynamic aka Fast power save */
-+#define WSM_PSM_FAST_PS (BIT(0) | BIT(7))
-+
-+/* Undetermined */
-+/* Note : Undetermined status is reported when the */
-+/* NULL data frame used to advertise the PM mode to */
-+/* the AP at Pre or Post Background Scan is not Acknowledged */
-+#define WSM_PSM_UNKNOWN BIT(1)
-+
-+/* Queue IDs */
-+/* best effort/legacy */
-+#define WSM_QUEUE_BEST_EFFORT (0)
-+
-+/* background */
-+#define WSM_QUEUE_BACKGROUND (1)
-+
-+/* video */
-+#define WSM_QUEUE_VIDEO (2)
-+
-+/* voice */
-+#define WSM_QUEUE_VOICE (3)
-+
-+/* HT TX parameters */
-+/* Non-HT */
-+#define WSM_HT_TX_NON_HT (0)
-+
-+/* Mixed format */
-+#define WSM_HT_TX_MIXED (1)
-+
-+/* Greenfield format */
-+#define WSM_HT_TX_GREENFIELD (2)
-+
-+/* STBC allowed */
-+#define WSM_HT_TX_STBC (BIT(7))
-+
-+/* EPTA prioirty flags for BT Coex */
-+/* default epta priority */
-+#define WSM_EPTA_PRIORITY_DEFAULT 4
-+/* use for normal data */
-+#define WSM_EPTA_PRIORITY_DATA 4
-+/* use for connect/disconnect/roaming*/
-+#define WSM_EPTA_PRIORITY_MGT 5
-+/* use for action frames */
-+#define WSM_EPTA_PRIORITY_ACTION 5
-+/* use for AC_VI data */
-+#define WSM_EPTA_PRIORITY_VIDEO 5
-+/* use for AC_VO data */
-+#define WSM_EPTA_PRIORITY_VOICE 6
-+/* use for EAPOL exchange */
-+#define WSM_EPTA_PRIORITY_EAPOL 7
-+
-+/* TX status */
-+/* Frame was sent aggregated */
-+/* Only valid for WSM_SUCCESS status. */
-+#define WSM_TX_STATUS_AGGREGATION (BIT(0))
-+
-+/* Host should requeue this frame later. */
-+/* Valid only when status is WSM_REQUEUE. */
-+#define WSM_TX_STATUS_REQUEUE (BIT(1))
-+
-+/* Normal Ack */
-+#define WSM_TX_STATUS_NORMAL_ACK (0<<2)
-+
-+/* No Ack */
-+#define WSM_TX_STATUS_NO_ACK (1<<2)
-+
-+/* No explicit acknowledgement */
-+#define WSM_TX_STATUS_NO_EXPLICIT_ACK (2<<2)
-+
-+/* Block Ack */
-+/* Only valid for WSM_SUCCESS status. */
-+#define WSM_TX_STATUS_BLOCK_ACK (3<<2)
-+
-+/* RX status */
-+/* Unencrypted */
-+#define WSM_RX_STATUS_UNENCRYPTED (0<<0)
-+
-+/* WEP */
-+#define WSM_RX_STATUS_WEP (1<<0)
-+
-+/* TKIP */
-+#define WSM_RX_STATUS_TKIP (2<<0)
-+
-+/* AES */
-+#define WSM_RX_STATUS_AES (3<<0)
-+
-+/* WAPI */
-+#define WSM_RX_STATUS_WAPI (4<<0)
-+
-+/* Macro to fetch encryption subfield. */
-+#define WSM_RX_STATUS_ENCRYPTION(status) ((status) & 0x07)
-+
-+/* Frame was part of an aggregation */
-+#define WSM_RX_STATUS_AGGREGATE (BIT(3))
-+
-+/* Frame was first in the aggregation */
-+#define WSM_RX_STATUS_AGGREGATE_FIRST (BIT(4))
-+
-+/* Frame was last in the aggregation */
-+#define WSM_RX_STATUS_AGGREGATE_LAST (BIT(5))
-+
-+/* Indicates a defragmented frame */
-+#define WSM_RX_STATUS_DEFRAGMENTED (BIT(6))
-+
-+/* Indicates a Beacon frame */
-+#define WSM_RX_STATUS_BEACON (BIT(7))
-+
-+/* Indicates STA bit beacon TIM field */
-+#define WSM_RX_STATUS_TIM (BIT(8))
-+
-+/* Indicates Beacon frame's virtual bitmap contains multicast bit */
-+#define WSM_RX_STATUS_MULTICAST (BIT(9))
-+
-+/* Indicates frame contains a matching SSID */
-+#define WSM_RX_STATUS_MATCHING_SSID (BIT(10))
-+
-+/* Indicates frame contains a matching BSSI */
-+#define WSM_RX_STATUS_MATCHING_BSSI (BIT(11))
-+
-+/* Indicates More bit set in Framectl field */
-+#define WSM_RX_STATUS_MORE_DATA (BIT(12))
-+
-+/* Indicates frame received during a measurement process */
-+#define WSM_RX_STATUS_MEASUREMENT (BIT(13))
-+
-+/* Indicates frame received as an HT packet */
-+#define WSM_RX_STATUS_HT (BIT(14))
-+
-+/* Indicates frame received with STBC */
-+#define WSM_RX_STATUS_STBC (BIT(15))
-+
-+/* Indicates Address 1 field matches dot11StationId */
-+#define WSM_RX_STATUS_ADDRESS1 (BIT(16))
-+
-+/* Indicates Group address present in the Address 1 field */
-+#define WSM_RX_STATUS_GROUP (BIT(17))
-+
-+/* Indicates Broadcast address present in the Address 1 field */
-+#define WSM_RX_STATUS_BROADCAST (BIT(18))
-+
-+/* Indicates group key used with encrypted frames */
-+#define WSM_RX_STATUS_GROUP_KEY (BIT(19))
-+
-+/* Macro to fetch encryption key index. */
-+#define WSM_RX_STATUS_KEY_IDX(status) (((status >> 20)) & 0x0F)
-+
-+/* Frame Control field starts at Frame offset + 2 */
-+#define WSM_TX_2BYTES_SHIFT (BIT(7))
-+
-+/* Join mode */
-+/* IBSS */
-+#define WSM_JOIN_MODE_IBSS (0)
-+
-+/* BSS */
-+#define WSM_JOIN_MODE_BSS (1)
-+
-+/* PLCP preamble type */
-+/* For long preamble */
-+#define WSM_JOIN_PREAMBLE_LONG (0)
-+
-+/* For short preamble (Long for 1Mbps) */
-+#define WSM_JOIN_PREAMBLE_SHORT (1)
-+
-+/* For short preamble (Long for 1 and 2Mbps) */
-+#define WSM_JOIN_PREAMBLE_SHORT_2 (2)
-+
-+/* Join flags */
-+/* Unsynchronized */
-+#define WSM_JOIN_FLAGS_UNSYNCRONIZED BIT(0)
-+/* The BSS owner is a P2P GO */
-+#define WSM_JOIN_FLAGS_P2P_GO BIT(1)
-+/* Force to join BSS with the BSSID and the
-+ * SSID specified without waiting for beacons. The
-+ * ProbeForJoin parameter is ignored. */
-+#define WSM_JOIN_FLAGS_FORCE BIT(2)
-+/* Give probe request/response higher
-+ * priority over the BT traffic */
-+#define WSM_JOIN_FLAGS_PRIO BIT(3)
-+
-+/* Key types */
-+#define WSM_KEY_TYPE_WEP_DEFAULT (0)
-+#define WSM_KEY_TYPE_WEP_PAIRWISE (1)
-+#define WSM_KEY_TYPE_TKIP_GROUP (2)
-+#define WSM_KEY_TYPE_TKIP_PAIRWISE (3)
-+#define WSM_KEY_TYPE_AES_GROUP (4)
-+#define WSM_KEY_TYPE_AES_PAIRWISE (5)
-+#define WSM_KEY_TYPE_WAPI_GROUP (6)
-+#define WSM_KEY_TYPE_WAPI_PAIRWISE (7)
-+
-+/* Key indexes */
-+#define WSM_KEY_MAX_INDEX (10)
-+
-+/* ACK policy */
-+#define WSM_ACK_POLICY_NORMAL (0)
-+#define WSM_ACK_POLICY_NO_ACK (1)
-+
-+/* Start modes */
-+#define WSM_START_MODE_AP (0) /* Mini AP */
-+#define WSM_START_MODE_P2P_GO (1) /* P2P GO */
-+#define WSM_START_MODE_P2P_DEV (2) /* P2P device */
-+
-+/* SetAssociationMode MIB flags */
-+#define WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE (BIT(0))
-+#define WSM_ASSOCIATION_MODE_USE_HT_MODE (BIT(1))
-+#define WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET (BIT(2))
-+#define WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING (BIT(3))
-+#define WSM_ASSOCIATION_MODE_SNOOP_ASSOC_FRAMES (BIT(4))
-+
-+/* RcpiRssiThreshold MIB flags */
-+#define WSM_RCPI_RSSI_THRESHOLD_ENABLE (BIT(0))
-+#define WSM_RCPI_RSSI_USE_RSSI (BIT(1))
-+#define WSM_RCPI_RSSI_DONT_USE_UPPER (BIT(2))
-+#define WSM_RCPI_RSSI_DONT_USE_LOWER (BIT(3))
-+
-+/* Update-ie constants */
-+#define WSM_UPDATE_IE_BEACON (BIT(0))
-+#define WSM_UPDATE_IE_PROBE_RESP (BIT(1))
-+#define WSM_UPDATE_IE_PROBE_REQ (BIT(2))
-+
-+/* WSM events */
-+/* Error */
-+#define WSM_EVENT_ERROR (0)
-+
-+/* BSS lost */
-+#define WSM_EVENT_BSS_LOST (1)
-+
-+/* BSS regained */
-+#define WSM_EVENT_BSS_REGAINED (2)
-+
-+/* Radar detected */
-+#define WSM_EVENT_RADAR_DETECTED (3)
-+
-+/* RCPI or RSSI threshold triggered */
-+#define WSM_EVENT_RCPI_RSSI (4)
-+
-+/* BT inactive */
-+#define WSM_EVENT_BT_INACTIVE (5)
-+
-+/* BT active */
-+#define WSM_EVENT_BT_ACTIVE (6)
-+
-+#define WSM_EVENT_PS_MODE_ERROR (7)
-+
-+#define WSM_EVENT_INACTIVITY (9)
-+
-+/* MAC Addr Filter */
-+#define WSM_MIB_ID_MAC_ADDR_FILTER 0x1030
-+
-+/* MIB IDs */
-+/* 4.1 dot11StationId */
-+#define WSM_MIB_ID_DOT11_STATION_ID 0x0000
-+
-+/* 4.2 dot11MaxtransmitMsduLifeTime */
-+#define WSM_MIB_ID_DOT11_MAX_TRANSMIT_LIFTIME 0x0001
-+
-+/* 4.3 dot11MaxReceiveLifeTime */
-+#define WSM_MIB_ID_DOT11_MAX_RECEIVE_LIFETIME 0x0002
-+
-+/* 4.4 dot11SlotTime */
-+#define WSM_MIB_ID_DOT11_SLOT_TIME 0x0003
-+
-+/* 4.5 dot11GroupAddressesTable */
-+#define WSM_MIB_ID_DOT11_GROUP_ADDRESSES_TABLE 0x0004
-+#define WSM_MAX_GRP_ADDRTABLE_ENTRIES 8
-+
-+/* 4.6 dot11WepDefaultKeyId */
-+#define WSM_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID 0x0005
-+
-+/* 4.7 dot11CurrentTxPowerLevel */
-+#define WSM_MIB_ID_DOT11_CURRENT_TX_POWER_LEVEL 0x0006
-+
-+/* 4.8 dot11RTSThreshold */
-+#define WSM_MIB_ID_DOT11_RTS_THRESHOLD 0x0007
-+
-+/* Huanglu add for firmware debug control */
-+#define WSM_MIB_ID_FW_DEBUG_CONTROL 0x0008
-+
-+/* yangfh add for read/write registers from firmware*/
-+#define WSM_MIB_ID_RW_FW_REG 0x0009
-+
-+/* yangfh add for Set max number of mpdus in a-mpdu*/
-+#define WSM_MIB_ID_SET_AMPDU_NUM 0x000a
-+
-+/* Huanglu add for tx-ampdu-len-adaption */
-+#define WSM_MIB_ID_SET_TALA_PARA 0x000b
-+
-+/* yangfh add for set TPA param */
-+#define WSM_MIB_ID_SET_TPA_PARAM 0x000c
-+
-+/* 4.9 NonErpProtection */
-+#define WSM_MIB_ID_NON_ERP_PROTECTION 0x1000
-+
-+/* 4.10 ArpIpAddressesTable */
-+#define WSM_MIB_ID_ARP_IP_ADDRESSES_TABLE 0x1001
-+#define WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES 1
-+
-+/* 4.11 TemplateFrame */
-+#define WSM_MIB_ID_TEMPLATE_FRAME 0x1002
-+
-+/* 4.12 RxFilter */
-+#define WSM_MIB_ID_RX_FILTER 0x1003
-+
-+/* 4.13 BeaconFilterTable */
-+#define WSM_MIB_ID_BEACON_FILTER_TABLE 0x1004
-+
-+/* 4.14 BeaconFilterEnable */
-+#define WSM_MIB_ID_BEACON_FILTER_ENABLE 0x1005
-+
-+/* 4.15 OperationalPowerMode */
-+#define WSM_MIB_ID_OPERATIONAL_POWER_MODE 0x1006
-+
-+/* 4.16 BeaconWakeUpPeriod */
-+#define WSM_MIB_ID_BEACON_WAKEUP_PERIOD 0x1007
-+
-+/* 4.17 RcpiRssiThreshold */
-+#define WSM_MIB_ID_RCPI_RSSI_THRESHOLD 0x1009
-+
-+/* 4.18 StatisticsTable */
-+#define WSM_MIB_ID_STATISTICS_TABLE 0x100A
-+
-+/* 4.19 IbssPsConfig */
-+#define WSM_MIB_ID_IBSS_PS_CONFIG 0x100B
-+
-+/* 4.20 CountersTable */
-+#define WSM_MIB_ID_COUNTERS_TABLE 0x100C
-+#define WSM_MIB_ID_AMPDUCOUNTERS_TABLE 0x1036
-+#define WSM_MIB_ID_TXPIPE_TABLE 0x1037
-+#define WSM_MIB_ID_BACKOFF_DBG 0x1038
-+#define WSM_MIB_ID_BACKOFF_CTRL 0x1039
-+
-+//add yangfh for requery packet status
-+#define WSM_MIB_ID_REQ_PKT_STATUS 0x1040
-+
-+//add yangfh for TPA debug informations
-+#define WSM_MIB_ID_TPA_DEBUG_INFO 0x1041
-+
-+//add yangfh for tx power informations
-+#define WSM_MIB_ID_TX_POWER_INFO 0x1042
-+
-+//add yangfh for some hardware information
-+#define WSM_MIB_ID_HW_INFO 0x1043
-+
-+/* 4.21 BlockAckPolicy */
-+#define WSM_MIB_ID_BLOCK_ACK_POLICY 0x100E
-+
-+/* 4.22 OverrideInternalTxRate */
-+#define WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE 0x100F
-+
-+/* 4.23 SetAssociationMode */
-+#define WSM_MIB_ID_SET_ASSOCIATION_MODE 0x1010
-+
-+/* 4.24 UpdateEptaConfigData */
-+#define WSM_MIB_ID_UPDATE_EPTA_CONFIG_DATA 0x1011
-+
-+/* 4.25 SelectCcaMethod */
-+#define WSM_MIB_ID_SELECT_CCA_METHOD 0x1012
-+
-+/* 4.26 SetUpasdInformation */
-+#define WSM_MIB_ID_SET_UAPSD_INFORMATION 0x1013
-+
-+/* 4.27 SetAutoCalibrationMode WBF00004073 */
-+#define WSM_MIB_ID_SET_AUTO_CALIBRATION_MODE 0x1015
-+
-+/* 4.28 SetTxRateRetryPolicy */
-+#define WSM_MIB_ID_SET_TX_RATE_RETRY_POLICY 0x1016
-+
-+/* 4.29 SetHostMessageTypeFilter */
-+#define WSM_MIB_ID_SET_HOST_MSG_TYPE_FILTER 0x1017
-+
-+/* 4.30 P2PFindInfo */
-+#define WSM_MIB_ID_P2P_FIND_INFO 0x1018
-+
-+/* 4.31 P2PPsModeInfo */
-+#define WSM_MIB_ID_P2P_PS_MODE_INFO 0x1019
-+
-+/* 4.32 SetEtherTypeDataFrameFilter */
-+#define WSM_MIB_ID_SET_ETHERTYPE_DATAFRAME_FILTER 0x101A
-+
-+/* 4.33 SetUDPPortDataFrameFilter */
-+#define WSM_MIB_ID_SET_UDPPORT_DATAFRAME_FILTER 0x101B
-+
-+/* 4.34 SetMagicDataFrameFilter */
-+#define WSM_MIB_ID_SET_MAGIC_DATAFRAME_FILTER 0x101C
-+#define WSM_MIB_ID_SET_HOST_SLEEP 0x1050
-+
-+/* This is the end of specification. */
-+
-+/* 4.35 P2PDeviceInfo */
-+#define WSM_MIB_ID_P2P_DEVICE_INFO 0x101D
-+
-+/* 4.36 SetWCDMABand */
-+#define WSM_MIB_ID_SET_WCDMA_BAND 0x101E
-+
-+/* 4.37 GroupTxSequenceCounter */
-+#define WSM_MIB_ID_GRP_SEQ_COUNTER 0x101F
-+
-+/* 4.38 ProtectedMgmtPolicy */
-+#define WSM_MIB_ID_PROTECTED_MGMT_POLICY 0x1020
-+
-+/* 4.39 SetHtProtection */
-+#define WSM_MID_ID_SET_HT_PROTECTION 0x1021
-+
-+/* 4.40 GPIO Command */
-+#define WSM_MIB_ID_GPIO_COMMAND 0x1022
-+
-+/* 4.41 TSF Counter Value */
-+#define WSM_MIB_ID_TSF_COUNTER 0x1023
-+
-+/* Test Purposes Only */
-+#define WSM_MIB_ID_BLOCK_ACK_INFO 0x100D
-+
-+/* 4.42 UseMultiTxConfMessage */
-+#define WSM_MIB_USE_MULTI_TX_CONF 0x1024
-+
-+/* 4.43 Keep-alive period */
-+#define WSM_MIB_ID_KEEP_ALIVE_PERIOD 0x1025
-+
-+/* 4.44 Disable BSSID filter */
-+#define WSM_MIB_ID_DISABLE_BSSID_FILTER 0x1026
-+
-+/* Inactivity */
-+#define WSM_MIB_ID_SET_INACTIVITY 0x1035
-+
-+/* MAC Addr Filter */
-+#define WSM_MIB_ID_MAC_ADDR_FILTER 0x1030
-+
-+#ifdef MCAST_FWDING
-+/* 4.51 Set Forwarding Offload */
-+#define WSM_MIB_ID_FORWARDING_OFFLOAD 0x1033
-+#endif
-+
-+/* Frame template types */
-+#define WSM_FRAME_TYPE_PROBE_REQUEST (0)
-+#define WSM_FRAME_TYPE_BEACON (1)
-+#define WSM_FRAME_TYPE_NULL (2)
-+#define WSM_FRAME_TYPE_QOS_NULL (3)
-+#define WSM_FRAME_TYPE_PS_POLL (4)
-+#define WSM_FRAME_TYPE_PROBE_RESPONSE (5)
-+#define WSM_FRAME_TYPE_ARP_REPLY (6)
-+
-+#define WSM_FRAME_GREENFIELD (0x80) /* See 4.11 */
-+
-+/* Status */
-+/* The WSM firmware has completed a request */
-+/* successfully. */
-+#define WSM_STATUS_SUCCESS (0)
-+
-+/* This is a generic failure code if other error codes do */
-+/* not apply. */
-+#define WSM_STATUS_FAILURE (1)
-+
-+/* A request contains one or more invalid parameters. */
-+#define WSM_INVALID_PARAMETER (2)
-+
-+/* The request cannot perform because the device is in */
-+/* an inappropriate mode. */
-+#define WSM_ACCESS_DENIED (3)
-+
-+/* The frame received includes a decryption error. */
-+#define WSM_STATUS_DECRYPTFAILURE (4)
-+
-+/* A MIC failure is detected in the received packets. */
-+#define WSM_STATUS_MICFAILURE (5)
-+
-+/* The transmit request failed due to retry limit being */
-+/* exceeded. */
-+#define WSM_STATUS_RETRY_EXCEEDED (6)
-+
-+/* The transmit request failed due to MSDU life time */
-+/* being exceeded. */
-+#define WSM_STATUS_TX_LIFETIME_EXCEEDED (7)
-+
-+/* The link to the AP is lost. */
-+#define WSM_STATUS_LINK_LOST (8)
-+
-+/* No key was found for the encrypted frame */
-+#define WSM_STATUS_NO_KEY_FOUND (9)
-+
-+/* Jammer was detected when transmitting this frame */
-+#define WSM_STATUS_JAMMER_DETECTED (10)
-+
-+/* The message should be requeued later. */
-+/* This is applicable only to Transmit */
-+#define WSM_REQUEUE (11)
-+
-+/* Advanced filtering options */
-+#define WSM_MAX_FILTER_ELEMENTS (4)
-+
-+#define WSM_FILTER_ACTION_IGNORE (0)
-+#define WSM_FILTER_ACTION_FILTER_IN (1)
-+#define WSM_FILTER_ACTION_FILTER_OUT (2)
-+
-+#define WSM_FILTER_PORT_TYPE_DST (0)
-+#define WSM_FILTER_PORT_TYPE_SRC (1)
-+
-+
-+
-+struct wsm_hdr {
-+ __le16 len;
-+ __le16 id;
-+};
-+
-+#define WSM_TX_SEQ_MAX (7)
-+#define WSM_TX_SEQ(seq) \
-+ ((seq & WSM_TX_SEQ_MAX) << 13)
-+#define WSM_TX_LINK_ID_MAX (0x0F)
-+#define WSM_TX_LINK_ID(link_id) \
-+ ((link_id & WSM_TX_LINK_ID_MAX) << 6)
-+
-+#define WSM_TX_IF_ID_MAX (0x0F)
-+#define WSM_TX_IF_ID(if_id) \
-+ ((if_id & WSM_TX_IF_ID_MAX) << 6)
-+
-+#define MAX_BEACON_SKIP_TIME_MS 1000
-+
-+#ifdef FPGA_SETUP
-+#define WSM_CMD_LAST_CHANCE_TIMEOUT (HZ * 9 / 2)
-+#else
-+#define WSM_CMD_LAST_CHANCE_TIMEOUT (HZ * 20 / 2)
-+#endif
-+#define WSM_CMD_EXTENDED_TIMEOUT (HZ * 20 / 2)
-+
-+#define WSM_RI_GET_PEER_ID_FROM_FLAGS(_f) (((_f)&(0xF<<25)>>25))
-+
-+
-+/* ******************************************************************** */
-+/* WSM capcbility */
-+#define WSM_FW_LABEL 128
-+struct wsm_caps {
-+ u16 numInpChBufs;
-+ u16 sizeInpChBuf;
-+ u16 hardwareId;
-+ u16 hardwareSubId;
-+ u16 firmwareCap;
-+ u16 firmwareType;
-+ u16 firmwareApiVer;
-+ u16 firmwareBuildNumber;
-+ u16 firmwareVersion;
-+ char fw_label[WSM_FW_LABEL+2];
-+ int firmwareReady;
-+};
-+
-+/* ******************************************************************** */
-+/* WSM commands */
-+
-+struct wsm_tx_power_range {
-+ int min_power_level;
-+ int max_power_level;
-+ u32 stepping;
-+};
-+
-+/* 3.1 */
-+struct wsm_configuration {
-+ /* [in] */ u32 dot11MaxTransmitMsduLifeTime;
-+ /* [in] */ u32 dot11MaxReceiveLifeTime;
-+ /* [in] */ u32 dot11RtsThreshold;
-+ /* [in, out] */ u8 *dot11StationId;
-+ /* [in] */ const void *dpdData;
-+ /* [in] */ size_t dpdData_size;
-+ /* [out] */ u8 dot11FrequencyBandsSupported;
-+ /* [out] */ u32 supportedRateMask;
-+ /* [out] */ struct wsm_tx_power_range txPowerRange[2];
-+};
-+
-+int wsm_configuration(struct xradio_common *hw_priv,
-+ struct wsm_configuration *arg,
-+ int if_id);
-+
-+/* 3.3 */
-+struct wsm_reset {
-+ /* [in] */ int link_id;
-+ /* [in] */ bool reset_statistics;
-+};
-+
-+int wsm_reset(struct xradio_common *hw_priv, const struct wsm_reset *arg,
-+ int if_id);
-+
-+//add by yangfh
-+void wsm_query_work(struct work_struct *work);
-+
-+/* 3.5 */
-+int wsm_read_mib(struct xradio_common *hw_priv, u16 mibId, void *buf,
-+ size_t buf_size, size_t arg_size);
-+
-+/* 3.7 */
-+int wsm_write_mib(struct xradio_common *hw_priv, u16 mibId, void *buf,
-+ size_t buf_size, int if_id);
-+
-+/* 3.9 */
-+struct wsm_ssid {
-+ u8 ssid[32];
-+ u32 length;
-+};
-+
-+struct wsm_scan_ch {
-+ u16 number;
-+ u32 minChannelTime;
-+ u32 maxChannelTime;
-+ u32 txPowerLevel;
-+};
-+
-+/* 3.13 */
-+struct wsm_scan_complete {
-+ /* WSM_STATUS_... */
-+ u32 status;
-+
-+ /* WSM_PSM_... */
-+ u8 psm;
-+
-+ /* Number of channels that the scan operation completed. */
-+ u8 numChannels;
-+#ifdef ROAM_OFFLOAD
-+ u16 reserved;
-+#endif /*ROAM_OFFLOAD*/
-+};
-+
-+/* 3.9 */
-+struct wsm_scan {
-+ /* WSM_PHY_BAND_... */
-+ /* [in] */ u8 band;
-+
-+ /* WSM_SCAN_TYPE_... */
-+ /* [in] */ u8 scanType;
-+
-+ /* WSM_SCAN_FLAG_... */
-+ /* [in] */ u8 scanFlags;
-+
-+ /* WSM_TRANSMIT_RATE_... */
-+ /* [in] */ u8 maxTransmitRate;
-+
-+ /* Interval period in TUs that the device shall the re- */
-+ /* execute the requested scan. Max value supported by the device */
-+ /* is 256s. */
-+ /* [in] */ u32 autoScanInterval;
-+
-+ /* Number of probe requests (per SSID) sent to one (1) */
-+ /* channel. Zero (0) means that none is send, which */
-+ /* means that a passive scan is to be done. Value */
-+ /* greater than zero (0) means that an active scan is to */
-+ /* be done. */
-+ /* [in] */ u32 numOfProbeRequests;
-+
-+ /* Number of channels to be scanned. */
-+ /* Maximum value is WSM_SCAN_MAX_NUM_OF_CHANNELS. */
-+ /* [in] */ u8 numOfChannels;
-+
-+ /* Number of SSID provided in the scan command (this */
-+ /* is zero (0) in broadcast scan) */
-+ /* The maximum number of SSIDs is WSM_SCAN_MAX_NUM_OF_SSIDS. */
-+ /* [in] */ u8 numOfSSIDs;
-+
-+ /* The delay time (in microseconds) period */
-+ /* before sending a probe-request. */
-+ /* [in] */ u8 probeDelay;
-+
-+ /* SSIDs to be scanned [numOfSSIDs]; */
-+ /* [in] */ struct wsm_ssid *ssids;
-+
-+ /* Channels to be scanned [numOfChannels]; */
-+ /* [in] */ struct wsm_scan_ch *ch;
-+};
-+
-+int wsm_scan(struct xradio_common *hw_priv, const struct wsm_scan *arg,
-+ int if_id);
-+
-+/* 3.11 */
-+int wsm_stop_scan(struct xradio_common *hw_priv, int if_id);
-+
-+/* 3.14 */
-+struct wsm_tx_confirm {
-+ /* Packet identifier used in wsm_tx. */
-+ /* [out] */ u32 packetID;
-+
-+ /* WSM_STATUS_... */
-+ /* [out] */ u32 status;
-+
-+ /* WSM_TRANSMIT_RATE_... */
-+ /* [out] */ u8 txedRate;
-+
-+ /* The number of times the frame was transmitted */
-+ /* without receiving an acknowledgement. */
-+ /* [out] */ u8 ackFailures;
-+
-+ /* WSM_TX_STATUS_... */
-+ /* [out] */ u16 flags;
-+
-+ //rate feed back, add by yangfh
-+ /* [out] */ u32 rate_try[3];
-+
-+ /* The total time in microseconds that the frame spent in */
-+ /* the WLAN device before transmission as completed. */
-+ /* [out] */ u32 mediaDelay;
-+
-+ /* The total time in microseconds that the frame spent in */
-+ /* the WLAN device before transmission was started. */
-+ /* [out] */ u32 txQueueDelay;
-+
-+ /* [out]*/ u32 link_id;
-+
-+ /*[out]*/ int if_id;
-+};
-+
-+/* 3.15 */
-+
-+/* Note that ideology of wsm_tx struct is different against the rest of
-+ * WSM API. wsm_hdr is /not/ a caller-adapted struct to be used as an input
-+ * argument for WSM call, but a prepared bytestream to be sent to firmware.
-+ * It is filled partly in xradio_tx, partly in low-level WSM code.
-+ * Please pay attention once again: ideology is different.
-+ *
-+ * Legend:
-+ * - [in]: xradio_tx must fill this field.
-+ * - [wsm]: the field is filled by low-level WSM.
-+ */
-+struct wsm_tx {
-+ /* common WSM header */
-+ /* [in/wsm] */ struct wsm_hdr hdr;
-+
-+ /* Packet identifier that meant to be used in completion. */
-+ /* [in] */ __le32 packetID;
-+
-+ /* WSM_TRANSMIT_RATE_... */
-+ /* [in] */ u8 maxTxRate;
-+
-+ /* WSM_QUEUE_... */
-+ /* [in] */ u8 queueId;
-+
-+ /* True: another packet is pending on the host for transmission. */
-+ /* [wsm] */ u8 more;
-+
-+ /* Bit 0 = 0 - Start expiry time from first Tx attempt (default) */
-+ /* Bit 0 = 1 - Start expiry time from receipt of Tx Request */
-+ /* Bits 3:1 - PTA Priority */
-+ /* Bits 6:4 - Tx Rate Retry Policy */
-+ /* Bit 7 - Reserved */
-+ /* [in] */ u8 flags;
-+
-+ /* Should be 0. */
-+ /* [in] */ __le32 reserved;
-+
-+ /* The elapsed time in TUs, after the initial transmission */
-+ /* of an MSDU, after which further attempts to transmit */
-+ /* the MSDU shall be terminated. Overrides the global */
-+ /* dot11MaxTransmitMsduLifeTime setting [optional] */
-+ /* Device will set the default value if this is 0. */
-+ /* [wsm] */ __le32 expireTime;
-+
-+ /* WSM_HT_TX_... */
-+ /* [in] */ __le32 htTxParameters;
-+};
-+
-+/* = sizeof(generic hi hdr) + sizeof(wsm hdr) + sizeof(alignment) */
-+#define WSM_TX_EXTRA_HEADROOM (28)
-+
-+/* 3.16 */
-+struct wsm_rx {
-+ /* WSM_STATUS_... */
-+ /* [out] */ u32 status;
-+
-+ /* Specifies the channel of the received packet. */
-+ /* [out] */ u16 channelNumber;
-+
-+ /* WSM_TRANSMIT_RATE_... */
-+ /* [out] */ u8 rxedRate;
-+
-+ /* This value is expressed in signed Q8.0 format for */
-+ /* RSSI and unsigned Q7.1 format for RCPI. */
-+ /* [out] */ u8 rcpiRssi;
-+
-+ /* WSM_RX_STATUS_... */
-+ /* [out] */ u32 flags;
-+
-+ /* An 802.11 frame. */
-+ /* [out] */ void *frame;
-+
-+ /* Size of the frame */
-+ /* [out] */ size_t frame_size;
-+
-+ /* Link ID */
-+ /* [out] */ int link_id;
-+ /* [out] */ int if_id;
-+};
-+
-+/* = sizeof(generic hi hdr) + sizeof(wsm hdr) */
-+#define WSM_RX_EXTRA_HEADROOM (16)
-+
-+/* 3.17 */
-+struct wsm_event {
-+ /* WSM_STATUS_... */
-+ /* [out] */ u32 eventId;
-+
-+ /* Indication parameters. */
-+ /* For error indication, this shall be a 32-bit WSM status. */
-+ /* For RCPI or RSSI indication, this should be an 8-bit */
-+ /* RCPI or RSSI value. */
-+ /* [out] */ u32 eventData;
-+};
-+
-+struct xradio_wsm_event {
-+ struct list_head link;
-+ struct wsm_event evt;
-+ u8 if_id;
-+};
-+
-+/* 3.18 - 3.22 */
-+/* Measurement. Skipped for now. Irrelevent. */
-+
-+
-+/* 3.23 */
-+struct wsm_join {
-+ /* WSM_JOIN_MODE_... */
-+ /* [in] */ u8 mode;
-+
-+ /* WSM_PHY_BAND_... */
-+ /* [in] */ u8 band;
-+
-+ /* Specifies the channel number to join. The channel */
-+ /* number will be mapped to an actual frequency */
-+ /* according to the band */
-+ /* [in] */ u16 channelNumber;
-+
-+ /* Specifies the BSSID of the BSS or IBSS to be joined */
-+ /* or the IBSS to be started. */
-+ /* [in] */ u8 bssid[6];
-+
-+ /* ATIM window of IBSS */
-+ /* When ATIM window is zero the initiated IBSS does */
-+ /* not support power saving. */
-+ /* [in] */ u16 atimWindow;
-+
-+ /* WSM_JOIN_PREAMBLE_... */
-+ /* [in] */ u8 preambleType;
-+
-+ /* Specifies if a probe request should be send with the */
-+ /* specified SSID when joining to the network. */
-+ /* [in] */ u8 probeForJoin;
-+
-+ /* DTIM Period (In multiples of beacon interval) */
-+ /* [in] */ u8 dtimPeriod;
-+
-+ /* WSM_JOIN_FLAGS_... */
-+ /* [in] */ u8 flags;
-+
-+ /* Length of the SSID */
-+ /* [in] */ u32 ssidLength;
-+
-+ /* Specifies the SSID of the IBSS to join or start */
-+ /* [in] */ u8 ssid[32];
-+
-+ /* Specifies the time between TBTTs in TUs */
-+ /* [in] */ u32 beaconInterval;
-+
-+ /* A bit mask that defines the BSS basic rate set. */
-+ /* [in] */ u32 basicRateSet;
-+
-+ /* Minimum transmission power level in units of 0.1dBm */
-+ /* [out] */ int minPowerLevel;
-+
-+ /* Maximum transmission power level in units of 0.1dBm */
-+ /* [out] */ int maxPowerLevel;
-+};
-+
-+int wsm_join(struct xradio_common *hw_priv, struct wsm_join *arg, int if_id);
-+
-+/* 3.25 */
-+struct wsm_set_pm {
-+ /* WSM_PSM_... */
-+ /* [in] */ u8 pmMode;
-+
-+ /* in unit of 500us; 0 to use default */
-+ /* [in] */ u8 fastPsmIdlePeriod;
-+
-+ /* in unit of 500us; 0 to use default */
-+ /* [in] */ u8 apPsmChangePeriod;
-+
-+ /* in unit of 500us; 0 to disable auto-pspoll */
-+ /* [in] */ u8 minAutoPsPollPeriod;
-+};
-+
-+int wsm_set_pm(struct xradio_common *hw_priv, const struct wsm_set_pm *arg,
-+ int if_id);
-+
-+/* 3.27 */
-+struct wsm_set_pm_complete {
-+ u8 psm; /* WSM_PSM_... */
-+};
-+
-+/* 3.28 */
-+struct wsm_set_bss_params {
-+ /* The number of lost consecutive beacons after which */
-+ /* the WLAN device should indicate the BSS-Lost event */
-+ /* to the WLAN host driver. */
-+ u8 beaconLostCount;
-+
-+ /* The AID received during the association process. */
-+ u16 aid;
-+
-+ /* The operational rate set mask */
-+ u32 operationalRateSet;
-+};
-+
-+int wsm_set_bss_params(struct xradio_common *hw_priv,
-+ const struct wsm_set_bss_params *arg, int if_id);
-+
-+/* 3.30 */
-+struct wsm_add_key {
-+ u8 type; /* WSM_KEY_TYPE_... */
-+ u8 entryIndex; /* Key entry index: 0 -- WSM_KEY_MAX_INDEX */
-+ u16 reserved;
-+ union {
-+ struct {
-+ u8 peerAddress[6]; /* MAC address of the
-+ * peer station */
-+ u8 reserved;
-+ u8 keyLength; /* Key length in bytes */
-+ u8 keyData[16]; /* Key data */
-+ } __packed wepPairwiseKey;
-+ struct {
-+ u8 keyId; /* Unique per key identifier
-+ * (0..3) */
-+ u8 keyLength; /* Key length in bytes */
-+ u16 reserved;
-+ u8 keyData[16]; /* Key data */
-+ } __packed wepGroupKey;
-+ struct {
-+ u8 peerAddress[6]; /* MAC address of the
-+ * peer station */
-+ u8 reserved[2];
-+ u8 tkipKeyData[16]; /* TKIP key data */
-+ u8 rxMicKey[8]; /* Rx MIC key */
-+ u8 txMicKey[8]; /* Tx MIC key */
-+ } __packed tkipPairwiseKey;
-+ struct {
-+ u8 tkipKeyData[16]; /* TKIP key data */
-+ u8 rxMicKey[8]; /* Rx MIC key */
-+ u8 keyId; /* Key ID */
-+ u8 reserved[3];
-+ u8 rxSeqCounter[8]; /* Receive Sequence Counter */
-+ } __packed tkipGroupKey;
-+ struct {
-+ u8 peerAddress[6]; /* MAC address of the
-+ * peer station */
-+ u16 reserved;
-+ u8 aesKeyData[16]; /* AES key data */
-+ } __packed aesPairwiseKey;
-+ struct {
-+ u8 aesKeyData[16]; /* AES key data */
-+ u8 keyId; /* Key ID */
-+ u8 reserved[3];
-+ u8 rxSeqCounter[8]; /* Receive Sequence Counter */
-+ } __packed aesGroupKey;
-+ struct {
-+ u8 peerAddress[6]; /* MAC address of the
-+ * peer station */
-+ u8 keyId; /* Key ID */
-+ u8 reserved;
-+ u8 wapiKeyData[16]; /* WAPI key data */
-+ u8 micKeyData[16]; /* MIC key data */
-+ } __packed wapiPairwiseKey;
-+ struct {
-+ u8 wapiKeyData[16]; /* WAPI key data */
-+ u8 micKeyData[16]; /* MIC key data */
-+ u8 keyId; /* Key ID */
-+ u8 reserved[3];
-+ } __packed wapiGroupKey;
-+ } __packed;
-+} __packed;
-+
-+int wsm_add_key(struct xradio_common *hw_priv, const struct wsm_add_key *arg,
-+ int if_id);
-+
-+/* 3.32 */
-+struct wsm_remove_key {
-+ /* Key entry index : 0-10 */
-+ u8 entryIndex;
-+};
-+
-+int wsm_remove_key(struct xradio_common *hw_priv,
-+ const struct wsm_remove_key *arg, int if_id);
-+
-+/* 3.34 */
-+struct wsm_set_tx_queue_params {
-+ /* WSM_ACK_POLICY_... */
-+ u8 ackPolicy;
-+
-+ /* Medium Time of TSPEC (in 32us units) allowed per */
-+ /* One Second Averaging Period for this queue. */
-+ u16 allowedMediumTime;
-+
-+ /* dot11MaxTransmitMsduLifetime to be used for the */
-+ /* specified queue. */
-+ u32 maxTransmitLifetime;
-+};
-+
-+struct wsm_tx_queue_params {
-+ /* NOTE: index is a linux queue id. */
-+ struct wsm_set_tx_queue_params params[4];
-+};
-+
-+#define WSM_TX_QUEUE_SET(queue_params, queue, ack_policy, allowed_time, \
-+ max_life_time) \
-+do { \
-+ struct wsm_set_tx_queue_params *p = &(queue_params)->params[queue]; \
-+ p->ackPolicy = (ack_policy); \
-+ p->allowedMediumTime = (allowed_time); \
-+ p->maxTransmitLifetime = (max_life_time); \
-+} while (0)
-+
-+int wsm_set_tx_queue_params(struct xradio_common *hw_priv,
-+ const struct wsm_set_tx_queue_params *arg,
-+ u8 id, int if_id);
-+
-+/* 3.36 */
-+struct wsm_edca_queue_params {
-+ /* CWmin (in slots) for the access class. */
-+ /* [in] */ u16 cwMin;
-+
-+ /* CWmax (in slots) for the access class. */
-+ /* [in] */ u16 cwMax;
-+
-+ /* AIFS (in slots) for the access class. */
-+ /* [in] */ u8 aifns;
-+
-+ /* TX OP Limit (in microseconds) for the access class. */
-+ /* [in] */ u16 txOpLimit;
-+
-+ /* dot11MaxReceiveLifetime to be used for the specified */
-+ /* the access class. Overrides the global */
-+ /* dot11MaxReceiveLifetime value */
-+ /* [in] */ u32 maxReceiveLifetime;
-+
-+ /* UAPSD trigger support for the access class. */
-+ /* [in] */ bool uapsdEnable;
-+};
-+
-+struct wsm_edca_params {
-+ /* NOTE: index is a linux queue id. */
-+ struct wsm_edca_queue_params params[4];
-+};
-+
-+#define TXOP_UNIT 32
-+#define WSM_EDCA_SET(edca, queue, aifs, cw_min, cw_max, txop, life_time,\
-+ uapsd) \
-+ do { \
-+ struct wsm_edca_queue_params *p = &(edca)->params[queue]; \
-+ p->cwMin = (cw_min); \
-+ p->cwMax = (cw_max); \
-+ p->aifns = (aifs); \
-+ p->txOpLimit = ((txop) * TXOP_UNIT); \
-+ p->maxReceiveLifetime = (life_time); \
-+ p->uapsdEnable = (uapsd); \
-+ } while (0)
-+
-+int wsm_set_edca_params(struct xradio_common *hw_priv,
-+ const struct wsm_edca_params *arg, int if_id);
-+
-+int wsm_set_uapsd_param(struct xradio_common *hw_priv,
-+ const struct wsm_edca_params *arg);
-+
-+/* 3.38 */
-+/* Set-System info. Skipped for now. Irrelevent. */
-+
-+/* 3.40 */
-+struct wsm_switch_channel {
-+ /* 1 - means the STA shall not transmit any further */
-+ /* frames until the channel switch has completed */
-+ /* [in] */ u8 channelMode;
-+
-+ /* Number of TBTTs until channel switch occurs. */
-+ /* 0 - indicates switch shall occur at any time */
-+ /* 1 - occurs immediately before the next TBTT */
-+ /* [in] */ u8 channelSwitchCount;
-+
-+ /* The new channel number to switch to. */
-+ /* Note this is defined as per section 2.7. */
-+ /* [in] */ u16 newChannelNumber;
-+};
-+
-+int wsm_switch_channel(struct xradio_common *hw_priv,
-+ const struct wsm_switch_channel *arg, int if_id);
-+
-+struct wsm_start {
-+ /* WSM_START_MODE_... */
-+ /* [in] */ u8 mode;
-+
-+ /* WSM_PHY_BAND_... */
-+ /* [in] */ u8 band;
-+
-+ /* Channel number */
-+ /* [in] */ u16 channelNumber;
-+
-+ /* Client Traffic window in units of TU */
-+ /* Valid only when mode == ..._P2P */
-+ /* [in] */ u32 CTWindow;
-+
-+ /* Interval between two consecutive */
-+ /* beacon transmissions in TU. */
-+ /* [in] */ u32 beaconInterval;
-+
-+ /* DTIM period in terms of beacon intervals */
-+ /* [in] */ u8 DTIMPeriod;
-+
-+ /* WSM_JOIN_PREAMBLE_... */
-+ /* [in] */ u8 preambleType;
-+
-+ /* The delay time (in microseconds) period */
-+ /* before sending a probe-request. */
-+ /* [in] */ u8 probeDelay;
-+
-+ /* Length of the SSID */
-+ /* [in] */ u8 ssidLength;
-+
-+ /* SSID of the BSS or P2P_GO to be started now. */
-+ /* [in] */ u8 ssid[32];
-+
-+ /* The basic supported rates for the MiniAP. */
-+ /* [in] */ u32 basicRateSet;
-+};
-+
-+int wsm_start(struct xradio_common *hw_priv, const struct wsm_start *arg,
-+ int if_id);
-+
-+#if 0
-+struct wsm_beacon_transmit {
-+ /* 1: enable; 0: disable */
-+ /* [in] */ u8 enableBeaconing;
-+};
-+
-+int wsm_beacon_transmit(struct xradio_common *hw_priv,
-+ const struct wsm_beacon_transmit *arg,
-+ int if_id);
-+#endif
-+
-+int wsm_start_find(struct xradio_common *hw_priv, int if_id);
-+
-+int wsm_stop_find(struct xradio_common *hw_priv, int if_id);
-+
-+struct wsm_suspend_resume {
-+ /* See 3.52 */
-+ /* Link ID */
-+ /* [out] */ int link_id;
-+ /* Stop sending further Tx requests down to device for this link */
-+ /* [out] */ bool stop;
-+ /* Transmit multicast Frames */
-+ /* [out] */ bool multicast;
-+ /* The AC on which Tx to be suspended /resumed. */
-+ /* This is applicable only for U-APSD */
-+ /* WSM_QUEUE_... */
-+ /* [out] */ int queue;
-+ /* [out] */ int if_id;
-+};
-+
-+/* 3.54 Update-IE request. */
-+struct wsm_update_ie {
-+ /* WSM_UPDATE_IE_... */
-+ /* [in] */ u16 what;
-+ /* [in] */ u16 count;
-+ /* [in] */ u8 *ies;
-+ /* [in] */ size_t length;
-+};
-+
-+int wsm_update_ie(struct xradio_common *hw_priv,
-+ const struct wsm_update_ie *arg, int if_id);
-+
-+/* 3.56 */
-+struct wsm_map_link {
-+ /* MAC address of the remote device */
-+ /* [in] */ u8 mac_addr[6];
-+ /* [in] */ u8 unmap;
-+ /* [in] */ u8 link_id;
-+};
-+
-+int wsm_map_link(struct xradio_common *hw_priv, const struct wsm_map_link *arg,
-+ int if_id);
-+
-+#ifdef MCAST_FWDING
-+
-+/* 3.65 Give Buffer Request */
-+int wsm_init_release_buffer_request(struct xradio_common *priv, u8 index);
-+
-+/* 3.65 fixed memory leakage by yangfh*/
-+int wsm_deinit_release_buffer(struct xradio_common *hw_priv);
-+
-+/* 3.67 Request Buffer Request */
-+int wsm_request_buffer_request(struct xradio_vif *priv,
-+ u8 *arg);
-+#endif
-+/* ******************************************************************** */
-+/* MIB shortcats */
-+#define XR_RRM 1
-+#ifdef XR_RRM//RadioResourceMeasurement
-+/* RadioResourceMeasurement Request*/
-+#define MEAS_CCA 0
-+#define MEAS_CHANNELLOAD 1
-+typedef struct LMAC_MEAS_CHANNEL_LOAD_PARAMS_S
-+{
-+ u8 Reserved;
-+ u8 ChannelLoadCCA;
-+ u16 ChannelNum;
-+ u16 RandomInterval;
-+ u16 MeasurementDuration;
-+ u32 MeasurementStartTimel;
-+ u32 MeasurementStartTimeh;
-+}LMAC_MEAS_CHANNEL_LOAD_PARAMS;
-+
-+#define MEAS_RPI 0
-+#define MEAS_IPI 1
-+
-+typedef struct LMAC_MEAS_NOISE_HISTOGRAM_PARAMS_S
-+{
-+ u8 Reserved;
-+ u8 IpiRpi;
-+ u16 ChannelNum;
-+ u16 RandomInterval;
-+ u16 MeasurementDuration;
-+ u32 MeasurementStartTimel;
-+ u32 MeasurementStartTimeh;
-+}LMAC_MEAS_NOISE_HISTOGRAM_PARAMS;
-+
-+#define LMAC_MAX_SSIDS 16
-+#define LMAC_MAX_SSID_LENGTH 32
-+typedef struct LMAC_CHANNELS_S
-+{
-+ u32 ChannelNum;
-+ u32 MinChannelTime;
-+ u32 MaxChannelTime;
-+ s32 TxPowerLevel;
-+}LMAC_CHANNELS;
-+
-+typedef struct LMAC_SSIDS_S
-+{
-+ u32 SSIDLength;
-+ u8 SSID[LMAC_MAX_SSID_LENGTH];
-+}LMAC_SSIDS;
-+
-+typedef struct LMAC_MEAS_BEACON_PARAMS_S
-+{
-+ //u8 RegulatoryClass;
-+ //u8 MeasurementMode;
-+ //u16 ChannelNum;
-+ u16 RandomInterval;
-+ //u16 MeasurementDuration;
-+ //u8 Bssid[6];
-+ u16 Reserved;
-+ //SCAN_PARAMETERS ScanParameters;
-+ u8 Band;
-+ u8 ScanType;
-+ u8 ScanFlags;
-+ u8 MaxTransmitRate;
-+ u32 AutoScanInterval;
-+ u8 NumOfProbeRequests;
-+ u8 NumOfChannels;
-+ u8 NumOfSSIDs;
-+ u8 ProbeDelay;
-+ LMAC_CHANNELS Channels;
-+ LMAC_SSIDS Ssids; // here for SCAN_PARAMETER sizing purposes
-+}LMAC_MEAS_BEACON_PARAMS;
-+
-+typedef struct LMAC_MEAS_STA_STATS_PARAMS_S
-+{
-+ u8 PeerMacAddress[6];
-+ u16 RandomInterval;
-+ u16 MeasurementDuration;
-+ u8 GroupId;
-+ u8 Reserved;
-+}LMAC_MEAS_STA_STATS_PARAMS;
-+
-+typedef struct LMAC_MEAS_LINK_MEASUREMENT_PARAMS_S
-+{
-+ u8 Reserved[4];
-+}LMAC_MEAS_LINK_MEASUREMENT_PARAMS;
-+
-+typedef union LMAC_MEAS_REQUEST_U
-+{
-+ LMAC_MEAS_CHANNEL_LOAD_PARAMS ChannelLoadParams;
-+ LMAC_MEAS_NOISE_HISTOGRAM_PARAMS NoisHistogramParams;
-+ LMAC_MEAS_BEACON_PARAMS BeaconParams;
-+ LMAC_MEAS_STA_STATS_PARAMS StaStatsParams;
-+ LMAC_MEAS_LINK_MEASUREMENT_PARAMS LinkMeasurementParams;
-+} LMAC_MEAS_REQUEST;
-+
-+// This struct is a copy of WSM_HI_START_MEASUREMENT_REQ, except that MsgLen and MsgId is not included
-+typedef struct MEASUREMENT_PARAMETERS_S
-+{
-+// u16 MsgLen;
-+// u16 MsgId;
-+ s32 TxPowerLevel;
-+ u8 DurationMandatory;
-+ u8 MeasurementType;
-+ u8 MeasurementRequestLength;
-+ u8 Reserved[5];
-+ LMAC_MEAS_REQUEST MeasurementRequest;
-+}MEASUREMENT_PARAMETERS;
-+
-+/* RadioResourceMeasurement Result*/
-+ typedef struct LMAC_MEAS_CHANNEL_LOAD_RESULTS_S
-+{
-+ u8 Reserved;
-+ u8 ChannelLoadCCA;
-+ u16 ChannelNum;
-+ u32 ActualMeasurementStartTimel;
-+ u32 ActualMeasurementStartTimeh;
-+ u16 MeasurementDuration;
-+ u8 CCAbusyFraction;
-+ u8 ChannelLoad;
-+}LMAC_MEAS_CHANNEL_LOAD_RESULTS;
-+
-+typedef struct LMAC_MEAS_NOISE_HISTOGRAM_RESULTS_S
-+{
-+ u16 Reserved;
-+ u16 ChannelNum;
-+ u32 ActualMeasurementStartTimel;
-+ u32 ActualMeasurementStartTimeh;
-+ u16 MeasurementDuration;
-+ u8 AntennaID;
-+ u8 IpiRpi;
-+ u8 PI_0_Density;
-+ u8 PI_1_Density;
-+ u8 PI_2_Density;
-+ u8 PI_3_Density;
-+ u8 PI_4_Density;
-+ u8 PI_5_Density;
-+ u8 PI_6_Density;
-+ u8 PI_7_Density;
-+ u8 PI_8_Density;
-+ u8 PI_9_Density;
-+ u8 PI_10_Density;
-+ u8 Reserved2;
-+}LMAC_MEAS_NOISE_HISTOGRAM_RESULTS;
-+
-+typedef struct LMAC_MEAS_BEACON_RESULTS_S
-+{
-+ u16 MeasurementDuration;
-+ u16 Reserved;
-+ u32 StartTsfl;
-+ u32 StartTsfh;
-+ u32 Durationl;
-+ u32 Durationh;
-+ //SCAN_PARAMETERS ScanParameters;
-+ u8 Band;
-+ u8 ScanType;
-+ u8 ScanFlags;
-+ u8 MaxTransmitRate;
-+ u32 AutoScanInterval;
-+ u8 NumOfProbeRequests;
-+ u8 NumOfChannels;
-+ u8 NumOfSSIDs;
-+ u8 ProbeDelay;
-+ LMAC_CHANNELS Channels;
-+ LMAC_SSIDS Ssids;
-+}LMAC_MEAS_BEACON_RESULTS;
-+
-+typedef struct LMAC_MEAS_STA_STATS_RESULTS_S
-+{
-+ u16 MeasurementDuration;
-+ u8 GroupId;
-+ u8 StatisticsGroupDataLength;
-+ u8 StatisticsGroupData[52];
-+}LMAC_MEAS_STA_STATS_RESULTS;
-+
-+typedef struct LMAC_MEAS_LINK_MEASUREMENT_RESULTS_S
-+{
-+ s16 TransmitPower;
-+ u8 RxAntennaID;
-+ u8 TxAntennaID;
-+ s32 NoiseLeveldBm;
-+ s8 LatestRssi;
-+ u8 Reserved1;
-+ u8 Reserved2;
-+ u8 Reserved3;
-+}LMAC_MEAS_LINK_MEASUREMENT_RESULTS;
-+
-+typedef union LMAC_MEAS_REPORT_U
-+{
-+ LMAC_MEAS_CHANNEL_LOAD_RESULTS ChannelLoadResults;
-+ LMAC_MEAS_NOISE_HISTOGRAM_RESULTS NoiseHistogramResults;
-+ LMAC_MEAS_BEACON_RESULTS BeaconResults;
-+ LMAC_MEAS_STA_STATS_RESULTS StaStatsResults;
-+ LMAC_MEAS_LINK_MEASUREMENT_RESULTS LinkMeasurementResults;
-+}LMAC_MEAS_REPORT;
-+
-+// Note: eMeasurementTypes MUST match the #define WSM_MEASURE_TYPE_XXX from wsm_api.h
-+typedef enum {
-+ ChannelLoadMeasurement=0,
-+ NoiseHistrogramMeasurement,
-+ BeaconReport,
-+ STAstatisticsReport,
-+ LinkMeasurement
-+}eMeasurementTypes;
-+
-+typedef struct MEASUREMENT_COMPLETE_S
-+{
-+// u16 RandomInterval;
-+// u16 Reserved0;
-+ u8 Dot11PowerMgmtMode; // From here WSM_HI_MEASURE_CMPL_IND and MEASUREMENT_COMPLETE_S must be identical
-+ u8 MeasurementType;
-+ u16 MoreInd; // Set to 1 if more indications are to follow for this measurement, otherwise 0;
-+ u32 Status;
-+ u8 MeasurementReportLength;
-+ u8 Reserved2[3];
-+ LMAC_MEAS_REPORT MeasurementReport;
-+}MEASUREMENT_COMPLETE; // Note: must be 32 bit aligned
-+
-+#endif
-+int wsm_11k_measure_requset(struct xradio_common *hw_priv,
-+ u8 measure_type,
-+ u16 ChannelNum,
-+ u16 Duration);
-+
-+
-+static inline int wsm_set_fw_debug_control(struct xradio_common *hw_priv,
-+ int debug_control, int if_id)
-+{
-+ __le32 val = __cpu_to_le32(debug_control);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_FW_DEBUG_CONTROL,
-+ &val, sizeof(val), if_id);
-+}
-+
-+static inline int wsm_set_host_sleep(struct xradio_common *hw_priv,
-+ u8 host_sleep, int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_HOST_SLEEP,
-+ &host_sleep, sizeof(host_sleep), if_id);
-+}
-+
-+static inline int wsm_set_output_power(struct xradio_common *hw_priv,
-+ int power_level, int if_id)
-+{
-+ __le32 val = __cpu_to_le32(power_level);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_CURRENT_TX_POWER_LEVEL,
-+ &val, sizeof(val), if_id);
-+}
-+
-+static inline int wsm_set_beacon_wakeup_period(struct xradio_common *hw_priv,
-+ unsigned dtim_interval,
-+ unsigned listen_interval,
-+ int if_id)
-+{
-+ struct {
-+ u8 numBeaconPeriods;
-+ u8 reserved;
-+ __le16 listenInterval;
-+ } val = {
-+ dtim_interval, 0, __cpu_to_le16(listen_interval)};
-+ if (dtim_interval > 0xFF || listen_interval > 0xFFFF)
-+ return -EINVAL;
-+ else
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_WAKEUP_PERIOD,
-+ &val, sizeof(val), if_id);
-+}
-+
-+struct wsm_rcpi_rssi_threshold {
-+ u8 rssiRcpiMode; /* WSM_RCPI_RSSI_... */
-+ u8 lowerThreshold;
-+ u8 upperThreshold;
-+ u8 rollingAverageCount;
-+};
-+
-+static inline int wsm_set_rcpi_rssi_threshold(struct xradio_common *hw_priv,
-+ struct wsm_rcpi_rssi_threshold *arg,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_RCPI_RSSI_THRESHOLD, arg,
-+ sizeof(*arg), if_id);
-+}
-+
-+struct wsm_counters_table {
-+ __le32 countPlcpErrors;
-+ __le32 countFcsErrors;
-+ __le32 countTxPackets;
-+ __le32 countRxPackets;
-+ __le32 countRxPacketErrors;
-+ __le32 countRtsSuccess;
-+ __le32 countRtsFailures;
-+ __le32 countRxFramesSuccess;
-+ __le32 countRxDecryptionFailures;
-+ __le32 countRxMicFailures;
-+ __le32 countRxNoKeyFailures;
-+ __le32 countTxMulticastFrames;
-+ __le32 countTxFramesSuccess;
-+ __le32 countTxFrameFailures;
-+ __le32 countTxFramesRetried;
-+ __le32 countTxFramesMultiRetried;
-+ __le32 countRxFrameDuplicates;
-+ __le32 countAckFailures;
-+ __le32 countRxMulticastFrames;
-+ __le32 countRxCMACICVErrors;
-+ __le32 countRxCMACReplays;
-+ __le32 countRxMgmtCCMPReplays;
-+ __le32 countRxBIPMICErrors;
-+};
-+
-+
-+struct wsm_ampducounters_table {
-+ u32 countTxAMPDUs;
-+ u32 countTxMPDUsInAMPDUs;
-+ u32 countTxOctetsInAMPDUs_l32;
-+ u32 countTxOctetsInAMPDUs_h32;
-+ u32 countRxAMPDUs;
-+ u32 countRxMPDUsInAMPDUs;
-+ u32 countRxOctetsInAMPDUs_l32;
-+ u32 countRxOctetsInAMPDUs_h32;
-+ u32 countRxDelimeterCRCErrorCount;
-+ u32 countImplictBARFailures;
-+ u32 countExplictBARFailures;
-+};
-+
-+struct wsm_txpipe_counter {
-+ u32 count1;
-+ u32 count2;
-+ u32 count3;
-+ u32 count4;
-+ u32 count5;
-+ u32 count6;
-+ u32 count7;
-+ u32 count8;
-+ u32 count9;
-+ u32 counta;
-+};
-+
-+struct wsm_backoff_counter {
-+ u32 count0;
-+ u32 count1;
-+ u32 count2;
-+ u32 count3;
-+ u32 count4;
-+ u32 count5;
-+ u32 count6;
-+ u32 count7;
-+ u32 count8;
-+ u32 count9;
-+};
-+//add by yangfh for read/write fw registers
-+#define WSM_REG_RW_F BIT(0) //0:read, 1:write
-+#define WSM_REG_RET_F BIT(1) //results is valid.
-+#define WSM_REG_BK_F BIT(4) //operate in block mode.
-+
-+struct reg_data {
-+ u32 reg_addr;
-+ u32 reg_val;
-+};
-+
-+typedef struct tag_wsm_reg_w {
-+ u16 flag;
-+ u16 data_size;
-+ struct reg_data arg[16];
-+} WSM_REG_W;
-+
-+typedef struct tag_wsm_reg_r {
-+ u16 flag;
-+ u16 data_size;
-+ u32 arg[16];
-+} WSM_REG_R;
-+
-+struct wsm_backoff_ctrl {
-+ u32 enable;
-+ u32 min;
-+ u32 max;
-+};
-+struct wsm_tala_para {
-+ u32 para;
-+ u32 thresh;
-+};
-+static inline int wsm_get_counters_table(struct xradio_common *hw_priv,
-+ struct wsm_counters_table *arg)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_COUNTERS_TABLE,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_get_ampducounters_table(struct xradio_common *hw_priv,
-+ struct wsm_ampducounters_table *arg)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_AMPDUCOUNTERS_TABLE,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_get_txpipe_table(struct xradio_common *hw_priv,
-+ struct wsm_txpipe_counter *arg)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_TXPIPE_TABLE,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_get_backoff_dbg(struct xradio_common *hw_priv,
-+ struct wsm_backoff_counter *arg)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_BACKOFF_DBG,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_set_backoff_ctrl(struct xradio_common *hw_priv,
-+ struct wsm_backoff_ctrl *arg)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BACKOFF_CTRL,
-+ arg, sizeof(*arg), 0);
-+}
-+
-+static inline int wsm_set_tala(struct xradio_common *hw_priv,
-+ struct wsm_tala_para *arg)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_TALA_PARA,
-+ arg, sizeof(*arg), 0);
-+}
-+static inline int wsm_get_station_id(struct xradio_common *hw_priv, u8 *mac)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_DOT11_STATION_ID, mac,
-+ ETH_ALEN, 0);
-+}
-+
-+struct wsm_rx_filter {
-+ bool promiscuous;
-+ bool bssid;
-+ bool fcs;
-+ bool probeResponder;
-+ bool keepalive;
-+};
-+
-+static inline int wsm_set_rx_filter(struct xradio_common *hw_priv,
-+ const struct wsm_rx_filter *arg,
-+ int if_id)
-+{
-+ __le32 val = 0;
-+ if (arg->promiscuous)
-+ val |= __cpu_to_le32(BIT(0));
-+ if (arg->bssid)
-+ val |= __cpu_to_le32(BIT(1));
-+ if (arg->fcs)
-+ val |= __cpu_to_le32(BIT(2));
-+ if (arg->probeResponder)
-+ val |= __cpu_to_le32(BIT(3));
-+ if (arg->keepalive)
-+ val |= __cpu_to_le32(BIT(4));
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_RX_FILTER, &val, sizeof(val),
-+ if_id);
-+}
-+
-+int wsm_set_probe_responder(struct xradio_vif *priv, bool enable);
-+int wsm_set_keepalive_filter(struct xradio_vif *priv, bool enable);
-+
-+#define WSM_BEACON_FILTER_IE_HAS_CHANGED BIT(0)
-+#define WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT BIT(1)
-+#define WSM_BEACON_FILTER_IE_HAS_APPEARED BIT(2)
-+
-+struct wsm_beacon_filter_table_entry {
-+ u8 ieId;
-+ u8 actionFlags;
-+ u8 oui[3];
-+ u8 matchData[3];
-+} __packed;
-+
-+struct wsm_beacon_filter_table {
-+ __le32 numOfIEs;
-+ struct wsm_beacon_filter_table_entry entry[10];
-+} __packed;
-+
-+static inline int wsm_set_beacon_filter_table(struct xradio_common *hw_priv,
-+ struct wsm_beacon_filter_table *ft,
-+ int if_id)
-+{
-+ size_t size = __le32_to_cpu(ft->numOfIEs) *
-+ sizeof(struct wsm_beacon_filter_table_entry) +
-+ sizeof(__le32);
-+
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_FILTER_TABLE, ft, size,
-+ if_id);
-+}
-+
-+#define WSM_BEACON_FILTER_ENABLE BIT(0) /* Enable/disable beacon filtering */
-+#define WSM_BEACON_FILTER_AUTO_ERP BIT(1) /* If 1 FW will handle ERP IE changes internally */
-+
-+struct wsm_beacon_filter_control {
-+ int enabled;
-+ int bcn_count;
-+};
-+
-+static inline int wsm_beacon_filter_control(struct xradio_common *hw_priv,
-+ struct wsm_beacon_filter_control *arg,
-+ int if_id)
-+{
-+ struct {
-+ __le32 enabled;
-+ __le32 bcn_count;
-+ } val;
-+ val.enabled = __cpu_to_le32(arg->enabled);
-+ val.bcn_count = __cpu_to_le32(arg->bcn_count);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_FILTER_ENABLE, &val,
-+ sizeof(val), if_id);
-+}
-+
-+enum wsm_power_mode {
-+ wsm_power_mode_active = 0,
-+ wsm_power_mode_doze = 1,
-+ wsm_power_mode_quiescent = 2,
-+};
-+
-+struct wsm_operational_mode {
-+ enum wsm_power_mode power_mode;
-+ int disableMoreFlagUsage;
-+ int performAntDiversity;
-+};
-+
-+static const struct wsm_operational_mode defaultoperationalmode = {
-+ .power_mode = wsm_power_mode_active,
-+ .disableMoreFlagUsage = true,
-+};
-+
-+static inline int wsm_set_operational_mode(struct xradio_common *hw_priv,
-+ const struct wsm_operational_mode *arg,
-+ int if_id)
-+{
-+ u32 val = arg->power_mode;
-+
-+ if (arg->disableMoreFlagUsage)
-+ val |= BIT(4);
-+ if (arg->performAntDiversity)
-+ val |= BIT(5);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_OPERATIONAL_POWER_MODE, &val,
-+ sizeof(val), if_id);
-+}
-+
-+struct wsm_inactivity {
-+ u8 max_inactivity;
-+ u8 min_inactivity;
-+};
-+
-+static inline int wsm_set_inactivity(struct xradio_common *hw_priv,
-+ const struct wsm_inactivity *arg,
-+ int if_id)
-+{
-+ struct {
-+ u8 min_inactive;
-+ u8 max_inactive;
-+ u16 reserved;
-+ } val;
-+
-+ val.max_inactive = arg->max_inactivity;
-+ val.min_inactive = arg->min_inactivity;
-+ val.reserved = 0;
-+
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_INACTIVITY, &val,
-+ sizeof(val), if_id);
-+}
-+
-+struct wsm_template_frame {
-+ u8 frame_type;
-+ u8 rate;
-+ bool disable;
-+ struct sk_buff *skb;
-+};
-+
-+static inline int wsm_set_template_frame(struct xradio_common *hw_priv,
-+ struct wsm_template_frame *arg,
-+ int if_id)
-+{
-+ int ret;
-+ u8 *p = skb_push(arg->skb, 4);
-+ p[0] = arg->frame_type;
-+ p[1] = arg->rate;
-+ if (arg->disable)
-+ ((u16 *) p)[1] = 0;
-+ else
-+ ((u16 *) p)[1] = __cpu_to_le16(arg->skb->len - 4);
-+ ret = wsm_write_mib(hw_priv, WSM_MIB_ID_TEMPLATE_FRAME, p,
-+ arg->skb->len, if_id);
-+ skb_pull(arg->skb, 4);
-+ return ret;
-+}
-+
-+
-+struct wsm_protected_mgmt_policy {
-+ bool protectedMgmtEnable;
-+ bool unprotectedMgmtFramesAllowed;
-+ bool encryptionForAuthFrame;
-+};
-+
-+static inline int
-+wsm_set_protected_mgmt_policy(struct xradio_common *hw_priv,
-+ struct wsm_protected_mgmt_policy *arg,
-+ int if_id)
-+{
-+ __le32 val = 0;
-+ int ret;
-+ if (arg->protectedMgmtEnable)
-+ val |= __cpu_to_le32(BIT(0));
-+ if (arg->unprotectedMgmtFramesAllowed)
-+ val |= __cpu_to_le32(BIT(1));
-+ if (arg->encryptionForAuthFrame)
-+ val |= __cpu_to_le32(BIT(2));
-+ ret = wsm_write_mib(hw_priv, WSM_MIB_ID_PROTECTED_MGMT_POLICY, &val,
-+ sizeof(val), if_id);
-+ return ret;
-+}
-+
-+static inline int wsm_set_block_ack_policy(struct xradio_common *hw_priv,
-+ u8 blockAckTxTidPolicy,
-+ u8 blockAckRxTidPolicy,
-+ int if_id)
-+{
-+ struct {
-+ u8 blockAckTxTidPolicy;
-+ u8 reserved1;
-+ u8 blockAckRxTidPolicy;
-+ u8 reserved2;
-+ } val = {
-+ .blockAckTxTidPolicy = blockAckTxTidPolicy,
-+ .blockAckRxTidPolicy = blockAckRxTidPolicy,
-+ };
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_BLOCK_ACK_POLICY, &val,
-+ sizeof(val), if_id);
-+}
-+
-+struct wsm_association_mode {
-+ u8 flags; /* WSM_ASSOCIATION_MODE_... */
-+ u8 preambleType; /* WSM_JOIN_PREAMBLE_... */
-+ u8 greenfieldMode; /* 1 for greenfield */
-+ u8 mpduStartSpacing;
-+ __le32 basicRateSet;
-+};
-+
-+static inline int wsm_set_association_mode(struct xradio_common *hw_priv,
-+ struct wsm_association_mode *arg,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_ASSOCIATION_MODE, arg,
-+ sizeof(*arg), if_id);
-+}
-+
-+struct wsm_set_tx_rate_retry_policy_header {
-+ u8 numTxRatePolicies;
-+ u8 reserved[3];
-+} __packed;
-+
-+struct wsm_set_tx_rate_retry_policy_policy {
-+ u8 policyIndex;
-+ u8 shortRetryCount;
-+ u8 longRetryCount;
-+ u8 policyFlags;
-+ u8 rateRecoveryCount;
-+ u8 reserved[3];
-+ __le32 rateCountIndices[3];
-+} __packed;
-+
-+struct wsm_set_tx_rate_retry_policy {
-+ struct wsm_set_tx_rate_retry_policy_header hdr;
-+ struct wsm_set_tx_rate_retry_policy_policy tbl[8];
-+} __packed;
-+
-+static inline int wsm_set_tx_rate_retry_policy(struct xradio_common *hw_priv,
-+ struct wsm_set_tx_rate_retry_policy *arg,
-+ int if_id)
-+{
-+ size_t size = sizeof(struct wsm_set_tx_rate_retry_policy_header) +
-+ arg->hdr.numTxRatePolicies *
-+ sizeof(struct wsm_set_tx_rate_retry_policy_policy);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_TX_RATE_RETRY_POLICY, arg,
-+ size, if_id);
-+}
-+
-+/* 4.32 SetEtherTypeDataFrameFilter */
-+struct wsm_ether_type_filter_hdr {
-+ u8 nrFilters; /* Up to WSM_MAX_FILTER_ELEMENTS */
-+ u8 reserved[3];
-+} __packed;
-+
-+struct wsm_ether_type_filter {
-+ u8 filterAction; /* WSM_FILTER_ACTION_XXX */
-+ u8 reserved;
-+ __le16 etherType; /* Type of ethernet frame */
-+} __packed;
-+
-+static inline int wsm_set_ether_type_filter(struct xradio_common *hw_priv,
-+ struct wsm_ether_type_filter_hdr *arg,
-+ int if_id)
-+{
-+ size_t size = sizeof(struct wsm_ether_type_filter_hdr) +
-+ arg->nrFilters * sizeof(struct wsm_ether_type_filter);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_ETHERTYPE_DATAFRAME_FILTER,
-+ arg, size, if_id);
-+}
-+
-+
-+/* 4.33 SetUDPPortDataFrameFilter */
-+struct wsm_udp_port_filter_hdr {
-+ u8 nrFilters; /* Up to WSM_MAX_FILTER_ELEMENTS */
-+ u8 reserved[3];
-+} __packed;
-+
-+struct wsm_udp_port_filter {
-+ u8 filterAction; /* WSM_FILTER_ACTION_XXX */
-+ u8 portType; /* WSM_FILTER_PORT_TYPE_XXX */
-+ __le16 udpPort; /* Port number */
-+} __packed;
-+
-+static inline int wsm_set_udp_port_filter(struct xradio_common *hw_priv,
-+ struct wsm_udp_port_filter_hdr *arg,
-+ int if_id)
-+{
-+ size_t size = sizeof(struct wsm_udp_port_filter_hdr) +
-+ arg->nrFilters * sizeof(struct wsm_udp_port_filter);
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_UDPPORT_DATAFRAME_FILTER,
-+ arg, size, if_id);
-+}
-+
-+/* Undocumented MIBs: */
-+/* 4.35 P2PDeviceInfo */
-+#define D11_MAX_SSID_LEN (32)
-+
-+struct wsm_p2p_device_type {
-+ __le16 categoryId;
-+ u8 oui[4];
-+ __le16 subCategoryId;
-+} __packed;
-+
-+struct wsm_p2p_device_info {
-+ struct wsm_p2p_device_type primaryDevice;
-+ u8 reserved1[3];
-+ u8 devNameSize;
-+ u8 localDevName[D11_MAX_SSID_LEN];
-+ u8 reserved2[3];
-+ u8 numSecDevSupported;
-+ struct wsm_p2p_device_type secondaryDevices[0];
-+} __packed;
-+
-+/* 4.36 SetWCDMABand - WO */
-+struct wsm_cdma_band {
-+ u8 WCDMA_Band;
-+ u8 reserved[3];
-+} __packed;
-+
-+/* 4.37 GroupTxSequenceCounter - RO */
-+struct wsm_group_tx_seq {
-+ __le32 bits_47_16;
-+ __le16 bits_15_00;
-+ __le16 reserved;
-+} __packed;
-+
-+/* 4.39 SetHtProtection - WO */
-+#define WSM_DUAL_CTS_PROT_ENB (1 << 0)
-+#define WSM_NON_GREENFIELD_STA PRESENT(1 << 1)
-+#define WSM_HT_PROT_MODE__NO_PROT (0 << 2)
-+#define WSM_HT_PROT_MODE__NON_MEMBER (1 << 2)
-+#define WSM_HT_PROT_MODE__20_MHZ (2 << 2)
-+#define WSM_HT_PROT_MODE__NON_HT_MIXED (3 << 2)
-+#define WSM_LSIG_TXOP_PROT_FULL (1 << 4)
-+#define WSM_LARGE_L_LENGTH_PROT (1 << 5)
-+
-+struct wsm_ht_protection {
-+ __le32 flags;
-+} __packed;
-+
-+/* 4.40 GPIO Command - R/W */
-+#define WSM_GPIO_COMMAND_SETUP 0
-+#define WSM_GPIO_COMMAND_READ 1
-+#define WSM_GPIO_COMMAND_WRITE 2
-+#define WSM_GPIO_COMMAND_RESET 3
-+#define WSM_GPIO_ALL_PINS 0xFF
-+
-+struct wsm_gpio_command {
-+ u8 GPIO_Command;
-+ u8 pin;
-+ __le16 config;
-+} __packed;
-+
-+/* 4.41 TSFCounter - RO */
-+struct wsm_tsf_counter {
-+ __le64 TSF_Counter;
-+} __packed;
-+
-+/* 4.43 Keep alive period */
-+struct wsm_keep_alive_period {
-+ __le16 keepAlivePeriod;
-+ u8 reserved[2];
-+} __packed;
-+
-+static inline int wsm_keep_alive_period(struct xradio_common *hw_priv,
-+ int period, int if_id)
-+{
-+ struct wsm_keep_alive_period arg = {
-+ .keepAlivePeriod = __cpu_to_le16(period),
-+ };
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_KEEP_ALIVE_PERIOD,
-+ &arg, sizeof(arg), if_id);
-+};
-+
-+/* BSSID filtering */
-+struct wsm_set_bssid_filtering {
-+ u8 filter;
-+ u8 reserved[3];
-+} __packed;
-+
-+static inline int wsm_set_bssid_filtering(struct xradio_common *hw_priv,
-+ bool enabled, int if_id)
-+{
-+ struct wsm_set_bssid_filtering arg = {
-+ .filter = !enabled,
-+ };
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_DISABLE_BSSID_FILTER,
-+ &arg, sizeof(arg), if_id);
-+}
-+
-+/* Multicat filtering - 4.5 */
-+struct wsm_multicast_filter {
-+ __le32 enable;
-+ __le32 numOfAddresses;
-+ u8 macAddress[WSM_MAX_GRP_ADDRTABLE_ENTRIES][ETH_ALEN];
-+} __packed;
-+
-+/* Mac Addr Filter Info */
-+struct wsm_mac_addr_info {
-+ u8 filter_mode;
-+ u8 address_mode;
-+ u8 MacAddr[6];
-+} __packed;
-+
-+/* Mac Addr Filter */
-+struct wsm_mac_addr_filter {
-+ u8 numfilter;
-+ u8 action_mode;
-+ u8 Reserved[2];
-+ struct wsm_mac_addr_info macaddrfilter[0];
-+} __packed;
-+
-+/* Broadcast Addr Filter */
-+struct wsm_broadcast_addr_filter {
-+ u8 action_mode;
-+ u8 nummacaddr;
-+ u8 filter_mode;
-+ u8 address_mode;
-+ u8 MacAddr[6];
-+} __packed;
-+
-+static inline int wsm_set_multicast_filter(struct xradio_common *hw_priv,
-+ struct wsm_multicast_filter *fp,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_GROUP_ADDRESSES_TABLE,
-+ fp, sizeof(*fp), if_id);
-+}
-+
-+/* ARP IPv4 filtering - 4.10 */
-+struct wsm_arp_ipv4_filter {
-+ __le32 enable;
-+ __be32 ipv4Address[WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES];
-+} __packed;
-+
-+
-+static inline int wsm_set_arp_ipv4_filter(struct xradio_common *hw_priv,
-+ struct wsm_arp_ipv4_filter *fp,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_ARP_IP_ADDRESSES_TABLE,
-+ fp, sizeof(*fp), if_id);
-+}
-+
-+/* P2P Power Save Mode Info - 4.31 */
-+struct wsm_p2p_ps_modeinfo {
-+ u8 oppPsCTWindow;
-+ u8 count;
-+ u8 reserved;
-+ u8 dtimCount;
-+ __le32 duration;
-+ __le32 interval;
-+ __le32 startTime;
-+} __packed;
-+
-+static inline int wsm_set_p2p_ps_modeinfo(struct xradio_common *hw_priv,
-+ struct wsm_p2p_ps_modeinfo *mi,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_P2P_PS_MODE_INFO,
-+ mi, sizeof(*mi), if_id);
-+}
-+
-+static inline int wsm_get_p2p_ps_modeinfo(struct xradio_common *hw_priv,
-+ struct wsm_p2p_ps_modeinfo *mi)
-+{
-+ return wsm_read_mib(hw_priv, WSM_MIB_ID_P2P_PS_MODE_INFO,
-+ mi, sizeof(*mi), 0);
-+}
-+
-+/* UseMultiTxConfMessage */
-+
-+static inline int wsm_use_multi_tx_conf(struct xradio_common *hw_priv,
-+ bool enabled, int if_id)
-+{
-+ __le32 arg = enabled ? __cpu_to_le32(1) : 0;
-+
-+ return wsm_write_mib(hw_priv, WSM_MIB_USE_MULTI_TX_CONF,
-+ &arg, sizeof(arg), if_id);
-+}
-+
-+
-+/* 4.26 SetUpasdInformation */
-+struct wsm_uapsd_info {
-+ __le16 uapsdFlags;
-+ __le16 minAutoTriggerInterval;
-+ __le16 maxAutoTriggerInterval;
-+ __le16 autoTriggerStep;
-+};
-+
-+static inline int wsm_set_uapsd_info(struct xradio_common *hw_priv,
-+ struct wsm_uapsd_info *arg,
-+ int if_id)
-+{
-+ /* TODO:COMBO:UAPSD will be supported only on one interface */
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_SET_UAPSD_INFORMATION,
-+ arg, sizeof(*arg), if_id);
-+}
-+
-+/* 4.22 OverrideInternalTxRate */
-+struct wsm_override_internal_txrate {
-+ u8 internalTxRate;
-+ u8 nonErpInternalTxRate;
-+ u8 reserved[2];
-+} __packed;
-+
-+static inline int
-+wsm_set_override_internal_txrate(struct xradio_common *hw_priv,
-+ struct wsm_override_internal_txrate *arg,
-+ int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE,
-+ arg, sizeof(*arg), if_id);
-+}
-+#ifdef MCAST_FWDING
-+/* 4.51 SetForwardingOffload */
-+struct wsm_forwarding_offload {
-+ u8 fwenable;
-+ u8 flags;
-+ u8 reserved[2];
-+} __packed;
-+
-+static inline int wsm_set_forwarding_offlad(struct xradio_common *hw_priv,
-+ struct wsm_forwarding_offload *arg,int if_id)
-+{
-+ return wsm_write_mib(hw_priv, WSM_MIB_ID_FORWARDING_OFFLOAD,
-+ arg, sizeof(*arg),if_id);
-+}
-+
-+#endif
-+/* ******************************************************************** */
-+/* WSM TX port control */
-+
-+void wsm_lock_tx(struct xradio_common *hw_priv);
-+void wsm_vif_lock_tx(struct xradio_vif *priv);
-+void wsm_lock_tx_async(struct xradio_common *hw_priv);
-+bool wsm_flush_tx(struct xradio_common *hw_priv);
-+bool wsm_vif_flush_tx(struct xradio_vif *priv);
-+void wsm_unlock_tx(struct xradio_common *hw_priv);
-+
-+/* ******************************************************************** */
-+/* WSM / BH API */
-+
-+int wsm_handle_exception(struct xradio_common *hw_priv, u8 * data, size_t len);
-+int wsm_handle_rx(struct xradio_common *hw_priv, int id, struct wsm_hdr *wsm,
-+ struct sk_buff **skb_p);
-+void wms_send_deauth_to_self(struct xradio_common *hw_priv, struct xradio_vif *priv);
-+void wms_send_disassoc_to_self(struct xradio_common *hw_priv, struct xradio_vif *priv);
-+
-+/* ******************************************************************** */
-+/* wsm_buf API */
-+
-+struct wsm_buf {
-+ u8 *begin;
-+ u8 *data;
-+ u8 *end;
-+};
-+
-+void wsm_buf_init(struct wsm_buf *buf);
-+void wsm_buf_deinit(struct wsm_buf *buf);
-+
-+/* ******************************************************************** */
-+/* wsm_cmd API */
-+
-+struct wsm_cmd {
-+ spinlock_t lock;
-+ int done;
-+ u8 *ptr;
-+ size_t len;
-+ void *arg;
-+ int ret;
-+ u16 cmd;
-+};
-+
-+/* ******************************************************************** */
-+/* WSM TX buffer access */
-+
-+int wsm_get_tx(struct xradio_common *hw_priv, u8 **data,
-+ size_t *tx_len, int *burst, int *vif_selected);
-+void wsm_txed(struct xradio_common *hw_priv, u8 *data);
-+
-+/* ******************************************************************** */
-+/* Queue mapping: WSM <---> linux */
-+/* Linux: VO VI BE BK */
-+/* WSM: BE BK VI VO */
-+
-+static inline u8 wsm_queue_id_to_linux(u8 queueId)
-+{
-+ static const u8 queue_mapping[] = {
-+ 2, 3, 1, 0
-+ };
-+ return queue_mapping[queueId];
-+}
-+
-+static inline u8 wsm_queue_id_to_wsm(u8 queueId)
-+{
-+ static const u8 queue_mapping[] = {
-+ 3, 2, 0, 1
-+ };
-+ return queue_mapping[queueId];
-+}
-+
-+#endif /* XRADIO_HWIO_H_INCLUDED */
-diff --git a/drivers/net/wireless/xradio/xradio.h b/drivers/net/wireless/xradio/xradio.h
-new file mode 100644
-index 0000000..d565db0
---- /dev/null
-+++ b/drivers/net/wireless/xradio/xradio.h
-@@ -0,0 +1,577 @@
-+/*
-+ * Common define of private data for XRadio drivers
-+ *
-+ * Copyright (c) 2013, XRadio
-+ * Author: XRadio
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef XRADIO_H
-+#define XRADIO_H
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+//Macroses for Driver parameters.
-+#define XRWL_MAX_QUEUE_SZ (128)
-+#define AC_QUEUE_NUM 4
-+
-+#define XRWL_MAX_VIFS (2)
-+#define XRWL_GENERIC_IF_ID (2)
-+#define XRWL_HOST_VIF0_11N_THROTTLE (58) //(XRWL_MAX_QUEUE_SZ/(XRWL_MAX_VIFS-1))*0.9
-+#define XRWL_HOST_VIF1_11N_THROTTLE (58) //(XRWL_MAX_QUEUE_SZ/(XRWL_MAX_VIFS-1))*0.9
-+#define XRWL_HOST_VIF0_11BG_THROTTLE (35) //XRWL_HOST_VIF0_11N_THROTTLE*0.6 = 35
-+#define XRWL_HOST_VIF1_11BG_THROTTLE (35) //XRWL_HOST_VIF0_11N_THROTTLE*0.6 = 35
-+#if 0
-+#define XRWL_FW_VIF0_THROTTLE (15)
-+#define XRWL_FW_VIF1_THROTTLE (15)
-+#endif
-+
-+#define IEEE80211_FCTL_WEP 0x4000
-+#define IEEE80211_QOS_DATAGRP 0x0080
-+#define WSM_KEY_MAX_IDX 20
-+
-+#include "queue.h"
-+#include "wsm.h"
-+#include "scan.h"
-+#include "tx.h"
-+#include "ht.h"
-+#include "pm.h"
-+#include "fwio.h"
-+
-+/* #define ROC_DEBUG */
-+/* hidden ssid is only supported when separate probe resp IE
-+ configuration is supported */
-+#ifdef PROBE_RESP_EXTRA_IE
-+#define HIDDEN_SSID 1
-+#endif
-+
-+#define XRADIO_MAX_CTRL_FRAME_LEN (0x1000)
-+
-+#define MAX_STA_IN_AP_MODE (14)
-+#define WLAN_LINK_ID_MAX (MAX_STA_IN_AP_MODE + 3)
-+
-+#define XRADIO_MAX_STA_IN_AP_MODE (5)
-+#define XRADIO_MAX_REQUEUE_ATTEMPTS (5)
-+#define XRADIO_LINK_ID_UNMAPPED (15)
-+#define XRADIO_MAX_TID (8)
-+
-+#define XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID (0x3F)
-+#define XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID (0x3F)
-+#define XRADIO_RX_BLOCK_ACK_ENABLED_FOR_BE_TID \
-+ (XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID & 0x01)
-+#define XRADIO_TX_BLOCK_ACK_DISABLED_FOR_ALL_TID (0)
-+#define XRADIO_RX_BLOCK_ACK_DISABLED_FOR_ALL_TID (0)
-+
-+#define XRADIO_BLOCK_ACK_CNT (30)
-+#define XRADIO_BLOCK_ACK_THLD (800)
-+#define XRADIO_BLOCK_ACK_HIST (3)
-+#define XRADIO_BLOCK_ACK_INTERVAL (1 * HZ / XRADIO_BLOCK_ACK_HIST)
-+#define XRWL_ALL_IFS (-1)
-+
-+#ifdef ROAM_OFFLOAD
-+#define XRADIO_SCAN_TYPE_ACTIVE 0x1000
-+#define XRADIO_SCAN_BAND_5G 0x2000
-+#endif /*ROAM_OFFLOAD*/
-+
-+#define IEEE80211_FCTL_WEP 0x4000
-+#define IEEE80211_QOS_DATAGRP 0x0080
-+
-+#ifdef MCAST_FWDING
-+#define WSM_MAX_BUF 30
-+#endif
-+
-+#define MAX_RATES_STAGE 8 //
-+#define MAX_RATES_RETRY 15
-+
-+#define XRADIO_WORKQUEUE "xradio_wq"
-+#define WIFI_CONF_PATH "/data/xr_wifi.conf"
-+
-+/* extern */ struct task_struct;
-+/* extern */ struct xradio_debug_priv;
-+/* extern */ struct xradio_debug_common;
-+/* extern */ struct firmware;
-+
-+/* Please keep order */
-+enum xradio_join_status {
-+ XRADIO_JOIN_STATUS_PASSIVE = 0,
-+ XRADIO_JOIN_STATUS_MONITOR,
-+ XRADIO_JOIN_STATUS_STA,
-+ XRADIO_JOIN_STATUS_AP,
-+};
-+
-+enum xradio_link_status {
-+ XRADIO_LINK_OFF,
-+ XRADIO_LINK_RESERVE,
-+ XRADIO_LINK_SOFT,
-+ XRADIO_LINK_HARD,
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ XRADIO_LINK_RESET,
-+ XRADIO_LINK_RESET_REMAP,
-+#endif
-+};
-+
-+enum xradio_bss_loss_status {
-+ XRADIO_BSS_LOSS_NONE,
-+ XRADIO_BSS_LOSS_CHECKING,
-+ XRADIO_BSS_LOSS_CONFIRMING,
-+ XRADIO_BSS_LOSS_CONFIRMED,
-+};
-+
-+struct xradio_link_entry {
-+ unsigned long timestamp;
-+ enum xradio_link_status status;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ enum xradio_link_status prev_status;
-+#endif
-+ u8 mac[ETH_ALEN];
-+ u8 buffered[XRADIO_MAX_TID];
-+ struct sk_buff_head rx_queue;
-+};
-+
-+#if defined(ROAM_OFFLOAD)
-+struct xradio_testframe {
-+ u8 len;
-+ u8 *data;
-+};
-+#endif
-+
-+struct xradio_common {
-+ struct xradio_debug_common *debug;
-+ struct xradio_queue tx_queue[AC_QUEUE_NUM];
-+ struct xradio_queue_stats tx_queue_stats;
-+
-+ struct ieee80211_hw *hw;
-+ struct mac_address addresses[XRWL_MAX_VIFS];
-+
-+ /*Will be a pointer to a list of VIFs - Dynamically allocated */
-+ struct ieee80211_vif *vif_list[XRWL_MAX_VIFS];
-+ atomic_t num_vifs;
-+ spinlock_t vif_list_lock;
-+ u32 if_id_slot;
-+ struct device *pdev;
-+ struct workqueue_struct *workqueue;
-+
-+ struct mutex conf_mutex;
-+
-+ struct sdio_func *sdio_func;
-+ int driver_ready;
-+
-+ /* HW/FW type (HIF_...) */
-+ int hw_type;
-+ int hw_revision;
-+ int fw_revision;
-+
-+ /* firmware/hardware info */
-+ unsigned int tx_hdr_len;
-+
-+ /* Radio data */
-+ int output_power;
-+ int noise;
-+
-+ /* calibration, output power limit and rssi<->dBm conversation data */
-+
-+ /* BBP/MAC state */
-+ const struct firmware *sdd;
-+ struct ieee80211_rate *rates;
-+ struct ieee80211_rate *mcs_rates;
-+ u8 mac_addr[ETH_ALEN];
-+ /*TODO:COMBO: To be made per VIFF after mac80211 support */
-+ struct ieee80211_channel *channel;
-+ int channel_switch_in_progress;
-+ wait_queue_head_t channel_switch_done;
-+ u8 channel_changed; //add by yangfh 2015-5-15 16:57:38.
-+ u8 long_frame_max_tx_count;
-+ u8 short_frame_max_tx_count;
-+ /* TODO:COMBO: According to Hong aggregation will happen per VIFF.
-+ * Keeping in common structure for the time being. Will be moved to VIFF
-+ * after the mechanism is clear */
-+ u8 ba_tid_mask;
-+ int ba_acc; /*TODO: Same as above */
-+ int ba_cnt; /*TODO: Same as above */
-+ int ba_cnt_rx; /*TODO: Same as above */
-+ int ba_acc_rx; /*TODO: Same as above */
-+ int ba_hist; /*TODO: Same as above */
-+ struct timer_list ba_timer;/*TODO: Same as above */
-+ spinlock_t ba_lock; /*TODO: Same as above */
-+ bool ba_ena; /*TODO: Same as above */
-+ struct work_struct ba_work; /*TODO: Same as above */
-+ struct xradio_pm_state pm_state;
-+ bool is_BT_Present;
-+ bool is_go_thru_go_neg;
-+ u8 conf_listen_interval;
-+
-+ /* BH */
-+ atomic_t bh_tx;
-+ atomic_t bh_term;
-+ atomic_t bh_suspend;
-+ struct task_struct *bh_thread;
-+ int bh_error;
-+ wait_queue_head_t bh_wq;
-+ wait_queue_head_t bh_evt_wq;
-+
-+
-+ int buf_id_tx; /* byte */
-+ int buf_id_rx; /* byte */
-+ int wsm_rx_seq; /* byte */
-+ int wsm_tx_seq; /* byte */
-+ int hw_bufs_used;
-+ int hw_bufs_used_vif[XRWL_MAX_VIFS];
-+ struct sk_buff *skb_cache;
-+ struct sk_buff *skb_reserved;
-+ int skb_resv_len;
-+ bool powersave_enabled;
-+ bool device_can_sleep;
-+ /* Keep xradio awake (WUP = 1) 1 second after each scan to avoid
-+ * FW issue with sleeping/waking up. */
-+ atomic_t recent_scan;
-+ long connet_time[XRWL_MAX_VIFS];
-+#ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
-+ atomic_t suspend_state;
-+#endif
-+
-+ /* WSM */
-+ struct wsm_caps wsm_caps;
-+ struct mutex wsm_cmd_mux;
-+ struct wsm_buf wsm_cmd_buf;
-+ struct wsm_cmd wsm_cmd;
-+ wait_queue_head_t wsm_cmd_wq;
-+ wait_queue_head_t wsm_startup_done;
-+ struct semaphore tx_lock_sem;
-+ atomic_t tx_lock;
-+ u32 pending_frame_id;
-+
-+ /* WSM debug */
-+ u32 query_packetID;
-+ atomic_t query_cnt;
-+ struct work_struct query_work; /* for query packet */
-+
-+ /* Scan status */
-+ struct xradio_scan scan;
-+
-+ /* TX/RX */
-+ unsigned long rx_timestamp;
-+
-+ /* WSM events */
-+ spinlock_t event_queue_lock;
-+ struct list_head event_queue;
-+ struct work_struct event_handler;
-+
-+ /* TX rate policy cache */
-+ struct tx_policy_cache tx_policy_cache;
-+ struct work_struct tx_policy_upload_work;
-+ atomic_t upload_count;
-+
-+ /* cryptographic engine information */
-+
-+ /* bit field of glowing LEDs */
-+ u16 softled_state;
-+
-+ /* statistics */
-+ struct ieee80211_low_level_stats stats;
-+
-+ struct xradio_ht_oper ht_oper;
-+ int tx_burst_idx;
-+
-+ struct ieee80211_iface_limit if_limits1[2];
-+ struct ieee80211_iface_limit if_limits2[2];
-+ struct ieee80211_iface_limit if_limits3[2];
-+ struct ieee80211_iface_combination if_combs[3];
-+
-+ struct mutex wsm_oper_lock;
-+ struct delayed_work rem_chan_timeout;
-+ atomic_t remain_on_channel;
-+ int roc_if_id;
-+ u64 roc_cookie;
-+ wait_queue_head_t offchannel_wq;
-+ u16 offchannel_done;
-+ u16 prev_channel;
-+ int if_id_selected;
-+ u32 key_map;
-+ struct wsm_add_key keys[WSM_KEY_MAX_INDEX + 1];
-+#ifdef MCAST_FWDING
-+ struct wsm_buf wsm_release_buf[WSM_MAX_BUF];
-+ u8 buf_released;
-+#endif
-+#ifdef ROAM_OFFLOAD
-+ u8 auto_scanning;
-+ u8 frame_rcvd;
-+ u8 num_scanchannels;
-+ u8 num_2g_channels;
-+ u8 num_5g_channels;
-+ struct wsm_scan_ch scan_channels[48];
-+ struct sk_buff *beacon;
-+ struct sk_buff *beacon_bkp;
-+ struct xradio_testframe testframe;
-+#endif /*ROAM_OFFLOAD*/
-+
-+ u8 connected_sta_cnt;
-+ u16 vif0_throttle;
-+ u16 vif1_throttle;
-+};
-+
-+/* Virtual Interface State. One copy per VIF */
-+struct xradio_vif {
-+ atomic_t enabled;
-+ spinlock_t vif_lock;
-+ int if_id;
-+ /*TODO: Split into Common and VIF parts */
-+ struct xradio_debug_priv *debug;
-+ /* BBP/MAC state */
-+ u8 bssid[ETH_ALEN];
-+ struct wsm_edca_params edca;
-+ struct wsm_tx_queue_params tx_queue_params;
-+ struct wsm_association_mode association_mode;
-+ struct wsm_set_bss_params bss_params;
-+ struct wsm_set_pm powersave_mode;
-+ struct wsm_set_pm firmware_ps_mode;
-+ int power_set_true;
-+ int user_power_set_true;
-+ u8 user_pm_mode;
-+ int cqm_rssi_thold;
-+ unsigned cqm_rssi_hyst;
-+ unsigned cqm_tx_failure_thold;
-+ unsigned cqm_tx_failure_count;
-+ bool cqm_use_rssi;
-+ int cqm_link_loss_count;
-+ int cqm_beacon_loss_count;
-+ int mode;
-+ bool enable_beacon;
-+ int beacon_int;
-+ size_t ssid_length;
-+ u8 ssid[IEEE80211_MAX_SSID_LEN];
-+#ifdef HIDDEN_SSID
-+ bool hidden_ssid;
-+#endif
-+ bool listening;
-+ struct wsm_rx_filter rx_filter;
-+ struct wsm_beacon_filter_table bf_table;
-+ struct wsm_beacon_filter_control bf_control;
-+ struct wsm_multicast_filter multicast_filter;
-+ bool has_multicast_subscription;
-+ struct wsm_broadcast_addr_filter broadcast_filter;
-+ bool disable_beacon_filter;
-+ struct wsm_arp_ipv4_filter filter4;
-+ struct work_struct update_filtering_work;
-+ struct work_struct set_beacon_wakeup_period_work;
-+ struct xradio_pm_state_vif pm_state_vif;
-+ /*TODO: Add support in mac80211 for psmode info per VIF */
-+ struct wsm_p2p_ps_modeinfo p2p_ps_modeinfo;
-+ struct wsm_uapsd_info uapsd_info;
-+ bool setbssparams_done;
-+ u32 listen_interval;
-+ u32 erp_info;
-+ bool powersave_enabled;
-+
-+ /* WSM Join */
-+ enum xradio_join_status join_status;
-+ u8 join_bssid[ETH_ALEN];
-+ struct work_struct join_work;
-+ struct delayed_work join_timeout;
-+ struct work_struct unjoin_work;
-+ struct work_struct offchannel_work;
-+ int join_dtim_period;
-+ atomic_t delayed_unjoin;
-+
-+ /* Security */
-+ s8 wep_default_key_id;
-+ struct work_struct wep_key_work;
-+ unsigned long rx_timestamp;
-+ u32 cipherType;
-+
-+
-+ /* AP powersave */
-+ u32 link_id_map;
-+ u32 max_sta_ap_mode;
-+ u32 link_id_after_dtim;
-+ u32 link_id_uapsd;
-+ u32 link_id_max;
-+ u32 wsm_key_max_idx;
-+ struct xradio_link_entry link_id_db[MAX_STA_IN_AP_MODE];
-+ struct work_struct link_id_work;
-+ struct delayed_work link_id_gc_work;
-+ u32 sta_asleep_mask;
-+ u32 pspoll_mask;
-+ bool aid0_bit_set;
-+ spinlock_t ps_state_lock;
-+ bool buffered_multicasts;
-+ bool tx_multicast;
-+ u8 last_tim[8]; //for softap dtim, add by yangfh
-+ struct work_struct set_tim_work;
-+ struct delayed_work set_cts_work;
-+ struct work_struct multicast_start_work;
-+ struct work_struct multicast_stop_work;
-+ struct timer_list mcast_timeout;
-+
-+ /* CQM Implementation */
-+ struct delayed_work bss_loss_work;
-+ struct delayed_work connection_loss_work;
-+ struct work_struct tx_failure_work;
-+ int delayed_link_loss;
-+ spinlock_t bss_loss_lock;
-+ int bss_loss_status;
-+ int bss_loss_confirm_id;
-+
-+ struct ieee80211_vif *vif;
-+ struct xradio_common *hw_priv;
-+ struct ieee80211_hw *hw;
-+
-+ /* ROC implementation */
-+ struct delayed_work pending_offchanneltx_work;
-+#if defined(CONFIG_XRADIO_USE_EXTENSIONS)
-+ /* Workaround for WFD testcase 6.1.10*/
-+ struct work_struct linkid_reset_work;
-+ u8 action_frame_sa[ETH_ALEN];
-+ u8 action_linkid;
-+#endif
-+ bool htcap;
-+#ifdef AP_HT_CAP_UPDATE
-+ u16 ht_oper;
-+ struct work_struct ht_oper_update_work;
-+#endif
-+
-+#ifdef AP_HT_COMPAT_FIX
-+ u16 ht_compat_cnt;
-+ u16 ht_compat_det;
-+#endif
-+};
-+struct xradio_sta_priv {
-+ int link_id;
-+ struct xradio_vif *priv;
-+};
-+enum xradio_data_filterid {
-+ IPV4ADDR_FILTER_ID = 0,
-+};
-+
-+/* Datastructure for LLC-SNAP HDR */
-+#define P80211_OUI_LEN 3
-+struct ieee80211_snap_hdr {
-+ u8 dsap; /* always 0xAA */
-+ u8 ssap; /* always 0xAA */
-+ u8 ctrl; /* always 0x03 */
-+ u8 oui[P80211_OUI_LEN]; /* organizational universal id */
-+} __packed;
-+
-+
-+#ifdef TES_P2P_0002_ROC_RESTART
-+extern s32 TES_P2P_0002_roc_dur;
-+extern s32 TES_P2P_0002_roc_sec;
-+extern s32 TES_P2P_0002_roc_usec;
-+extern u32 TES_P2P_0002_packet_id;
-+extern u32 TES_P2P_0002_state;
-+
-+#define TES_P2P_0002_STATE_IDLE 0x00
-+#define TES_P2P_0002_STATE_SEND_RESP 0x01
-+#define TES_P2P_0002_STATE_GET_PKTID 0x02
-+#endif
-+
-+/* debug.h must be here because refer to struct xradio_vif and
-+ struct xradio_common.*/
-+#include "debug.h"
-+
-+/*******************************************************
-+ interfaces for operations of vif.
-+********************************************************/
-+static inline
-+struct xradio_common *xrwl_vifpriv_to_hwpriv(struct xradio_vif *priv)
-+{
-+ return priv->hw_priv;
-+}
-+static inline
-+struct xradio_vif *xrwl_get_vif_from_ieee80211(struct ieee80211_vif *vif)
-+{
-+ return (struct xradio_vif *)vif->drv_priv;
-+}
-+
-+static inline
-+struct xradio_vif *xrwl_hwpriv_to_vifpriv(struct xradio_common *hw_priv,
-+ int if_id)
-+{
-+ struct xradio_vif *vif;
-+
-+ if (WARN_ON((-1 == if_id) || (if_id > XRWL_MAX_VIFS)))
-+ return NULL;
-+ /* TODO:COMBO: During scanning frames can be received
-+ * on interface ID 3 */
-+ spin_lock(&hw_priv->vif_list_lock);
-+ if (!hw_priv->vif_list[if_id]) {
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ return NULL;
-+ }
-+
-+ vif = xrwl_get_vif_from_ieee80211(hw_priv->vif_list[if_id]);
-+ WARN_ON(!vif);
-+ if (vif)
-+ spin_lock(&vif->vif_lock);
-+ spin_unlock(&hw_priv->vif_list_lock);
-+ return vif;
-+}
-+
-+static inline
-+struct xradio_vif *__xrwl_hwpriv_to_vifpriv(struct xradio_common *hw_priv,
-+ int if_id)
-+{
-+ WARN_ON((-1 == if_id) || (if_id > XRWL_MAX_VIFS));
-+ /* TODO:COMBO: During scanning frames can be received
-+ * on interface ID 3 */
-+ if (!hw_priv->vif_list[if_id]) {
-+ return NULL;
-+ }
-+
-+ return xrwl_get_vif_from_ieee80211(hw_priv->vif_list[if_id]);
-+}
-+
-+static inline
-+struct xradio_vif *xrwl_get_activevif(struct xradio_common *hw_priv)
-+{
-+ return xrwl_hwpriv_to_vifpriv(hw_priv, ffs(hw_priv->if_id_slot)-1);
-+}
-+
-+static inline bool is_hardware_xradio(struct xradio_common *hw_priv)
-+{
-+ return (hw_priv->hw_revision == XR819_HW_REV0);
-+}
-+
-+static inline int xrwl_get_nr_hw_ifaces(struct xradio_common *hw_priv)
-+{
-+ switch(hw_priv->hw_revision) {
-+ case XR819_HW_REV0:
-+ default:
-+ return 1;
-+ }
-+}
-+
-+#define xradio_for_each_vif(_hw_priv, _priv, _i) \
-+ for( \
-+ _i = 0; \
-+ (_i < XRWL_MAX_VIFS) \
-+ && ((_priv = _hw_priv->vif_list[_i] ? \
-+ xrwl_get_vif_from_ieee80211(_hw_priv->vif_list[_i]) : NULL),1); \
-+ _i++ \
-+ )
-+
-+/*******************************************************
-+ interfaces for operations of queue.
-+********************************************************/
-+static inline void xradio_tx_queues_lock(struct xradio_common *hw_priv)
-+{
-+ int i;
-+ for (i = 0; i < 4; ++i)
-+ xradio_queue_lock(&hw_priv->tx_queue[i]);
-+}
-+
-+static inline void xradio_tx_queues_unlock(struct xradio_common *hw_priv)
-+{
-+ int i;
-+ for (i = 0; i < 4; ++i)
-+ xradio_queue_unlock(&hw_priv->tx_queue[i]);
-+}
-+
-+#endif /* XRADIO_H */
diff --git a/patch/kernel/sunxi-legacy/xxx-0001-network-audio-orangepiwin-dts.patch b/patch/kernel/sunxi-legacy/xxx-0001-network-audio-orangepiwin-dts.patch.disabled
similarity index 100%
rename from patch/kernel/sunxi-legacy/xxx-0001-network-audio-orangepiwin-dts.patch
rename to patch/kernel/sunxi-legacy/xxx-0001-network-audio-orangepiwin-dts.patch.disabled
diff --git a/patch/kernel/sunxi-legacy/xxx-opi-win-bluetooth.patch b/patch/kernel/sunxi-legacy/xxx-opi-win-bluetooth.patch
deleted file mode 100644
index a77db4f07..000000000
--- a/patch/kernel/sunxi-legacy/xxx-opi-win-bluetooth.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
-index b4ce2e056..63b9e7433 100644
---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
-+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
-@@ -94,6 +94,8 @@
- wifi_pwrseq: wifi_pwrseq {
- compatible = "mmc-pwrseq-simple";
- reset-gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
-+ clocks = <&rtc 1>;
-+ clock-names = "ext_clock";
- };
-
- hdmi-connector {
-@@ -191,6 +193,14 @@
- bus-width = <4>;
- non-removable;
- status = "okay";
-+
-+ brcmf: wifi@1 {
-+ reg = <1>;
-+ compatible = "brcm,bcm4329-fmac";
-+ interrupt-parent = <&r_pio>;
-+ interrupts = <0 7 IRQ_TYPE_LEVEL_LOW>; /* PL7 */
-+ interrupt-names = "host-wake";
-+ };
- };
-
- &ohci0 {
-@@ -363,7 +373,20 @@
- &uart1 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
-+ uart-has-rtscts;
- status = "okay";
-+
-+ bluetooth {
-+ compatible = "brcm,bcm43438-bt";
-+ max-speed = <1500000>;
-+ clocks = <&rtc 1>;
-+ clock-names = "lpo";
-+ vbat-supply = <®_dldo2>;
-+ vddio-supply = <®_dldo4>;
-+ device-wakeup-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */
-+ host-wakeup-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* PL5 */
-+ shutdown-gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
-+ };
- };
-
- &usb_otg {
-@@ -375,4 +398,4 @@
- usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */
- usb1_vbus-supply = <®_usb1_vbus>;
- status = "okay";
--};
-\ No newline at end of file
-+};