]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorDavid S. Miller <davem@davemloft.net>
Wed, 1 Oct 2008 13:12:56 +0000 (06:12 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 1 Oct 2008 13:12:56 +0000 (06:12 -0700)
Conflicts:

drivers/net/wireless/ath9k/core.c
drivers/net/wireless/ath9k/main.c
net/core/dev.c

15 files changed:
1  2 
Documentation/feature-removal-schedule.txt
MAINTAINERS
drivers/net/bnx2.h
drivers/net/e100.c
drivers/net/forcedeth.c
drivers/net/wireless/ath9k/core.c
drivers/net/wireless/ath9k/core.h
drivers/net/wireless/ath9k/main.c
drivers/net/wireless/ath9k/xmit.c
drivers/net/wireless/b43/rfkill.c
include/net/netlink.h
net/core/dev.c
net/ipv4/tcp_ipv4.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c

index c93fcdec246d9f9f36da53a53da383a54020b382,83c88cae1eda446a12562a34f2c10f1a3f8cf5c2..d0f22fac55daf4c3af9a23ab4ff7135b18b8b3b4
@@@ -6,24 -6,6 +6,24 @@@ be removed from this file
  
  ---------------------------
  
 +What: old static regulatory information and ieee80211_regdom module parameter
 +When: 2.6.29
 +Why:  The old regulatory infrastructure has been replaced with a new one
 +      which does not require statically defined regulatory domains. We do
 +      not want to keep static regulatory domains in the kernel due to the
 +      the dynamic nature of regulatory law and localization. We kept around
 +      the old static definitions for the regulatory domains of:
 +              * US
 +              * JP
 +              * EU
 +      and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was
 +      set. We also kept around the ieee80211_regdom module parameter in case
 +      some applications were relying on it. Changing regulatory domains
 +      can now be done instead by using nl80211, as is done with iw.
 +Who:  Luis R. Rodriguez <lrodriguez@atheros.com>
 +
 +---------------------------
 +
  What: dev->power.power_state
  When: July 2007
  Why:  Broken design for runtime control over driver power states, confusing
@@@ -340,3 -322,11 +340,11 @@@ Why:  Accounting can now be enabled/dis
        controlled by a kernel/module/sysfs/sysctl parameter.
  Who:  Krzysztof Piotr Oledzki <ole@ans.pl>
  
+ ---------------------------
+ What: ide-scsi (BLK_DEV_IDESCSI)
+ When: 2.6.29
+ Why:  The 2.6 kernel supports direct writing to ide CD drives, which
+       eliminates the need for ide-scsi. The new method is more
+       efficient in every way.
+ Who:  FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
diff --combined MAINTAINERS
index c29b420fc1ca3576d46d70a5eef239f8f131071a,3596d17822641bd63a0536026107d0f402f5a93b..e6aa6aa789f54ac1b5d626297851502b49f3baec
@@@ -271,20 -271,20 +271,20 @@@ W:      http://www.lesswatts.org/projects/ac
  S:    Supported
  
  ACPI WMI DRIVER
- P:      Carlos Corbacho
- M:      carlos@strangeworlds.co.uk
- L:      linux-acpi@vger.kernel.org
- W:      http://www.lesswatts.org/projects/acpi/
- S:      Maintained
+ P:    Carlos Corbacho
+ M:    carlos@strangeworlds.co.uk
+ L:    linux-acpi@vger.kernel.org
+ W:    http://www.lesswatts.org/projects/acpi/
+ S:    Maintained
  
  AD1889 ALSA SOUND DRIVER
- P:     Kyle McMartin
- M:     kyle@mcmartin.ca
- P:     Thibaut Varene
- M:     T-Bone@parisc-linux.org
- W:     http://wiki.parisc-linux.org/AD1889
- L:     linux-parisc@vger.kernel.org
- S:     Maintained
+ P:    Kyle McMartin
+ M:    kyle@mcmartin.ca
+ P:    Thibaut Varene
+ M:    T-Bone@parisc-linux.org
+ W:    http://wiki.parisc-linux.org/AD1889
+ L:    linux-parisc@vger.kernel.org
+ S:    Maintained
  
  ADM1025 HARDWARE MONITOR DRIVER
  P:    Jean Delvare
@@@ -473,11 -473,11 +473,11 @@@ L:      linux-arm-kernel@lists.arm.linux.org
  S:    Maintained
  
  ARM/ATMEL AT91RM9200 ARM ARCHITECTURE
- P:      Andrew Victor
- M:      linux@maxim.org.za
- L:      linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
- W:      http://maxim.org.za/at91_26.html
- S:      Maintained
+ P:    Andrew Victor
+ M:    linux@maxim.org.za
+ L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+ W:    http://maxim.org.za/at91_26.html
+ S:    Maintained
  
  ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
  P:    Lennert Buytenhek
@@@ -532,10 -532,10 +532,10 @@@ L:      linux-arm-kernel@lists.arm.linux.org
  S:    Maintained
  
  ARM/HP JORNADA 7XX MACHINE SUPPORT
- P:      Kristoffer Ericson
- M:      kristoffer.ericson@gmail.com
- W:      www.jlime.com
- S:      Maintained
+ P:    Kristoffer Ericson
+ M:    kristoffer.ericson@gmail.com
+ W:    www.jlime.com
+ S:    Maintained
  
  ARM/INTEL IOP32X ARM ARCHITECTURE
  P:    Lennert Buytenhek
@@@ -1017,7 -1017,7 +1017,7 @@@ T:      git kernel.org:/pub/scm/linux/kernel
  S:    Maintained
  
  CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
- P:    Jonathan Corbet
+ P:    Jonathan Corbet
  M:    corbet@lwn.net
  L:    video4linux-list@redhat.com
  S:    Maintained
@@@ -1048,13 -1048,6 +1048,13 @@@ L:    cbe-oss-dev@ozlabs.or
  W:    http://www.ibm.com/developerworks/power/cell/
  S:    Supported
  
 +CISCO 10G ETHERNET DRIVER
 +P:    Scott Feldman
 +M:    scofeldm@cisco.com
 +P:    Joe Eykholt
 +M:    jeykholt@cisco.com
 +S:    Supported
 +
  CFAG12864B LCD DRIVER
  P:    Miguel Ojeda Sandonis
  M:    miguel.ojeda.sandonis@gmail.com
@@@ -1366,7 -1359,7 +1366,7 @@@ P:      Digi International, In
  M:    Eng.Linux@digi.com
  L:    Eng.Linux@digi.com
  W:    http://www.digi.com
- S:    Orphaned
+ S:    Orphan
  
  DIRECTORY NOTIFICATION
  P:    Stephen Rothwell
@@@ -1430,12 -1423,12 +1430,12 @@@ L:   linux-acpi@vger.kernel.or
  S:    Supported
  
  DOCUMENTATION (/Documentation directory)
- P:     Michael Kerrisk
- M:     mtk.manpages@gmail.com
- P:     Randy Dunlap
- M:     rdunlap@xenotime.net
- L:     linux-doc@vger.kernel.org
- S:     Maintained
+ P:    Michael Kerrisk
+ M:    mtk.manpages@gmail.com
+ P:    Randy Dunlap
+ M:    rdunlap@xenotime.net
+ L:    linux-doc@vger.kernel.org
+ S:    Maintained
  
  DOUBLETALK DRIVER
  P:    James R. Van Zandt
@@@ -1466,7 -1459,7 +1466,7 @@@ S:      Maintaine
  DVB SUBSYSTEM AND DRIVERS
  P:    LinuxTV.org Project
  M:    v4l-dvb-maintainer@linuxtv.org
- L:    linux-dvb@linuxtv.org (subscription required)
+ L:    linux-dvb@linuxtv.org (subscription required)
  W:    http://linuxtv.org/
  T:    git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
  S:    Maintained
@@@ -1804,7 -1797,7 +1804,7 @@@ FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-
  P:    Rik Faith
  M:    faith@cs.unc.edu
  L:    linux-scsi@vger.kernel.org
- S:    Odd fixes (e.g., new signatures)
+ S:    Odd Fixes (e.g., new signatures)
  
  GDT SCSI DISK ARRAY CONTROLLER DRIVER
  P:    Achim Leubner
@@@ -1845,10 -1838,10 +1845,10 @@@ S:   Maintaine
  HARDWARE MONITORING
  L:    lm-sensors@lm-sensors.org
  W:    http://www.lm-sensors.org/
- S:    Orphaned
+ S:    Orphan
  
  HARDWARE RANDOM NUMBER GENERATOR CORE
- S:    Orphaned
+ S:    Orphan
  
  HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
  P:    Robert Love
@@@ -1991,7 -1984,7 +1991,7 @@@ S:      Maintaine
  I2C/SMBUS STUB DRIVER
  P:    Mark M. Hoffman
  M:    mhoffman@lightlink.com
- L:    lm-sensors@lm-sensors.org
+ L:    i2c@lm-sensors.org
  S:    Maintained
  
  I2C SUBSYSTEM
@@@ -2115,7 -2108,7 +2115,7 @@@ M:      rolandd@cisco.co
  P:    Sean Hefty
  M:    sean.hefty@intel.com
  P:    Hal Rosenstock
- M:    hal.rosenstock@gmail.com 
+ M:    hal.rosenstock@gmail.com
  L:    general@lists.openfabrics.org
  W:    http://www.openib.org/
  T:    git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
@@@ -2328,12 -2321,6 +2328,12 @@@ L:    video4linux-list@redhat.co
  W:    http://www.ivtvdriver.org
  S:    Maintained
  
 +JME NETWORK DRIVER
 +P:    Guo-Fu Tseng
 +M:    cooldavid@cooldavid.org
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +
  JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
  P:    David Woodhouse
  M:    dwmw2@infradead.org
@@@ -2709,17 -2696,17 +2709,17 @@@ S:   Maintaine
  
  MARVELL YUKON / SYSKONNECT DRIVER
  P:    Mirko Lindner
- M:    mlindner@syskonnect.de
+ M:    mlindner@syskonnect.de
  P:    Ralph Roesler
- M:    rroesler@syskonnect.de
- W:    http://www.syskonnect.com
- S:    Supported
+ M:    rroesler@syskonnect.de
+ W:    http://www.syskonnect.com
+ S:    Supported
  
  MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
  P:    Michael Kerrisk
  M:    mtk.manpages@gmail.com
- W:     http://www.kernel.org/doc/man-pages
- S:     Supported
+ W:    http://www.kernel.org/doc/man-pages
+ S:    Supported
  
  MARVELL LIBERTAS WIRELESS DRIVER
  P:    Dan Williams
@@@ -2748,7 -2735,7 +2748,7 @@@ S:      Maintaine
  MEGARAID SCSI DRIVERS
  P:    Neela Syam Kolli
  M:    megaraidlinux@lsi.com
S:    linux-scsi@vger.kernel.org
L:    linux-scsi@vger.kernel.org
  W:    http://megaraid.lsilogic.com
  S:    Maintained
  
@@@ -2866,7 -2853,7 +2866,7 @@@ MULTIMEDIA CARD (MMC) ETC. OVER SP
  P:    David Brownell
  M:    dbrownell@users.sourceforge.net
  L:    linux-kernel@vger.kernel.org
- S:    Odd fixes
+ S:    Odd Fixes
  
  MULTISOUND SOUND DRIVER
  P:    Andrew Veliath
@@@ -2880,10 -2867,10 +2880,10 @@@ L:   linux-kernel@vger.kernel.or
  S:    Maintained
  
  MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
- P:     Felipe Balbi
- M:     felipe.balbi@nokia.com
- L:     linux-usb@vger.kernel.org
- S:     Maintained
+ P:    Felipe Balbi
+ M:    felipe.balbi@nokia.com
+ L:    linux-usb@vger.kernel.org
+ S:    Maintained
  
  MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
  P:    Andrew Gallatin
@@@ -2895,7 -2882,7 +2895,7 @@@ W:      http://www.myri.com/scs/download-Myr
  S:    Supported
  
  NATSEMI ETHERNET DRIVER (DP8381x)
- P:    Tim Hockin
+ P:    Tim Hockin
  M:    thockin@hockin.org
  S:    Maintained
  
@@@ -3114,7 -3101,7 +3114,7 @@@ M:      laforge@gnumonks.or
  S:    Maintained
  
  OMNIVISION OV7670 SENSOR DRIVER
- P:    Jonathan Corbet
+ P:    Jonathan Corbet
  M:    corbet@lwn.net
  L:    video4linux-list@redhat.com
  S:    Maintained
@@@ -3224,7 -3211,7 +3224,7 @@@ T:      git kernel.org:/pub/scm/linux/kernel
  S:    Supported
  
  PCI HOTPLUG CORE
- P:    Kristen Carlson Accardi
+ P:    Kristen Carlson Accardi
  M:    kristen.c.accardi@intel.com
  S:    Supported
  
@@@ -3398,13 -3385,6 +3398,13 @@@ M:    linux-driver@qlogic.co
  L:    netdev@vger.kernel.org
  S:    Supported
  
 +QLOGIC QLGE 10Gb ETHERNET DRIVER
 +P:    Ron Mercer
 +M:    linux-driver@qlogic.com
 +M:    ron.mercer@qlogic.com
 +L:    netdev@vger.kernel.org
 +S:    Supported
 +
  QNX4 FILESYSTEM
  P:    Anders Larsen
  M:    al@alarsen.net
@@@ -3670,7 -3650,7 +3670,7 @@@ M:      jmorris@namei.or
  P:    Eric Paris
  M:    eparis@parisplace.org
  L:    linux-kernel@vger.kernel.org (kernel issues)
- L:    selinux@tycho.nsa.gov (subscribers-only, general discussion)
+ L:    selinux@tycho.nsa.gov (subscribers-only, general discussion)
  W:    http://www.nsa.gov/selinux
  S:    Supported
  
@@@ -3746,7 -3726,7 +3746,7 @@@ S:      Maintaine
  SIS 96X I2C/SMBUS DRIVER
  P:    Mark M. Hoffman
  M:    mhoffman@lightlink.com
- L:    lm-sensors@lm-sensors.org
+ L:    i2c@lm-sensors.org
  S:    Maintained
  
  SIS FRAMEBUFFER DRIVER
@@@ -3788,10 -3768,10 +3788,10 @@@ M:   bn@niasdigital.co
  S:    Maintained
  
  SOC-CAMERA V4L2 SUBSYSTEM
- P:     Guennadi Liakhovetski
- M:     g.liakhovetski@gmx.de
- L:     video4linux-list@redhat.com
- S:     Maintained
+ P:    Guennadi Liakhovetski
+ M:    g.liakhovetski@gmx.de
+ L:    video4linux-list@redhat.com
+ S:    Maintained
  
  SOFTWARE RAID (Multiple Disks) SUPPORT
  P:    Ingo Molnar
@@@ -3853,11 -3833,12 +3853,12 @@@ S:   Maintaine
  
  SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
  P:    Liam Girdwood
- M:    liam.girdwood@wolfsonmicro.com
+ M:    lrg@slimlogic.co.uk
  P:    Mark Brown
  M:    broonie@opensource.wolfsonmicro.com
  T:    git opensource.wolfsonmicro.com/linux-2.6-asoc
  L:    alsa-devel@alsa-project.org (subscribers-only)
+ W:    http://alsa-project.org/main/index.php/ASoC
  S:    Supported
  
  SPI SUBSYSTEM
@@@ -3945,7 -3926,7 +3946,7 @@@ S:      Maintaine
  
  STARMODE RADIO IP (STRIP) PROTOCOL DRIVER
  W:    http://mosquitonet.Stanford.EDU/strip.html
- S:    Unsupported ?
+ S:    Orphan
  
  STRADIS MPEG-2 DECODER DRIVER
  P:    Nathan Laredo
@@@ -4026,9 -4007,9 +4027,9 @@@ T:      git repo.or.cz/linux-2.6/linux-acpi-
  S:    Maintained
  
  TI FLASH MEDIA INTERFACE DRIVER
- P:      Alex Dubov
- M:      oakad@yahoo.com
- S:      Maintained
+ P:    Alex Dubov
+ M:    oakad@yahoo.com
+ S:    Maintained
  
  TI OMAP MMC INTERFACE DRIVER
  P:    Carlos Aguiar, Anderson Briglia and Syed Khasim
@@@ -4174,13 -4155,13 +4175,13 @@@ USB BLOCK DRIVER (UB ub
  P:    Pete Zaitcev
  M:    zaitcev@redhat.com
  L:    linux-kernel@vger.kernel.org
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Supported
  
  USB CDC ETHERNET DRIVER
  P:    Greg Kroah-Hartman
  M:    greg@kroah.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  W:    http://www.kroah.com/linux-usb/
  
@@@ -4207,13 -4188,13 +4208,13 @@@ S:   Maintaine
  USB EHCI DRIVER
  P:    David Brownell
  M:    dbrownell@users.sourceforge.net
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Odd Fixes
  
  USB ET61X[12]51 DRIVER
  P:    Luca Risolia
  M:    luca.risolia@studio.unibo.it
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  L:    video4linux-list@redhat.com
  W:    http://www.linux-projects.org
  S:    Maintained
  USB GADGET/PERIPHERAL SUBSYSTEM
  P:    David Brownell
  M:    dbrownell@users.sourceforge.net
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  W:    http://www.linux-usb.org/gadget
  S:    Maintained
  
  USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
  P:    Jiri Kosina
  M:    jkosina@suse.cz
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  T:    git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
  S:    Maintained
  
  USB ISP116X DRIVER
  P:    Olav Kongas
  M:    ok@artecdesign.ee
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  
  USB KAWASAKI LSI DRIVER
  P:    Oliver Neukum
  M:    oliver@neukum.name
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  
  USB MASS STORAGE DRIVER
  P:    Matthew Dharm
  M:    mdharm-usb@one-eyed-alien.net
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  L:    usb-storage@lists.one-eyed-alien.net
  S:    Maintained
  W:    http://www.one-eyed-alien.net/~mdharm/linux-usb/
  USB OHCI DRIVER
  P:    David Brownell
  M:    dbrownell@users.sourceforge.net
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Odd Fixes
  
  USB OPTION-CARD DRIVER
  P:    Matthias Urlichs
  M:    smurf@smurf.noris.de
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  
  USB OV511 DRIVER
  P:    Mark McClelland
  M:    mmcclell@bigfoot.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  W:    http://alpha.dyndns.org/ov511/
  S:    Maintained
  
  USB PEGASUS DRIVER
  P:    Petko Manolov
  M:    petkan@users.sourceforge.net
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  L:    netdev@vger.kernel.org
  W:    http://pegasus2.sourceforge.net/
  S:    Maintained
  USB PRINTER DRIVER (usblp)
  P:    Pete Zaitcev
  M:    zaitcev@redhat.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Supported
  
  USB RTL8150 DRIVER
  P:    Petko Manolov
  M:    petkan@users.sourceforge.net
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  L:    netdev@vger.kernel.org
  W:    http://pegasus2.sourceforge.net/
  S:    Maintained
  USB SE401 DRIVER
  P:    Jeroen Vreeken
  M:    pe1rxq@amsat.org
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  W:    http://www.chello.nl/~j.vreeken/se401/
  S:    Maintained
  
  USB SERIAL BELKIN F5U103 DRIVER
  P:    William Greathouse
  M:    wgreathouse@smva.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  
  USB SERIAL CYPRESS M8 DRIVER
  P:    Lonnie Mendez
  M:    dignome@gmail.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  W:    http://geocities.com/i0xox0i
  W:    http://firstlight.net/cvs
@@@ -4324,39 -4305,39 +4325,39 @@@ USB SERIAL DIGI ACCELEPORT DRIVE
  P:    Peter Berger and Al Borchers
  M:    pberger@brimson.com
  M:    alborchers@steinerpoint.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  
  USB SERIAL DRIVER
  P:    Greg Kroah-Hartman
  M:    gregkh@suse.de
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Supported
  
  USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
  P:    Gary Brubaker
  M:    xavyer@ix.netcom.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  
  USB SERIAL KEYSPAN DRIVER
  P:    Greg Kroah-Hartman
  M:    greg@kroah.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  W:    http://www.kroah.com/linux/
  S:    Maintained
  
  USB SERIAL WHITEHEAT DRIVER
  P:    Support Department
  M:    support@connecttech.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  W:    http://www.connecttech.com
  S:    Supported
  
  USB SN9C1xx DRIVER
  P:    Luca Risolia
  M:    luca.risolia@studio.unibo.it
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  L:    video4linux-list@redhat.com
  W:    http://www.linux-projects.org
  S:    Maintained
  USB SUBSYSTEM
  P:    Greg Kroah-Hartman
  M:    gregkh@suse.de
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  W:    http://www.linux-usb.org
  T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
  S:    Supported
  USB UHCI DRIVER
  P:    Alan Stern
  M:    stern@rowland.harvard.edu
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  S:    Maintained
  
  USB "USBNET" DRIVER FRAMEWORK
@@@ -4385,7 -4366,7 +4386,7 @@@ S:      Maintaine
  USB VIDEO CLASS
  P:    Laurent Pinchart
  M:    laurent.pinchart@skynet.be
- L:    linx-uvc-devel@berlios.de
+ L:    linux-uvc-devel@lists.berlios.de
  L:    video4linux-list@redhat.com
  W:    http://linux-uvc.berlios.de
  S:    Maintained
  USB W996[87]CF DRIVER
  P:    Luca Risolia
  M:    luca.risolia@studio.unibo.it
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  L:    video4linux-list@redhat.com
  W:    http://www.linux-projects.org
  S:    Maintained
@@@ -4407,7 -4388,7 +4408,7 @@@ S:      Maintaine
  USB ZC0301 DRIVER
  P:    Luca Risolia
  M:    luca.risolia@studio.unibo.it
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  L:    video4linux-list@redhat.com
  W:    http://www.linux-projects.org
  S:    Maintained
  USB ZD1201 DRIVER
  P:    Jeroen Vreeken
  M:    pe1rxq@amsat.org
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  W:    http://linux-lc100020.sourceforge.net
  S:    Maintained
  
  USB ZR364XX DRIVER
  P:    Antoine Jacquet
  M:    royale@zerezo.com
- L:      linux-usb@vger.kernel.org
+ L:    linux-usb@vger.kernel.org
  L:    video4linux-list@redhat.com
  W:    http://royale.zerezo.com/zr364xx/
  S:    Maintained
diff --combined drivers/net/bnx2.h
index 682b8f07752941eee1bef2f8be92f8533b9047fd,dfacd31f7ed08856cdac5c9c0156f6cef4addd1f..edc7774f2f21312dec2bf155a98c854add82c89f
@@@ -6597,7 -6597,7 +6597,7 @@@ struct flash_spec 
  
  struct bnx2_irq {
        irq_handler_t   handler;
-       u16             vector;
+       unsigned int    vector;
        u8              requested;
        char            name[16];
  };
@@@ -6654,8 -6654,6 +6654,8 @@@ struct bnx2_napi 
        struct bnx2_tx_ring_info        tx_ring;
  };
  
 +#define BNX2_TIMER_INTERVAL                   HZ
 +
  struct bnx2 {
        /* Fields used in the tx and intr/napi performance paths are grouped */
        /* together in the beginning of the structure. */
  
        /* End of fields used in the performance code paths. */
  
 -      char                    *name;
 -
 -      int                     timer_interval;
        int                     current_interval;
        struct                  timer_list timer;
        struct work_struct      reset_task;
diff --combined drivers/net/e100.c
index 7d7dfa512bfae9f20df97d79804353e0b99a168c,5cf78d612c4579ed337e2ed726c19121f656aab7..3d69fae781cf5461949b4d9fccf1e9ce7244249d
@@@ -191,7 -191,7 +191,7 @@@ MODULE_PARM_DESC(use_io, "Force use of 
  #define DPRINTK(nlevel, klevel, fmt, args...) \
        (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
        printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
 -              __FUNCTION__ , ## args))
 +              __func__ , ## args))
  
  #define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
        PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
@@@ -2738,9 -2738,7 +2738,7 @@@ static int __devinit e100_probe(struct 
                nic->flags |= wol_magic;
  
        /* ack any pending wake events, disable PME */
-       err = pci_enable_wake(pdev, 0, 0);
-       if (err)
-               DPRINTK(PROBE, ERR, "Error clearing wake event\n");
+       pci_pme_active(pdev, false);
  
        strcpy(netdev->name, "eth%d");
        if((err = register_netdev(netdev))) {
diff --combined drivers/net/forcedeth.c
index 35e582d3fd2a7588d1b1814bcd00707e0e3e1f29,eeb55ed2152d4377ac69b5a892906439d4cfdca8..cc7328b1552136f0fa7c8e8f5587b61e110f216b
@@@ -337,7 -337,7 +337,7 @@@ enum 
        NvRegMSIXIrqStatus = 0x3f0,
  
        NvRegPowerState2 = 0x600,
 -#define NVREG_POWERSTATE2_POWERUP_MASK                0x0F11
 +#define NVREG_POWERSTATE2_POWERUP_MASK                0x0F15
  #define NVREG_POWERSTATE2_POWERUP_REV_A3      0x0001
  #define NVREG_POWERSTATE2_PHY_RESET           0x0004
  };
@@@ -5643,6 -5643,7 +5643,7 @@@ static int __devinit nv_probe(struct pc
                dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
                dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
                writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
+               printk(KERN_DEBUG "nv_probe: set workaround bit for reversed mac addr\n");
        }
        memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
  
@@@ -5890,14 -5891,12 +5891,12 @@@ static void nv_restore_phy(struct net_d
        }
  }
  
- static void __devexit nv_remove(struct pci_dev *pci_dev)
+ static void nv_restore_mac_addr(struct pci_dev *pci_dev)
  {
        struct net_device *dev = pci_get_drvdata(pci_dev);
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
  
-       unregister_netdev(dev);
        /* special op: write back the misordered MAC address - otherwise
         * the next nv_probe would see a wrong address.
         */
        writel(np->orig_mac[1], base + NvRegMacAddrB);
        writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV,
               base + NvRegTransmitPoll);
+ }
+ static void __devexit nv_remove(struct pci_dev *pci_dev)
+ {
+       struct net_device *dev = pci_get_drvdata(pci_dev);
+       unregister_netdev(dev);
+       nv_restore_mac_addr(pci_dev);
  
        /* restore any phy related changes */
        nv_restore_phy(dev);
@@@ -5975,6 -5983,8 +5983,8 @@@ static void nv_shutdown(struct pci_dev 
        if (netif_running(dev))
                nv_close(dev);
  
+       nv_restore_mac_addr(pdev);
        pci_disable_device(pdev);
        if (system_state == SYSTEM_POWER_OFF) {
                if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled))
index 690f7c56af3d8faa2bc5608b59bad50061539322,87e37bc391454ecdf51921ad16504df28e3f103c..6c433a4d003e688eb7263e28c2a72feae6b365ec
@@@ -21,6 -21,9 +21,6 @@@
  
  static int ath_outdoor;               /* enable outdoor use */
  
 -static const u8 ath_bcast_mac[ETH_ALEN] =
 -    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 -
  static u32 ath_chainmask_sel_up_rssi_thres =
        ATH_CHAINMASK_SEL_UP_RSSI_THRES;
  static u32 ath_chainmask_sel_down_rssi_thres =
@@@ -51,8 -54,10 +51,8 @@@ static void bus_read_cachesize(struct a
   *  Set current operating mode
   *
   *  This function initializes and fills the rate table in the ATH object based
 - *  on the operating mode.  The blink rates are also set up here, although
 - *  they have been superceeded by the ath_led module.
 + *  on the operating mode.
  */
 -
  static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
  {
        const struct ath9k_rate_table *rt;
@@@ -230,7 -235,7 +230,7 @@@ static int ath_setup_channels(struct at
   *  Determine mode from channel flags
   *
   *  This routine will provide the enumerated WIRELESSS_MODE value based
 - *  on the settings of the channel flags.  If ho valid set of flags
 + *  on the settings of the channel flags.  If no valid set of flags
   *  exist, the lowest mode (11b) is selected.
  */
  
@@@ -255,8 -260,7 +255,8 @@@ static enum wireless_mode ath_chan2mode
        else if (chan->chanmode == CHANNEL_G_HT40MINUS)
                return ATH9K_MODE_11NG_HT40MINUS;
  
 -      /* NB: should not get here */
 +      WARN_ON(1); /* should not get here */
 +
        return ATH9K_MODE_11B;
  }
  
@@@ -271,12 -275,14 +271,12 @@@ static int ath_stop(struct ath_softc *s
  {
        struct ath_hal *ah = sc->sc_ah;
  
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %u\n",
 -              __func__, sc->sc_invalid);
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n",
 +              __func__, sc->sc_flags & SC_OP_INVALID);
  
        /*
         * Shutdown the hardware and driver:
         *    stop output from above
 -       *    reset 802.11 state machine
 -       *      (sends station deassoc/deauth frames)
         *    turn off timers
         *    disable interrupts
         *    clear transmit machinery
         * hardware is gone (invalid).
         */
  
 +      if (!(sc->sc_flags & SC_OP_INVALID))
 +              ath9k_hw_set_interrupts(ah, 0);
        ath_draintxq(sc, false);
 -      if (!sc->sc_invalid) {
 +      if (!(sc->sc_flags & SC_OP_INVALID)) {
                ath_stoprecv(sc);
                ath9k_hw_phy_disable(ah);
        } else
        return 0;
  }
  
 -/*
 - *  Start Scan
 - *
 - *  This function is called when starting a channel scan.  It will perform
 - *  power save wakeup processing, set the filter for the scan, and get the
 - *  chip ready to send broadcast packets out during the scan.
 -*/
 -
 -void ath_scan_start(struct ath_softc *sc)
 -{
 -      struct ath_hal *ah = sc->sc_ah;
 -      u32 rfilt;
 -      u32 now = (u32) jiffies_to_msecs(get_timestamp());
 -
 -      sc->sc_scanning = 1;
 -      rfilt = ath_calcrxfilter(sc);
 -      ath9k_hw_setrxfilter(ah, rfilt);
 -      ath9k_hw_write_associd(ah, ath_bcast_mac, 0);
 -
 -      /* Restore previous power management state. */
 -
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0\n",
 -              now / 1000, now % 1000, __func__, rfilt);
 -}
 -
 -/*
 - *  Scan End
 - *
 - *  This routine is called by the upper layer when the scan is completed.  This
 - *  will set the filters back to normal operating mode, set the BSSID to the
 - *  correct value, and restore the power save state.
 -*/
 -
 -void ath_scan_end(struct ath_softc *sc)
 -{
 -      struct ath_hal *ah = sc->sc_ah;
 -      u32 rfilt;
 -      u32 now = (u32) jiffies_to_msecs(get_timestamp());
 -
 -      sc->sc_scanning = 0;
 -      /* Request for a full reset due to rx packet filter changes */
 -      sc->sc_full_reset = 1;
 -      rfilt = ath_calcrxfilter(sc);
 -      ath9k_hw_setrxfilter(ah, rfilt);
 -      ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid);
 -
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0x%x\n",
 -              now / 1000, now % 1000, __func__, rfilt, sc->sc_curaid);
 -}
 -
  /*
   * Set the current channel
   *
@@@ -311,23 -365,25 +311,23 @@@ int ath_set_channel(struct ath_softc *s
  {
        struct ath_hal *ah = sc->sc_ah;
        bool fastcc = true, stopped;
 -      enum ath9k_ht_macmode ht_macmode;
  
 -      if (sc->sc_invalid)     /* if the device is invalid or removed */
 +      if (sc->sc_flags & SC_OP_INVALID) /* the device is invalid or removed */
                return -EIO;
  
        DPRINTF(sc, ATH_DBG_CONFIG,
                "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n",
                __func__,
 -              ath9k_hw_mhz2ieee(ah, sc->sc_curchan.channel,
 -                                sc->sc_curchan.channelFlags),
 -              sc->sc_curchan.channel,
 +              ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel,
 +                                sc->sc_ah->ah_curchan->channelFlags),
 +              sc->sc_ah->ah_curchan->channel,
                ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags),
                hchan->channel, hchan->channelFlags);
  
 -      ht_macmode = ath_cwm_macmode(sc);
 -
 -      if (hchan->channel != sc->sc_curchan.channel ||
 -          hchan->channelFlags != sc->sc_curchan.channelFlags ||
 -          sc->sc_update_chainmask || sc->sc_full_reset) {
 +      if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
 +          hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
 +          (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
 +          (sc->sc_flags & SC_OP_FULL_RESET)) {
                int status;
                /*
                 * This is only performed if the channel settings have
                 * to flush data frames already in queue because of
                 * changing channel. */
  
 -              if (!stopped || sc->sc_full_reset)
 +              if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
                        fastcc = false;
  
                spin_lock_bh(&sc->sc_resetlock);
 -              if (!ath9k_hw_reset(ah, sc->sc_opmode, hchan,
 -                                      ht_macmode, sc->sc_tx_chainmask,
 -                                      sc->sc_rx_chainmask,
 -                                      sc->sc_ht_extprotspacing,
 -                                      fastcc, &status)) {
 +              if (!ath9k_hw_reset(ah, hchan,
 +                                  sc->sc_ht_info.tx_chan_width,
 +                                  sc->sc_tx_chainmask,
 +                                  sc->sc_rx_chainmask,
 +                                  sc->sc_ht_extprotspacing,
 +                                  fastcc, &status)) {
                        DPRINTF(sc, ATH_DBG_FATAL,
                                "%s: unable to reset channel %u (%uMhz) "
                                "flags 0x%x hal status %u\n", __func__,
                }
                spin_unlock_bh(&sc->sc_resetlock);
  
 -              sc->sc_curchan = *hchan;
 -              sc->sc_update_chainmask = 0;
 -              sc->sc_full_reset = 0;
 +              sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
 +              sc->sc_flags &= ~SC_OP_FULL_RESET;
  
                /* Re-enable rx framework */
                if (ath_startrecv(sc) != 0) {
@@@ -479,7 -535,7 +479,7 @@@ int ath_chainmask_sel_logic(struct ath_
  
  void ath_update_chainmask(struct ath_softc *sc, int is_ht)
  {
 -      sc->sc_update_chainmask = 1;
 +      sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
        if (is_ht) {
                sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
                sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
  /* VAP management */
  /******************/
  
 -/*
 - *  VAP in Listen mode
 - *
 - *  This routine brings the VAP out of the down state into a "listen" state
 - *  where it waits for association requests.  This is used in AP and AdHoc
 - *  modes.
 -*/
 -
 -int ath_vap_listen(struct ath_softc *sc, int if_id)
 -{
 -      struct ath_hal *ah = sc->sc_ah;
 -      struct ath_vap *avp;
 -      u32 rfilt = 0;
 -      DECLARE_MAC_BUF(mac);
 -
 -      avp = sc->sc_vaps[if_id];
 -      if (avp == NULL) {
 -              DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n",
 -                      __func__, if_id);
 -              return -EINVAL;
 -      }
 -
 -#ifdef CONFIG_SLOW_ANT_DIV
 -      ath_slow_ant_div_stop(&sc->sc_antdiv);
 -#endif
 -
 -      /* update ratectrl about the new state */
 -      ath_rate_newstate(sc, avp);
 -
 -      rfilt = ath_calcrxfilter(sc);
 -      ath9k_hw_setrxfilter(ah, rfilt);
 -
 -      if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS) {
 -              memcpy(sc->sc_curbssid, ath_bcast_mac, ETH_ALEN);
 -              ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid);
 -      } else
 -              sc->sc_curaid = 0;
 -
 -      DPRINTF(sc, ATH_DBG_CONFIG,
 -              "%s: RX filter 0x%x bssid %s aid 0x%x\n",
 -              __func__, rfilt, print_mac(mac,
 -                      sc->sc_curbssid), sc->sc_curaid);
 -
 -      /*
 -       * XXXX
 -       * Disable BMISS interrupt when we're not associated
 -       */
 -      ath9k_hw_set_interrupts(ah,
 -              sc->sc_imask & ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS));
 -      sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
 -      /* need to reconfigure the beacons when it moves to RUN */
 -      sc->sc_beacons = 0;
 -
 -      return 0;
 -}
 -
  int ath_vap_attach(struct ath_softc *sc,
                   int if_id,
                   struct ieee80211_vif *if_data,
        /* Set the VAP opmode */
        avp->av_opmode = opmode;
        avp->av_bslot = -1;
 -      INIT_LIST_HEAD(&avp->av_mcastq.axq_q);
 -      INIT_LIST_HEAD(&avp->av_mcastq.axq_acq);
 -      spin_lock_init(&avp->av_mcastq.axq_lock);
  
 -      ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
 +      if (opmode == ATH9K_M_HOSTAP)
 +              ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
  
        sc->sc_vaps[if_id] = avp;
        sc->sc_nvaps++;
        /* Set the device opmode */
 -      sc->sc_opmode = opmode;
 +      sc->sc_ah->ah_opmode = opmode;
  
        /* default VAP configuration */
        avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
@@@ -573,6 -687,9 +573,6 @@@ int ath_vap_detach(struct ath_softc *sc
        ath_stoprecv(sc);       /* stop recv side */
        ath_flushrecv(sc);      /* flush recv queue */
  
 -      /* Reclaim any pending mcast bufs on the vap. */
 -      ath_tx_draintxq(sc, &avp->av_mcastq, false);
 -
        kfree(avp);
        sc->sc_vaps[if_id] = NULL;
        sc->sc_nvaps--;
@@@ -609,9 -726,9 +609,9 @@@ int ath_open(struct ath_softc *sc, stru
        struct ath_hal *ah = sc->sc_ah;
        int status;
        int error = 0;
 -      enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
  
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_opmode);
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n",
 +              __func__, sc->sc_ah->ah_opmode);
  
        /*
         * Stop anything previously setup.  This is safe
         * be followed by initialization of the appropriate bits
         * and then setup of the interrupt mask.
         */
 -      sc->sc_curchan = *initial_chan;
  
        spin_lock_bh(&sc->sc_resetlock);
 -      if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, ht_macmode,
 -                         sc->sc_tx_chainmask, sc->sc_rx_chainmask,
 -                         sc->sc_ht_extprotspacing, false, &status)) {
 +      if (!ath9k_hw_reset(ah, initial_chan,
 +                          sc->sc_ht_info.tx_chan_width,
 +                          sc->sc_tx_chainmask, sc->sc_rx_chainmask,
 +                          sc->sc_ht_extprotspacing, false, &status)) {
                DPRINTF(sc, ATH_DBG_FATAL,
                        "%s: unable to reset hardware; hal status %u "
                        "(freq %u flags 0x%x)\n", __func__, status,
 -                      sc->sc_curchan.channel, sc->sc_curchan.channelFlags);
 +                      initial_chan->channel, initial_chan->channelFlags);
                error = -EIO;
                spin_unlock_bh(&sc->sc_resetlock);
                goto done;
        if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
                sc->sc_imask |= ATH9K_INT_CST;
  
+       /* Note: We disable MIB interrupts for now as we don't yet
+        * handle processing ANI, otherwise you will get an interrupt
+        * storm after about 7 hours of usage making the system unusable
+        * with huge latency. Once we do have ANI processing included
+        * we can re-enable this interrupt. */
+ #if 0
        /*
         * Enable MIB interrupts when there are hardware phy counters.
         * Note we only do this (at the moment) for station mode.
         */
        if (ath9k_hw_phycounters(ah) &&
 -          ((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS)))
 +          ((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
 +           (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)))
                sc->sc_imask |= ATH9K_INT_MIB;
+ #endif
        /*
         * Some hardware processes the TIM IE and fires an
         * interrupt when the TIM bit is set.  For hardware
         * enable the TIM interrupt when operating as station.
         */
        if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
 -          (sc->sc_opmode == ATH9K_M_STA) &&
 +          (sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
            !sc->sc_config.swBeaconProcess)
                sc->sc_imask |= ATH9K_INT_TIM;
        /*
  
        /* XXX: we must make sure h/w is ready and clear invalid flag
         * before turning on interrupt. */
 -      sc->sc_invalid = 0;
 +      sc->sc_flags &= ~SC_OP_INVALID;
  done:
        return error;
  }
  
 -/*
 - * Reset the hardware w/o losing operational state.  This is
 - * basically a more efficient way of doing ath_stop, ath_init,
 - * followed by state transitions to the current 802.11
 - * operational state.  Used to recover from errors rx overrun
 - * and to reset the hardware when rf gain settings must be reset.
 - */
 -
 -static int ath_reset_start(struct ath_softc *sc, u32 flag)
 +int ath_reset(struct ath_softc *sc, bool retry_tx)
  {
        struct ath_hal *ah = sc->sc_ah;
 +      int status;
 +      int error = 0;
  
        ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
 -      ath_draintxq(sc, flag & RESET_RETRY_TXQ);       /* stop xmit side */
 -      ath_stoprecv(sc);       /* stop recv side */
 -      ath_flushrecv(sc);      /* flush recv queue */
 +      ath_draintxq(sc, retry_tx);     /* stop xmit */
 +      ath_stoprecv(sc);               /* stop recv */
 +      ath_flushrecv(sc);              /* flush recv queue */
  
 -      return 0;
 -}
 -
 -static int ath_reset_end(struct ath_softc *sc, u32 flag)
 -{
 -      struct ath_hal *ah = sc->sc_ah;
 +      /* Reset chip */
 +      spin_lock_bh(&sc->sc_resetlock);
 +      if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan,
 +                          sc->sc_ht_info.tx_chan_width,
 +                          sc->sc_tx_chainmask, sc->sc_rx_chainmask,
 +                          sc->sc_ht_extprotspacing, false, &status)) {
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: unable to reset hardware; hal status %u\n",
 +                      __func__, status);
 +              error = -EIO;
 +      }
 +      spin_unlock_bh(&sc->sc_resetlock);
  
        if (ath_startrecv(sc) != 0)     /* restart recv */
                DPRINTF(sc, ATH_DBG_FATAL,
         * that changes the channel so update any state that
         * might change as a result.
         */
 -      ath_setcurmode(sc, ath_chan2mode(&sc->sc_curchan));
 +      ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan));
  
 -      ath_update_txpow(sc);   /* update tx power state */
 +      ath_update_txpow(sc);
  
 -      if (sc->sc_beacons)
 +      if (sc->sc_flags & SC_OP_BEACONS)
                ath_beacon_config(sc, ATH_IF_ID_ANY);   /* restart beacons */
 +
        ath9k_hw_set_interrupts(ah, sc->sc_imask);
  
        /* Restart the txq */
 -      if (flag & RESET_RETRY_TXQ) {
 +      if (retry_tx) {
                int i;
                for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                        if (ATH_TXQ_SETUP(sc, i)) {
                        }
                }
        }
 -      return 0;
 -}
 -
 -int ath_reset(struct ath_softc *sc)
 -{
 -      struct ath_hal *ah = sc->sc_ah;
 -      int status;
 -      int error = 0;
 -      enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
 -
 -      /* NB: indicate channel change so we do a full reset */
 -      spin_lock_bh(&sc->sc_resetlock);
 -      if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan,
 -                         ht_macmode,
 -                         sc->sc_tx_chainmask, sc->sc_rx_chainmask,
 -                         sc->sc_ht_extprotspacing, false, &status)) {
 -              DPRINTF(sc, ATH_DBG_FATAL,
 -                      "%s: unable to reset hardware; hal status %u\n",
 -                      __func__, status);
 -              error = -EIO;
 -      }
 -      spin_unlock_bh(&sc->sc_resetlock);
  
        return error;
  }
@@@ -772,7 -916,7 +779,7 @@@ int ath_suspend(struct ath_softc *sc
        struct ath_hal *ah = sc->sc_ah;
  
        /* No I/O if device has been surprise removed */
 -      if (sc->sc_invalid)
 +      if (sc->sc_flags & SC_OP_INVALID)
                return -EIO;
  
        /* Shut off the interrupt before setting sc->sc_invalid to '1' */
  
        /* XXX: we must make sure h/w will not generate any interrupt
         * before setting the invalid flag. */
 -      sc->sc_invalid = 1;
 +      sc->sc_flags |= SC_OP_INVALID;
  
        /* disable HAL and put h/w to sleep */
        ath9k_hw_disable(sc->sc_ah);
@@@ -801,7 -945,7 +808,7 @@@ irqreturn_t ath_isr(int irq, void *dev
        bool sched = false;
  
        do {
 -              if (sc->sc_invalid) {
 +              if (sc->sc_flags & SC_OP_INVALID) {
                        /*
                         * The hardware is not ready/present, don't
                         * touch anything. Note this can happen early
@@@ -911,7 -1055,7 +918,7 @@@ static void ath9k_tasklet(unsigned lon
  
        if (status & ATH9K_INT_FATAL) {
                /* need a chip reset */
 -              ath_internal_reset(sc);
 +              ath_reset(sc, false);
                return;
        } else {
  
@@@ -954,9 -1098,10 +961,9 @@@ int ath_init(u16 devid, struct ath_soft
        int status;
        int error = 0, i;
        int csz = 0;
 -      u32 rd;
  
        /* XXX: hardware will not be ready until ath_open() being called */
 -      sc->sc_invalid = 1;
 +      sc->sc_flags |= SC_OP_INVALID;
  
        sc->sc_debug = DBG_DEFAULT;
        DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid);
        }
        sc->sc_ah = ah;
  
 -      /* Get the chipset-specific aggr limit. */
 -      sc->sc_rtsaggrlimit = ah->ah_caps.rts_aggr_limit;
 -
        /* Get the hardware key cache size. */
        sc->sc_keymax = ah->ah_caps.keycache_size;
        if (sc->sc_keymax > ATH_KEYMAX) {
         * is resposible for filtering this list based on settings
         * like the phy mode.
         */
 -      rd = ah->ah_currentRD;
 -
        error = ath_setup_channels(sc);
        if (error)
                goto bad;
  
        /* default to STA mode */
 -      sc->sc_opmode = ATH9K_M_MONITOR;
 +      sc->sc_ah->ah_opmode = ATH9K_M_MONITOR;
  
        /* Setup rate tables */
  
  
        sc->sc_rc = ath_rate_attach(ah);
        if (sc->sc_rc == NULL) {
 -              error = EIO;
 +              error = -EIO;
                goto bad2;
        }
  
  
        /* 11n Capabilities */
        if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
 -              sc->sc_txaggr = 1;
 -              sc->sc_rxaggr = 1;
 +              sc->sc_flags |= SC_OP_TXAGGR;
 +              sc->sc_flags |= SC_OP_RXAGGR;
        }
  
        sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
        sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
  
 -      /* Configuration for rx chain detection */
 -      sc->sc_rxchaindetect_ref = 0;
 -      sc->sc_rxchaindetect_thresh5GHz = 35;
 -      sc->sc_rxchaindetect_thresh2GHz = 35;
 -      sc->sc_rxchaindetect_delta5GHz = 30;
 -      sc->sc_rxchaindetect_delta2GHz = 30;
 -
        ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
        sc->sc_defant = ath9k_hw_getdefantenna(ah);
  
@@@ -1184,8 -1341,10 +1191,10 @@@ void ath_deinit(struct ath_softc *sc
  
        DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__);
  
+       tasklet_kill(&sc->intr_tq);
+       tasklet_kill(&sc->bcon_tasklet);
        ath_stop(sc);
 -      if (!sc->sc_invalid)
 +      if (!(sc->sc_flags & SC_OP_INVALID))
                ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
        ath_rate_detach(sc->sc_rc);
        /* cleanup tx queues */
@@@ -1312,9 -1471,9 +1321,9 @@@ void ath_newassoc(struct ath_softc *sc
        /* if station reassociates, tear down the aggregation state. */
        if (!isnew) {
                for (tidno = 0; tidno < WME_NUM_TID; tidno++) {
 -                      if (sc->sc_txaggr)
 +                      if (sc->sc_flags & SC_OP_TXAGGR)
                                ath_tx_aggr_teardown(sc, an, tidno);
 -                      if (sc->sc_rxaggr)
 +                      if (sc->sc_flags & SC_OP_RXAGGR)
                                ath_rx_aggr_teardown(sc, an, tidno);
                }
        }
@@@ -1663,6 -1822,13 +1672,6 @@@ void ath_descdma_cleanup(struct ath_sof
  /* Utilities */
  /*************/
  
 -void ath_internal_reset(struct ath_softc *sc)
 -{
 -      ath_reset_start(sc, 0);
 -      ath_reset(sc);
 -      ath_reset_end(sc, 0);
 -}
 -
  int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
  {
        int qnum;
index 6ff3befe39f780feb1b45b402f6b88689961e0e6,2f84093331ee79253e58f33ff59006392c54d891..872f0c5a0b0e44a53145923f29385de82bc59353
@@@ -39,8 -39,6 +39,8 @@@
  #include <linux/scatterlist.h>
  #include <asm/page.h>
  #include <net/mac80211.h>
 +#include <linux/leds.h>
 +#include <linux/rfkill.h>
  
  #include "ath9k.h"
  #include "rc.h"
@@@ -81,12 -79,12 +81,12 @@@ struct ath_node
                }                               \
        } while (0)
  
 +#define TSF_TO_TU(_h,_l) \
 +      ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
 +
  /* XXX: remove */
  #define memzero(_buf, _len) memset(_buf, 0, _len)
  
 -#define get_dma_mem_context(var, field) (&((var)->field))
 -#define copy_dma_mem_context(dst, src)  (*dst = *src)
 -
  #define ATH9K_BH_STATUS_INTACT                0
  #define ATH9K_BH_STATUS_CHANGE                1
  
@@@ -97,8 -95,6 +97,8 @@@ static inline unsigned long get_timesta
        return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ);
  }
  
 +static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 +
  /*************/
  /* Debugging */
  /*************/
@@@ -179,6 -175,11 +179,6 @@@ void ath_update_chainmask(struct ath_so
  /* Descriptor Management */
  /*************************/
  
 -/* Number of descriptors per buffer. The only case where we see skbuff
 -chains is due to FF aggregation in the driver. */
 -#define       ATH_TXDESC          1
 -/* if there's more fragment for this MSDU */
 -#define ATH_BF_MORE_MPDU    1
  #define ATH_TXBUF_RESET(_bf) do {                             \
                (_bf)->bf_status = 0;                           \
                (_bf)->bf_lastbf = NULL;                        \
                            sizeof(struct ath_buf_state));      \
        } while (0)
  
 +enum buffer_type {
 +      BUF_DATA                = BIT(0),
 +      BUF_AGGR                = BIT(1),
 +      BUF_AMPDU               = BIT(2),
 +      BUF_HT                  = BIT(3),
 +      BUF_RETRY               = BIT(4),
 +      BUF_XRETRY              = BIT(5),
 +      BUF_SHORT_PREAMBLE      = BIT(6),
 +      BUF_BAR                 = BIT(7),
 +      BUF_PSPOLL              = BIT(8),
 +      BUF_AGGR_BURST          = BIT(9),
 +      BUF_CALC_AIRTIME        = BIT(10),
 +};
 +
  struct ath_buf_state {
 -      int bfs_nframes;        /* # frames in aggregate */
 -      u16 bfs_al;             /* length of aggregate */
 -      u16 bfs_frmlen;         /* length of frame */
 -      int bfs_seqno;          /* sequence number */
 -      int bfs_tidno;          /* tid of this frame */
 -      int bfs_retries;        /* current retries */
 +      int bfs_nframes;                        /* # frames in aggregate */
 +      u16 bfs_al;                             /* length of aggregate */
 +      u16 bfs_frmlen;                         /* length of frame */
 +      int bfs_seqno;                          /* sequence number */
 +      int bfs_tidno;                          /* tid of this frame */
 +      int bfs_retries;                        /* current retries */
        struct ath_rc_series bfs_rcs[4];        /* rate series */
 -      u8 bfs_isdata:1;        /* is a data frame/aggregate */
 -      u8 bfs_isaggr:1;        /* is an aggregate */
 -      u8 bfs_isampdu:1;       /* is an a-mpdu, aggregate or not */
 -      u8 bfs_ht:1;            /* is an HT frame */
 -      u8 bfs_isretried:1;     /* is retried */
 -      u8 bfs_isxretried:1;    /* is excessive retried */
 -      u8 bfs_shpreamble:1;    /* is short preamble */
 -      u8 bfs_isbar:1;         /* is a BAR */
 -      u8 bfs_ispspoll:1;      /* is a PS-Poll */
 -      u8 bfs_aggrburst:1;     /* is a aggr burst */
 -      u8 bfs_calcairtime:1;   /* requests airtime be calculated
 -                              when set for tx frame */
 -      int bfs_rifsburst_elem; /* RIFS burst/bar */
 -      int bfs_nrifsubframes;  /* # of elements in burst */
 +      u32 bf_type;                            /* BUF_* (enum buffer_type) */
        /* key type use to encrypt this frame */
        enum ath9k_key_type bfs_keytype;
  };
  #define bf_seqno              bf_state.bfs_seqno
  #define bf_tidno              bf_state.bfs_tidno
  #define bf_rcs                bf_state.bfs_rcs
 -#define bf_isdata             bf_state.bfs_isdata
 -#define bf_isaggr             bf_state.bfs_isaggr
 -#define bf_isampdu            bf_state.bfs_isampdu
 -#define bf_ht                 bf_state.bfs_ht
 -#define bf_isretried          bf_state.bfs_isretried
 -#define bf_isxretried         bf_state.bfs_isxretried
 -#define bf_shpreamble         bf_state.bfs_shpreamble
 -#define bf_rifsburst_elem     bf_state.bfs_rifsburst_elem
 -#define bf_nrifsubframes      bf_state.bfs_nrifsubframes
  #define bf_keytype            bf_state.bfs_keytype
 -#define bf_isbar              bf_state.bfs_isbar
 -#define bf_ispspoll           bf_state.bfs_ispspoll
 -#define bf_aggrburst          bf_state.bfs_aggrburst
 -#define bf_calcairtime        bf_state.bfs_calcairtime
 +#define bf_isdata(bf)         (bf->bf_state.bf_type & BUF_DATA)
 +#define bf_isaggr(bf)         (bf->bf_state.bf_type & BUF_AGGR)
 +#define bf_isampdu(bf)                (bf->bf_state.bf_type & BUF_AMPDU)
 +#define bf_isht(bf)           (bf->bf_state.bf_type & BUF_HT)
 +#define bf_isretried(bf)      (bf->bf_state.bf_type & BUF_RETRY)
 +#define bf_isxretried(bf)     (bf->bf_state.bf_type & BUF_XRETRY)
 +#define bf_isshpreamble(bf)   (bf->bf_state.bf_type & BUF_SHORT_PREAMBLE)
 +#define bf_isbar(bf)          (bf->bf_state.bf_type & BUF_BAR)
 +#define bf_ispspoll(bf)       (bf->bf_state.bf_type & BUF_PSPOLL)
 +#define bf_isaggrburst(bf)    (bf->bf_state.bf_type & BUF_AGGR_BURST)
  
  /*
   * Abstraction of a contiguous buffer to transmit/receive.  There is only
   * a single hw descriptor encapsulated here.
   */
 -
  struct ath_buf {
        struct list_head list;
        struct list_head *last;
@@@ -387,10 -391,10 +387,10 @@@ int ath_rx_input(struct ath_softc *sc
                 struct sk_buff *skb,
                 struct ath_recv_status *rx_status,
                 enum ATH_RX_TYPE *status);
 -int ath__rx_indicate(struct ath_softc *sc,
 -                  struct sk_buff *skb,
 -                  struct ath_recv_status *status,
 -                  u16 keyix);
 +int _ath_rx_indicate(struct ath_softc *sc,
 +                   struct sk_buff *skb,
 +                   struct ath_recv_status *status,
 +                   u16 keyix);
  int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb,
                    struct ath_recv_status *status);
  
  /* TX */
  /******/
  
 -#define ATH_FRAG_PER_MSDU       1
 -#define ATH_TXBUF               (512/ATH_FRAG_PER_MSDU)
 +#define ATH_TXBUF               512
  /* max number of transmit attempts (tries) */
  #define ATH_TXMAXTRY            13
  /* max number of 11n transmit attempts (tries) */
@@@ -517,6 -522,7 +517,6 @@@ struct ath_tx_control 
        u32 keyix;
        int min_rate;
        int mcast_rate;
 -      u16 nextfraglen;
        struct ath_softc *dev;
        dma_addr_t dmacontext;
  };
@@@ -551,10 -557,10 +551,10 @@@ void ath_tx_cleanupq(struct ath_softc *
  int ath_tx_setup(struct ath_softc *sc, int haltype);
  void ath_draintxq(struct ath_softc *sc, bool retry_tx);
  void ath_tx_draintxq(struct ath_softc *sc,
 -      struct ath_txq *txq, bool retry_tx);
 +                   struct ath_txq *txq, bool retry_tx);
  void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
  void ath_tx_node_cleanup(struct ath_softc *sc,
 -      struct ath_node *an, bool bh_flag);
 +                       struct ath_node *an, bool bh_flag);
  void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
  void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
  int ath_tx_init(struct ath_softc *sc, int nbufs);
@@@ -569,7 -575,6 +569,7 @@@ u32 ath_txq_aggr_depth(struct ath_soft
  void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
  void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                     struct ath_xmit_status *tx_status, struct ath_node *an);
 +void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
  
  /**********************/
  /* Node / Aggregation */
  /* indicates the node is 80211 power save */
  #define ATH_NODE_PWRSAVE        0x2
  
 -#define ADDBA_TIMEOUT              200 /* 200 milliseconds */
  #define ADDBA_EXCHANGE_ATTEMPTS    10
  #define ATH_AGGR_DELIM_SZ          4   /* delimiter size   */
  #define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
@@@ -699,6 -705,9 +699,6 @@@ struct ath_node *ath_node_find(struct a
  #define       ATH_BCBUF                       4   /* number of beacon buffers */
  #define ATH_DEFAULT_BINTVAL           100 /* default beacon interval in TU */
  #define ATH_DEFAULT_BMISS_LIMIT       10
 -#define       ATH_BEACON_AIFS_DEFAULT         0  /* Default aifs for ap beacon q */
 -#define       ATH_BEACON_CWMIN_DEFAULT        0  /* Default cwmin for ap beacon q */
 -#define       ATH_BEACON_CWMAX_DEFAULT        0  /* Default cwmax for ap beacon q */
  #define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
  
  /* beacon configuration */
@@@ -715,16 -724,30 +715,16 @@@ struct ath_beacon_config 
        } u; /* last received beacon/probe response timestamp of this BSS. */
  };
  
 -/* offsets in a beacon frame for
 - * quick acess of beacon content by low-level driver */
 -struct ath_beacon_offset {
 -      u8 *bo_tim;     /* start of atim/dtim */
 -};
 -
  void ath9k_beacon_tasklet(unsigned long data);
  void ath_beacon_config(struct ath_softc *sc, int if_id);
  int ath_beaconq_setup(struct ath_hal *ah);
  int ath_beacon_alloc(struct ath_softc *sc, int if_id);
  void ath_bstuck_process(struct ath_softc *sc);
 -void ath_beacon_tasklet(struct ath_softc *sc, int *needmark);
 -void ath_beacon_free(struct ath_softc *sc);
  void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp);
  void ath_beacon_sync(struct ath_softc *sc, int if_id);
 -void ath_update_beacon_info(struct ath_softc *sc, int avgbrssi);
  void ath_get_beaconconfig(struct ath_softc *sc,
                          int if_id,
                          struct ath_beacon_config *conf);
 -int ath_update_beacon(struct ath_softc *sc,
 -                    int if_id,
 -                    struct ath_beacon_offset *bo,
 -                    struct sk_buff *skb,
 -                    int mcast);
  /********/
  /* VAPs */
  /********/
@@@ -751,8 -774,10 +751,8 @@@ struct ath_vap 
        struct ieee80211_vif *av_if_data;
        enum ath9k_opmode av_opmode;    /* VAP operational mode */
        struct ath_buf *av_bcbuf;       /* beacon buffer */
 -      struct ath_beacon_offset av_boff; /* dynamic update state */
        struct ath_tx_control av_btxctl;  /* txctl information for beacon */
        int av_bslot;                   /* beacon slot index */
 -      struct ath_txq av_mcastq;       /* multicast transmit queue */
        struct ath_vap_config av_config;/* vap configuration parameters*/
        struct ath_rate_node *rc_node;
  };
@@@ -763,7 -788,8 +763,7 @@@ int ath_vap_attach(struct ath_softc *sc
                   enum ath9k_opmode opmode);
  int ath_vap_detach(struct ath_softc *sc, int if_id);
  int ath_vap_config(struct ath_softc *sc,
 -      int if_id, struct ath_vap_config *if_config);
 -int ath_vap_listen(struct ath_softc *sc, int if_id);
 +                 int if_id, struct ath_vap_config *if_config);
  
  /*********************/
  /* Antenna diversity */
@@@ -803,36 -829,6 +803,36 @@@ void ath_slow_ant_div(struct ath_antdi
                      struct ath_rx_status *rx_stats);
  void ath_setdefantenna(void *sc, u32 antenna);
  
 +/********************/
 +/*   LED Control    */
 +/********************/
 +
 +#define ATH_LED_PIN   1
 +
 +enum ath_led_type {
 +      ATH_LED_RADIO,
 +      ATH_LED_ASSOC,
 +      ATH_LED_TX,
 +      ATH_LED_RX
 +};
 +
 +struct ath_led {
 +      struct ath_softc *sc;
 +      struct led_classdev led_cdev;
 +      enum ath_led_type led_type;
 +      char name[32];
 +      bool registered;
 +};
 +
 +/* Rfkill */
 +#define ATH_RFKILL_POLL_INTERVAL      2000 /* msecs */
 +
 +struct ath_rfkill {
 +      struct rfkill *rfkill;
 +      struct delayed_work rfkill_poll;
 +      char rfkill_name[32];
 +};
 +
  /********************/
  /* Main driver core */
  /********************/
  #define       ATH_DEFAULT_NOISE_FLOOR -95
  #define ATH_REGCLASSIDS_MAX     10
  #define ATH_CABQ_READY_TIME     80  /* % of beacon interval */
 -#define ATH_PREAMBLE_SHORT    (1<<0)
 -#define ATH_PROTECT_ENABLE    (1<<1)
  #define ATH_MAX_SW_RETRIES      10
 -/* Num farmes difference in tx to flip default recv */
 -#define       ATH_ANTENNA_DIFF        2
  #define ATH_CHAN_MAX            255
  #define IEEE80211_WEP_NKID      4       /* number of key ids */
  #define IEEE80211_RATE_VAL      0x7f
   */
  #define       ATH_KEYMAX              128        /* max key cache size we handle */
  
 -#define RESET_RETRY_TXQ         0x00000001
  #define ATH_IF_ID_ANY         0xff
 -
  #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
  
  #define RSSI_LPF_THRESHOLD         -20
@@@ -905,64 -907,60 +905,64 @@@ struct ath_ht_info 
        u8 ext_chan_offset;
  };
  
 +#define SC_OP_INVALID         BIT(0)
 +#define SC_OP_BEACONS         BIT(1)
 +#define SC_OP_RXAGGR          BIT(2)
 +#define SC_OP_TXAGGR          BIT(3)
 +#define SC_OP_CHAINMASK_UPDATE        BIT(4)
 +#define SC_OP_FULL_RESET      BIT(5)
 +#define SC_OP_NO_RESET                BIT(6)
 +#define SC_OP_PREAMBLE_SHORT  BIT(7)
 +#define SC_OP_PROTECT_ENABLE  BIT(8)
 +#define SC_OP_RXFLUSH         BIT(9)
 +#define SC_OP_LED_ASSOCIATED  BIT(10)
 +#define SC_OP_RFKILL_REGISTERED       BIT(11)
 +#define SC_OP_RFKILL_SW_BLOCKED       BIT(12)
 +#define SC_OP_RFKILL_HW_BLOCKED       BIT(13)
 +
  struct ath_softc {
        struct ieee80211_hw *hw;
        struct pci_dev *pdev;
 -      void __iomem *mem;
        struct tasklet_struct intr_tq;
        struct tasklet_struct bcon_tasklet;
 -      struct ath_config sc_config;    /* load-time parameters */
 -      int sc_debug;
 +      struct ath_config sc_config;
        struct ath_hal *sc_ah;
 -      struct ath_rate_softc *sc_rc;   /* tx rate control support */
 +      struct ath_rate_softc *sc_rc;
 +      void __iomem *mem;
 +
 +      u8 sc_curbssid[ETH_ALEN];
 +      u8 sc_myaddr[ETH_ALEN];
 +      u8 sc_bssidmask[ETH_ALEN];
 +
 +      int sc_debug;
        u32 sc_intrstatus;
 -      enum ath9k_opmode sc_opmode;    /* current operating mode */
 -
 -      u8 sc_invalid;                  /* being detached */
 -      u8 sc_beacons;                  /* beacons running */
 -      u8 sc_scanning;                 /* scanning active */
 -      u8 sc_txaggr;                   /* enable 11n tx aggregation */
 -      u8 sc_rxaggr;                   /* enable 11n rx aggregation */
 -      u8 sc_update_chainmask;         /* change chain mask */
 -      u8 sc_full_reset;               /* force full reset */
 -      enum wireless_mode sc_curmode;  /* current phy mode */
 +      u32 sc_flags; /* SC_OP_* */
 +      unsigned int rx_filter;
        u16 sc_curtxpow;
        u16 sc_curaid;
 -      u8 sc_curbssid[ETH_ALEN];
 -      u8 sc_myaddr[ETH_ALEN];
 +      u16 sc_cachelsz;
 +      int sc_slotupdate;              /* slot to next advance fsm */
 +      int sc_slottime;
 +      int sc_bslot[ATH_BCBUF];
 +      u8 sc_tx_chainmask;
 +      u8 sc_rx_chainmask;
 +      enum ath9k_int sc_imask;
 +      enum wireless_mode sc_curmode;  /* current phy mode */
        enum PROT_MODE sc_protmode;
 -      u8 sc_mcastantenna;
 -      u8 sc_txantenna;                /* data tx antenna (fixed or auto) */
 +
        u8 sc_nbcnvaps;                 /* # of vaps sending beacons */
        u16 sc_nvaps;                   /* # of active virtual ap's */
        struct ath_vap *sc_vaps[ATH_BCBUF];
 -      enum ath9k_int sc_imask;
 -      u8 sc_bssidmask[ETH_ALEN];
 +
 +      u8 sc_mcastantenna;
        u8 sc_defant;                   /* current default antenna */
        u8 sc_rxotherant;               /* rx's on non-default antenna */
 -      u16 sc_cachelsz;
 -      int sc_slotupdate;              /* slot to next advance fsm */
 -      int sc_slottime;
 -      u8 sc_noreset;
 -      int sc_bslot[ATH_BCBUF];
 +
        struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
        struct list_head node_list;
        struct ath_ht_info sc_ht_info;
 -      int16_t sc_noise_floor;         /* signal noise floor in dBm */
        enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
 -      u8 sc_tx_chainmask;
 -      u8 sc_rx_chainmask;
 -      u8 sc_rxchaindetect_ref;
 -      u8 sc_rxchaindetect_thresh5GHz;
 -      u8 sc_rxchaindetect_thresh2GHz;
 -      u8 sc_rxchaindetect_delta5GHz;
 -      u8 sc_rxchaindetect_delta2GHz;
 -      u32 sc_rtsaggrlimit;            /* Chipset specific aggr limit */
 -      u32 sc_flags;
 +
  #ifdef CONFIG_SLOW_ANT_DIV
        struct ath_antdiv sc_antdiv;
  #endif
        u32 sc_keymax;          /* size of key cache */
        DECLARE_BITMAP(sc_keymap, ATH_KEYMAX);  /* key use bit map */
        u8 sc_splitmic;         /* split TKIP MIC keys */
-       int sc_keytype;
  
        /* RX */
        struct list_head sc_rxbuf;
        struct ath_descdma sc_rxdma;
        int sc_rxbufsize;       /* rx size based on mtu */
        u32 *sc_rxlink;         /* link ptr in last RX desc */
 -      u32 sc_rxflush;         /* rx flush in progress */
 -      u64 sc_lastrx;          /* tsf of last rx'd frame */
  
        /* TX */
        struct list_head sc_txbuf;
        u32 sc_txqsetup;
        u32 sc_txintrperiod;    /* tx interrupt batching */
        int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */
 -      u32 sc_ant_tx[8];       /* recent tx frames/antenna */
        u16 seq_no; /* TX sequence number */
  
        /* Beacon */
        u32 sc_bhalq;
        u32 sc_bmisscount;
        u32 ast_be_xmit;        /* beacons transmitted */
 +      u64 bc_tstamp;
  
        /* Rate */
        struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
        /* Channel, Band */
        struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX];
        struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
 -      struct ath9k_channel sc_curchan;
  
        /* Locks */
        spinlock_t sc_rxflushlock;
        spinlock_t sc_txbuflock;
        spinlock_t sc_resetlock;
        spinlock_t node_lock;
 +
 +      /* LEDs */
 +      struct ath_led radio_led;
 +      struct ath_led assoc_led;
 +      struct ath_led tx_led;
 +      struct ath_led rx_led;
 +
 +      /* Rfkill */
 +      struct ath_rfkill rf_kill;
  };
  
  int ath_init(u16 devid, struct ath_softc *sc);
@@@ -1039,8 -1030,14 +1038,8 @@@ void ath_deinit(struct ath_softc *sc)
  int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan);
  int ath_suspend(struct ath_softc *sc);
  irqreturn_t ath_isr(int irq, void *dev);
 -int ath_reset(struct ath_softc *sc);
 -void ath_scan_start(struct ath_softc *sc);
 -void ath_scan_end(struct ath_softc *sc);
 +int ath_reset(struct ath_softc *sc, bool retry_tx);
  int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan);
 -void ath_setup_rate(struct ath_softc *sc,
 -                  enum wireless_mode wMode,
 -                  enum RATE_TYPE type,
 -                  const struct ath9k_rate_table *rt);
  
  /*********************/
  /* Utility Functions */
@@@ -1059,5 -1056,17 +1058,5 @@@ int ath_cabq_update(struct ath_softc *)
  void ath_get_currentCountry(struct ath_softc *sc,
        struct ath9k_country_entry *ctry);
  u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp);
 -void ath_internal_reset(struct ath_softc *sc);
 -u32 ath_chan2flags(struct ieee80211_channel *chan, struct ath_softc *sc);
 -dma_addr_t ath_skb_map_single(struct ath_softc *sc,
 -                            struct sk_buff *skb,
 -                            int direction,
 -                            dma_addr_t *pa);
 -void ath_skb_unmap_single(struct ath_softc *sc,
 -                        struct sk_buff *skb,
 -                        int direction,
 -                        dma_addr_t *pa);
 -void ath_mcast_merge(struct ath_softc *sc, u32 mfilt[2]);
 -enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc);
  
  #endif /* CORE_H */
index 1ba18006f475e87571f5718d1adc0865fd8cb838,acebdf1d20a842048ceaa1dcb5fcfbf117ce6fcc..2caba440316728ec75e1c4f85849978394c7deef
@@@ -22,6 -22,8 +22,6 @@@
  #define ATH_PCI_VERSION "0.1"
  
  #define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR     13
 -#define IEEE80211_ACTION_CAT_HT                       7
 -#define IEEE80211_ACTION_HT_TXCHWIDTH         0
  
  static char *dev_info = "ath9k";
  
@@@ -140,7 -142,7 +140,7 @@@ static int ath_key_config(struct ath_so
        struct ath9k_keyval hk;
        const u8 *mac = NULL;
        int ret = 0;
 -      enum ieee80211_if_types opmode;
 +      enum nl80211_iftype opmode;
  
        memset(&hk, 0, sizeof(hk));
  
         */
        if (is_broadcast_ether_addr(addr)) {
                switch (opmode) {
 -              case IEEE80211_IF_TYPE_STA:
 +              case NL80211_IFTYPE_STATION:
                        /* default key:  could be group WPA key
                         * or could be static WEP key */
                        mac = NULL;
                        break;
 -              case IEEE80211_IF_TYPE_IBSS:
 +              case NL80211_IFTYPE_ADHOC:
                        break;
 -              case IEEE80211_IF_TYPE_AP:
 +              case NL80211_IFTYPE_AP:
                        break;
                default:
                        ASSERT(0);
        if (!ret)
                return -EIO;
  
-       if (mac)
-               sc->sc_keytype = hk.kv_type;
        return 0;
  }
  
  static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
  {
 -#define ATH_MAX_NUM_KEYS 4
        int freeslot;
  
 -      freeslot = (key->keyidx >= ATH_MAX_NUM_KEYS) ? 1 : 0;
 +      freeslot = (key->keyidx >= 4) ? 1 : 0;
        ath_key_reset(sc, key->keyidx, freeslot);
 -#undef ATH_MAX_NUM_KEYS
  }
  
  static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
  {
 -/* Until mac80211 includes these fields */
 -
 -#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
 -#define       IEEE80211_HT_CAP_MAXRXAMPDU_65536 0x3   /* 2 ^ 16 */
 -#define       IEEE80211_HT_CAP_MPDUDENSITY_8 0x6      /* 8 usec */
 +#define       ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3       /* 2 ^ 16 */
 +#define       ATH9K_HT_CAP_MPDUDENSITY_8 0x6          /* 8 usec */
  
        ht_info->ht_supported = 1;
        ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH
 -                      |(u16)IEEE80211_HT_CAP_MIMO_PS
 +                      |(u16)IEEE80211_HT_CAP_SM_PS
                        |(u16)IEEE80211_HT_CAP_SGI_40
                        |(u16)IEEE80211_HT_CAP_DSSSCCK40;
  
 -      ht_info->ampdu_factor = IEEE80211_HT_CAP_MAXRXAMPDU_65536;
 -      ht_info->ampdu_density = IEEE80211_HT_CAP_MPDUDENSITY_8;
 +      ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
 +      ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
        /* setup supported mcs set */
        memset(ht_info->supp_mcs_set, 0, 16);
        ht_info->supp_mcs_set[0] = 0xff;
@@@ -325,1335 -330,964 +323,1334 @@@ static u8 parse_mpdudensity(u8 mpdudens
        }
  }
  
 -static int ath9k_start(struct ieee80211_hw *hw)
 +static void ath9k_ht_conf(struct ath_softc *sc,
 +                        struct ieee80211_bss_conf *bss_conf)
  {
 -      struct ath_softc *sc = hw->priv;
 -      struct ieee80211_channel *curchan = hw->conf.channel;
 -      int error = 0, pos;
 -
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with "
 -              "initial channel: %d MHz\n", __func__, curchan->center_freq);
 +#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
 +      struct ath_ht_info *ht_info = &sc->sc_ht_info;
  
 -      /* setup initial channel */
 +      if (bss_conf->assoc_ht) {
 +              ht_info->ext_chan_offset =
 +                      bss_conf->ht_bss_conf->bss_cap &
 +                              IEEE80211_HT_IE_CHA_SEC_OFFSET;
  
 -      pos = ath_get_channel(sc, curchan);
 -      if (pos == -1) {
 -              DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
 -              return -EINVAL;
 -      }
 +              if (!(bss_conf->ht_conf->cap &
 +                      IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
 +                          (bss_conf->ht_bss_conf->bss_cap &
 +                              IEEE80211_HT_IE_CHA_WIDTH))
 +                      ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
 +              else
 +                      ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
  
 -      sc->sc_ah->ah_channels[pos].chanmode =
 -              (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
 +              ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
 +              ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
 +                                      bss_conf->ht_conf->ampdu_factor);
 +              ht_info->mpdudensity =
 +                      parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
  
 -      /* open ath_dev */
 -      error = ath_open(sc, &sc->sc_ah->ah_channels[pos]);
 -      if (error) {
 -              DPRINTF(sc, ATH_DBG_FATAL,
 -                      "%s: Unable to complete ath_open\n", __func__);
 -              return error;
        }
  
 -      ieee80211_wake_queues(hw);
 -      return 0;
 +#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
  }
  
 -static int ath9k_tx(struct ieee80211_hw *hw,
 -                  struct sk_buff *skb)
 +static void ath9k_bss_assoc_info(struct ath_softc *sc,
 +                               struct ieee80211_bss_conf *bss_conf)
  {
 -      struct ath_softc *sc = hw->priv;
 -      int hdrlen, padsize;
 -      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 -
 -      /*
 -       * As a temporary workaround, assign seq# here; this will likely need
 -       * to be cleaned up to work better with Beacon transmission and virtual
 -       * BSSes.
 -       */
 -      if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 -              struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 -              if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
 -                      sc->seq_no += 0x10;
 -              hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
 -              hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
 -      }
 +      struct ieee80211_hw *hw = sc->hw;
 +      struct ieee80211_channel *curchan = hw->conf.channel;
 +      struct ath_vap *avp;
 +      int pos;
 +      DECLARE_MAC_BUF(mac);
  
 -      /* Add the padding after the header if this is not already done */
 -      hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 -      if (hdrlen & 3) {
 -              padsize = hdrlen % 4;
 -              if (skb_headroom(skb) < padsize)
 -                      return -1;
 -              skb_push(skb, padsize);
 -              memmove(skb->data, skb->data + padsize, hdrlen);
 -      }
 +      if (bss_conf->assoc) {
 +              DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n",
 +                      __func__,
 +                      bss_conf->aid);
  
 -      DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting packet, skb: %p\n",
 -              __func__,
 -              skb);
 +              avp = sc->sc_vaps[0];
 +              if (avp == NULL) {
 +                      DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
 +                              __func__);
 +                      return;
 +              }
  
 -      if (ath_tx_start(sc, skb) != 0) {
 -              DPRINTF(sc, ATH_DBG_XMIT, "%s: TX failed\n", __func__);
 -              dev_kfree_skb_any(skb);
 -              /* FIXME: Check for proper return value from ATH_DEV */
 -              return 0;
 -      }
 +              /* New association, store aid */
 +              if (avp->av_opmode == ATH9K_M_STA) {
 +                      sc->sc_curaid = bss_conf->aid;
 +                      ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
 +                                             sc->sc_curaid);
 +              }
  
 -      return 0;
 -}
 +              /* Configure the beacon */
 +              ath_beacon_config(sc, 0);
 +              sc->sc_flags |= SC_OP_BEACONS;
  
 -static void ath9k_stop(struct ieee80211_hw *hw)
 -{
 -      struct ath_softc *sc = hw->priv;
 -      int error;
 +              /* Reset rssi stats */
 +              sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
 +              sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
 +              sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
 +              sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
  
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__);
 +              /* Update chainmask */
 +              ath_update_chainmask(sc, bss_conf->assoc_ht);
  
 -      error = ath_suspend(sc);
 -      if (error)
                DPRINTF(sc, ATH_DBG_CONFIG,
 -                      "%s: Device is no longer present\n", __func__);
 +                      "%s: bssid %s aid 0x%x\n",
 +                      __func__,
 +                      print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
  
 -      ieee80211_stop_queues(hw);
 -}
 +              DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
 +                      __func__,
 +                      curchan->center_freq);
  
 -static int ath9k_add_interface(struct ieee80211_hw *hw,
 -                             struct ieee80211_if_init_conf *conf)
 -{
 -      struct ath_softc *sc = hw->priv;
 -      int error, ic_opmode = 0;
 +              pos = ath_get_channel(sc, curchan);
 +              if (pos == -1) {
 +                      DPRINTF(sc, ATH_DBG_FATAL,
 +                              "%s: Invalid channel\n", __func__);
 +                      return;
 +              }
  
 -      /* Support only vap for now */
 +              if (hw->conf.ht_conf.ht_supported)
 +                      sc->sc_ah->ah_channels[pos].chanmode =
 +                              ath_get_extchanmode(sc, curchan);
 +              else
 +                      sc->sc_ah->ah_channels[pos].chanmode =
 +                              (curchan->band == IEEE80211_BAND_2GHZ) ?
 +                              CHANNEL_G : CHANNEL_A;
  
 -      if (sc->sc_nvaps)
 -              return -ENOBUFS;
 +              /* set h/w channel */
 +              if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
 +                      DPRINTF(sc, ATH_DBG_FATAL,
 +                              "%s: Unable to set channel\n",
 +                              __func__);
  
 -      switch (conf->type) {
 -      case IEEE80211_IF_TYPE_STA:
 -              ic_opmode = ATH9K_M_STA;
 -              break;
 -      case IEEE80211_IF_TYPE_IBSS:
 -              ic_opmode = ATH9K_M_IBSS;
 -              break;
 -      default:
 -              DPRINTF(sc, ATH_DBG_FATAL,
 -                      "%s: Only STA and IBSS are supported currently\n",
 -                      __func__);
 -              return -EOPNOTSUPP;
 +              ath_rate_newstate(sc, avp);
 +              /* Update ratectrl about the new state */
 +              ath_rc_node_update(hw, avp->rc_node);
 +      } else {
 +              DPRINTF(sc, ATH_DBG_CONFIG,
 +              "%s: Bss Info DISSOC\n", __func__);
 +              sc->sc_curaid = 0;
        }
 +}
  
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a VAP of type: %d\n",
 -              __func__,
 -              ic_opmode);
 +void ath_get_beaconconfig(struct ath_softc *sc,
 +                        int if_id,
 +                        struct ath_beacon_config *conf)
 +{
 +      struct ieee80211_hw *hw = sc->hw;
  
 -      error = ath_vap_attach(sc, 0, conf->vif, ic_opmode);
 -      if (error) {
 -              DPRINTF(sc, ATH_DBG_FATAL,
 -                      "%s: Unable to attach vap, error: %d\n",
 -                      __func__, error);
 -              return error;
 -      }
 +      /* fill in beacon config data */
  
 -      return 0;
 +      conf->beacon_interval = hw->conf.beacon_int;
 +      conf->listen_interval = 100;
 +      conf->dtim_count = 1;
 +      conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
  }
  
 -static void ath9k_remove_interface(struct ieee80211_hw *hw,
 -                                 struct ieee80211_if_init_conf *conf)
 +void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 +                   struct ath_xmit_status *tx_status, struct ath_node *an)
  {
 -      struct ath_softc *sc = hw->priv;
 -      struct ath_vap *avp;
 -      int error;
 +      struct ieee80211_hw *hw = sc->hw;
 +      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
  
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__);
 +      DPRINTF(sc, ATH_DBG_XMIT,
 +              "%s: TX complete: skb: %p\n", __func__, skb);
  
 -      avp = sc->sc_vaps[0];
 -      if (avp == NULL) {
 -              DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
 -                      __func__);
 -              return;
 +      if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
 +              tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
 +              /* free driver's private data area of tx_info */
 +              if (tx_info->driver_data[0] != NULL)
 +                      kfree(tx_info->driver_data[0]);
 +                      tx_info->driver_data[0] = NULL;
        }
  
 -#ifdef CONFIG_SLOW_ANT_DIV
 -      ath_slow_ant_div_stop(&sc->sc_antdiv);
 -#endif
 -
 -      /* Update ratectrl */
 -      ath_rate_newstate(sc, avp);
 +      if (tx_status->flags & ATH_TX_BAR) {
 +              tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 +              tx_status->flags &= ~ATH_TX_BAR;
 +      }
  
 -      /* Reclaim beacon resources */
 -      if (sc->sc_opmode == ATH9K_M_HOSTAP || sc->sc_opmode == ATH9K_M_IBSS) {
 -              ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
 -              ath_beacon_return(sc, avp);
 +      if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
 +              if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
 +                      /* Frame was not ACKed, but an ACK was expected */
 +                      tx_info->status.excessive_retries = 1;
 +              }
 +      } else {
 +              /* Frame was ACKed */
 +              tx_info->flags |= IEEE80211_TX_STAT_ACK;
        }
  
 -      /* Set interrupt mask */
 -      sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
 -      ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
 -      sc->sc_beacons = 0;
 +      tx_info->status.retry_count = tx_status->retries;
  
 -      error = ath_vap_detach(sc, 0);
 -      if (error)
 -              DPRINTF(sc, ATH_DBG_FATAL,
 -                      "%s: Unable to detach vap, error: %d\n",
 -                      __func__, error);
 +      ieee80211_tx_status(hw, skb);
 +      if (an)
 +              ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
  }
  
 -static int ath9k_config(struct ieee80211_hw *hw,
 -                      struct ieee80211_conf *conf)
 +int _ath_rx_indicate(struct ath_softc *sc,
 +                   struct sk_buff *skb,
 +                   struct ath_recv_status *status,
 +                   u16 keyix)
  {
 -      struct ath_softc *sc = hw->priv;
 -      struct ieee80211_channel *curchan = hw->conf.channel;
 -      int pos;
 -
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
 -              __func__,
 -              curchan->center_freq);
 +      struct ieee80211_hw *hw = sc->hw;
 +      struct ath_node *an = NULL;
 +      struct ieee80211_rx_status rx_status;
 +      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 +      int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 +      int padsize;
 +      enum ATH_RX_TYPE st;
  
 -      pos = ath_get_channel(sc, curchan);
 -      if (pos == -1) {
 -              DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
 -              return -EINVAL;
 +      /* see if any padding is done by the hw and remove it */
 +      if (hdrlen & 3) {
 +              padsize = hdrlen % 4;
 +              memmove(skb->data + padsize, skb->data, hdrlen);
 +              skb_pull(skb, padsize);
        }
  
 -      sc->sc_ah->ah_channels[pos].chanmode =
 -              (curchan->band == IEEE80211_BAND_2GHZ) ?
 -              CHANNEL_G : CHANNEL_A;
 +      /* Prepare rx status */
 +      ath9k_rx_prepare(sc, skb, status, &rx_status);
  
 -      if (sc->sc_curaid && hw->conf.ht_conf.ht_supported)
 -              sc->sc_ah->ah_channels[pos].chanmode =
 -                      ath_get_extchanmode(sc, curchan);
 +      if (!(keyix == ATH9K_RXKEYIX_INVALID) &&
 +          !(status->flags & ATH_RX_DECRYPT_ERROR)) {
 +              rx_status.flag |= RX_FLAG_DECRYPTED;
 +      } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
 +                 && !(status->flags & ATH_RX_DECRYPT_ERROR)
 +                 && skb->len >= hdrlen + 4) {
 +              keyix = skb->data[hdrlen + 3] >> 6;
  
 -      sc->sc_config.txpowlimit = 2 * conf->power_level;
 +              if (test_bit(keyix, sc->sc_keymap))
 +                      rx_status.flag |= RX_FLAG_DECRYPTED;
 +      }
  
 -      /* set h/w channel */
 -      if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
 -              DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n",
 -                      __func__);
 +      spin_lock_bh(&sc->node_lock);
 +      an = ath_node_find(sc, hdr->addr2);
 +      spin_unlock_bh(&sc->node_lock);
 +
 +      if (an) {
 +              ath_rx_input(sc, an,
 +                           hw->conf.ht_conf.ht_supported,
 +                           skb, status, &st);
 +      }
 +      if (!an || (st != ATH_RX_CONSUMED))
 +              __ieee80211_rx(hw, skb, &rx_status);
  
        return 0;
  }
  
 -static int ath9k_config_interface(struct ieee80211_hw *hw,
 -                                struct ieee80211_vif *vif,
 -                                struct ieee80211_if_conf *conf)
 +int ath_rx_subframe(struct ath_node *an,
 +                  struct sk_buff *skb,
 +                  struct ath_recv_status *status)
  {
 -      struct ath_softc *sc = hw->priv;
 -      struct ath_vap *avp;
 -      u32 rfilt = 0;
 -      int error, i;
 -      DECLARE_MAC_BUF(mac);
 +      struct ath_softc *sc = an->an_sc;
 +      struct ieee80211_hw *hw = sc->hw;
 +      struct ieee80211_rx_status rx_status;
  
 -      avp = sc->sc_vaps[0];
 -      if (avp == NULL) {
 -              DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
 -                      __func__);
 -              return -EINVAL;
 +      /* Prepare rx status */
 +      ath9k_rx_prepare(sc, skb, status, &rx_status);
 +      if (!(status->flags & ATH_RX_DECRYPT_ERROR))
 +              rx_status.flag |= RX_FLAG_DECRYPTED;
 +
 +      __ieee80211_rx(hw, skb, &rx_status);
 +
 +      return 0;
 +}
 +
 +/********************************/
 +/*     LED functions          */
 +/********************************/
 +
 +static void ath_led_brightness(struct led_classdev *led_cdev,
 +                             enum led_brightness brightness)
 +{
 +      struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
 +      struct ath_softc *sc = led->sc;
 +
 +      switch (brightness) {
 +      case LED_OFF:
 +              if (led->led_type == ATH_LED_ASSOC ||
 +                  led->led_type == ATH_LED_RADIO)
 +                      sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
 +              ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
 +                              (led->led_type == ATH_LED_RADIO) ? 1 :
 +                              !!(sc->sc_flags & SC_OP_LED_ASSOCIATED));
 +              break;
 +      case LED_FULL:
 +              if (led->led_type == ATH_LED_ASSOC)
 +                      sc->sc_flags |= SC_OP_LED_ASSOCIATED;
 +              ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
 +              break;
 +      default:
 +              break;
        }
 +}
  
 -      if ((conf->changed & IEEE80211_IFCC_BSSID) &&
 -          !is_zero_ether_addr(conf->bssid)) {
 -              switch (vif->type) {
 -              case IEEE80211_IF_TYPE_STA:
 -              case IEEE80211_IF_TYPE_IBSS:
 -                      /* Update ratectrl about the new state */
 -                      ath_rate_newstate(sc, avp);
 +static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
 +                          char *trigger)
 +{
 +      int ret;
  
 -                      /* Set rx filter */
 -                      rfilt = ath_calcrxfilter(sc);
 -                      ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
 +      led->sc = sc;
 +      led->led_cdev.name = led->name;
 +      led->led_cdev.default_trigger = trigger;
 +      led->led_cdev.brightness_set = ath_led_brightness;
  
 -                      /* Set BSSID */
 -                      memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN);
 -                      sc->sc_curaid = 0;
 -                      ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
 -                                             sc->sc_curaid);
 +      ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
 +      if (ret)
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "Failed to register led:%s", led->name);
 +      else
 +              led->registered = 1;
 +      return ret;
 +}
  
 -                      /* Set aggregation protection mode parameters */
 -                      sc->sc_config.ath_aggr_prot = 0;
 +static void ath_unregister_led(struct ath_led *led)
 +{
 +      if (led->registered) {
 +              led_classdev_unregister(&led->led_cdev);
 +              led->registered = 0;
 +      }
 +}
  
 -                      /*
 -                       * Reset our TSF so that its value is lower than the
 -                       * beacon that we are trying to catch.
 -                       * Only then hw will update its TSF register with the
 -                       * new beacon. Reset the TSF before setting the BSSID
 -                       * to avoid allowing in any frames that would update
 -                       * our TSF only to have us clear it
 -                       * immediately thereafter.
 -                       */
 -                      ath9k_hw_reset_tsf(sc->sc_ah);
 +static void ath_deinit_leds(struct ath_softc *sc)
 +{
 +      ath_unregister_led(&sc->assoc_led);
 +      sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
 +      ath_unregister_led(&sc->tx_led);
 +      ath_unregister_led(&sc->rx_led);
 +      ath_unregister_led(&sc->radio_led);
 +      ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
 +}
  
 -                      /* Disable BMISS interrupt when we're not associated */
 -                      ath9k_hw_set_interrupts(sc->sc_ah,
 -                                      sc->sc_imask &
 -                                      ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS));
 -                      sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
 +static void ath_init_leds(struct ath_softc *sc)
 +{
 +      char *trigger;
 +      int ret;
 +
 +      /* Configure gpio 1 for output */
 +      ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
 +                          AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 +      /* LED off, active low */
 +      ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
 +
 +      trigger = ieee80211_get_radio_led_name(sc->hw);
 +      snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
 +              "ath9k-%s:radio", wiphy_name(sc->hw->wiphy));
 +      ret = ath_register_led(sc, &sc->radio_led, trigger);
 +      sc->radio_led.led_type = ATH_LED_RADIO;
 +      if (ret)
 +              goto fail;
  
 -                      DPRINTF(sc, ATH_DBG_CONFIG,
 -                              "%s: RX filter 0x%x bssid %s aid 0x%x\n",
 -                              __func__, rfilt,
 -                              print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
 +      trigger = ieee80211_get_assoc_led_name(sc->hw);
 +      snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
 +              "ath9k-%s:assoc", wiphy_name(sc->hw->wiphy));
 +      ret = ath_register_led(sc, &sc->assoc_led, trigger);
 +      sc->assoc_led.led_type = ATH_LED_ASSOC;
 +      if (ret)
 +              goto fail;
  
 -                      /* need to reconfigure the beacon */
 -                      sc->sc_beacons = 0;
 +      trigger = ieee80211_get_tx_led_name(sc->hw);
 +      snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
 +              "ath9k-%s:tx", wiphy_name(sc->hw->wiphy));
 +      ret = ath_register_led(sc, &sc->tx_led, trigger);
 +      sc->tx_led.led_type = ATH_LED_TX;
 +      if (ret)
 +              goto fail;
  
 -                      break;
 -              default:
 -                      break;
 -              }
 -      }
 +      trigger = ieee80211_get_rx_led_name(sc->hw);
 +      snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
 +              "ath9k-%s:rx", wiphy_name(sc->hw->wiphy));
 +      ret = ath_register_led(sc, &sc->rx_led, trigger);
 +      sc->rx_led.led_type = ATH_LED_RX;
 +      if (ret)
 +              goto fail;
  
 -      if ((conf->changed & IEEE80211_IFCC_BEACON) &&
 -          (vif->type == IEEE80211_IF_TYPE_IBSS)) {
 -              /*
 -               * Allocate and setup the beacon frame.
 -               *
 -               * Stop any previous beacon DMA.  This may be
 -               * necessary, for example, when an ibss merge
 -               * causes reconfiguration; we may be called
 -               * with beacon transmission active.
 -               */
 -              ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
 +      return;
  
 -              error = ath_beacon_alloc(sc, 0);
 -              if (error != 0)
 -                      return error;
 +fail:
 +      ath_deinit_leds(sc);
 +}
  
 -              ath_beacon_sync(sc, 0);
 +#ifdef CONFIG_RFKILL
 +/*******************/
 +/*    Rfkill     */
 +/*******************/
 +
 +static void ath_radio_enable(struct ath_softc *sc)
 +{
 +      struct ath_hal *ah = sc->sc_ah;
 +      int status;
 +
 +      spin_lock_bh(&sc->sc_resetlock);
 +      if (!ath9k_hw_reset(ah, ah->ah_curchan,
 +                          sc->sc_ht_info.tx_chan_width,
 +                          sc->sc_tx_chainmask,
 +                          sc->sc_rx_chainmask,
 +                          sc->sc_ht_extprotspacing,
 +                          false, &status)) {
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: unable to reset channel %u (%uMhz) "
 +                      "flags 0x%x hal status %u\n", __func__,
 +                      ath9k_hw_mhz2ieee(ah,
 +                                        ah->ah_curchan->channel,
 +                                        ah->ah_curchan->channelFlags),
 +                      ah->ah_curchan->channel,
 +                      ah->ah_curchan->channelFlags, status);
        }
 +      spin_unlock_bh(&sc->sc_resetlock);
  
 -      /* Check for WLAN_CAPABILITY_PRIVACY ? */
 -      if ((avp->av_opmode != IEEE80211_IF_TYPE_STA)) {
 -              for (i = 0; i < IEEE80211_WEP_NKID; i++)
 -                      if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
 -                              ath9k_hw_keysetmac(sc->sc_ah,
 -                                                 (u16)i,
 -                                                 sc->sc_curbssid);
 +      ath_update_txpow(sc);
 +      if (ath_startrecv(sc) != 0) {
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: unable to restart recv logic\n", __func__);
 +              return;
        }
  
 -      /* Only legacy IBSS for now */
 -      if (vif->type == IEEE80211_IF_TYPE_IBSS)
 -              ath_update_chainmask(sc, 0);
 +      if (sc->sc_flags & SC_OP_BEACONS)
 +              ath_beacon_config(sc, ATH_IF_ID_ANY);   /* restart beacons */
  
 -      return 0;
 -}
 +      /* Re-Enable  interrupts */
 +      ath9k_hw_set_interrupts(ah, sc->sc_imask);
  
 -#define SUPPORTED_FILTERS                     \
 -      (FIF_PROMISC_IN_BSS |                   \
 -      FIF_ALLMULTI |                          \
 -      FIF_CONTROL |                           \
 -      FIF_OTHER_BSS |                         \
 -      FIF_BCN_PRBRESP_PROMISC |               \
 -      FIF_FCSFAIL)
 +      /* Enable LED */
 +      ath9k_hw_cfg_output(ah, ATH_LED_PIN,
 +                          AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 +      ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
  
 -/* Accept unicast, bcast and mcast frames */
 +      ieee80211_wake_queues(sc->hw);
 +}
  
 -static void ath9k_configure_filter(struct ieee80211_hw *hw,
 -                                 unsigned int changed_flags,
 -                                 unsigned int *total_flags,
 -                                 int mc_count,
 -                                 struct dev_mc_list *mclist)
 +static void ath_radio_disable(struct ath_softc *sc)
  {
 -      struct ath_softc *sc = hw->priv;
 +      struct ath_hal *ah = sc->sc_ah;
 +      int status;
  
 -      changed_flags &= SUPPORTED_FILTERS;
 -      *total_flags &= SUPPORTED_FILTERS;
  
 -      if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
 -              if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
 -                      ath_scan_start(sc);
 -              else
 -                      ath_scan_end(sc);
 +      ieee80211_stop_queues(sc->hw);
 +
 +      /* Disable LED */
 +      ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1);
 +      ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN);
 +
 +      /* Disable interrupts */
 +      ath9k_hw_set_interrupts(ah, 0);
 +
 +      ath_draintxq(sc, false);        /* clear pending tx frames */
 +      ath_stoprecv(sc);               /* turn off frame recv */
 +      ath_flushrecv(sc);              /* flush recv queue */
 +
 +      spin_lock_bh(&sc->sc_resetlock);
 +      if (!ath9k_hw_reset(ah, ah->ah_curchan,
 +                          sc->sc_ht_info.tx_chan_width,
 +                          sc->sc_tx_chainmask,
 +                          sc->sc_rx_chainmask,
 +                          sc->sc_ht_extprotspacing,
 +                          false, &status)) {
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: unable to reset channel %u (%uMhz) "
 +                      "flags 0x%x hal status %u\n", __func__,
 +                      ath9k_hw_mhz2ieee(ah,
 +                              ah->ah_curchan->channel,
 +                              ah->ah_curchan->channelFlags),
 +                      ah->ah_curchan->channel,
 +                      ah->ah_curchan->channelFlags, status);
        }
 +      spin_unlock_bh(&sc->sc_resetlock);
 +
 +      ath9k_hw_phy_disable(ah);
 +      ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
  }
  
 -static void ath9k_sta_notify(struct ieee80211_hw *hw,
 -                           struct ieee80211_vif *vif,
 -                           enum sta_notify_cmd cmd,
 -                           const u8 *addr)
 +static bool ath_is_rfkill_set(struct ath_softc *sc)
  {
 -      struct ath_softc *sc = hw->priv;
 -      struct ath_node *an;
 -      unsigned long flags;
 -      DECLARE_MAC_BUF(mac);
 +      struct ath_hal *ah = sc->sc_ah;
  
 -      spin_lock_irqsave(&sc->node_lock, flags);
 -      an = ath_node_find(sc, (u8 *) addr);
 -      spin_unlock_irqrestore(&sc->node_lock, flags);
 +      return ath9k_hw_gpio_get(ah, ah->ah_rfkill_gpio) ==
 +                                ah->ah_rfkill_polarity;
 +}
  
 -      switch (cmd) {
 -      case STA_NOTIFY_ADD:
 -              spin_lock_irqsave(&sc->node_lock, flags);
 -              if (!an) {
 -                      ath_node_attach(sc, (u8 *)addr, 0);
 -                      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n",
 -                              __func__,
 -                              print_mac(mac, addr));
 +/* h/w rfkill poll function */
 +static void ath_rfkill_poll(struct work_struct *work)
 +{
 +      struct ath_softc *sc = container_of(work, struct ath_softc,
 +                                          rf_kill.rfkill_poll.work);
 +      bool radio_on;
 +
 +      if (sc->sc_flags & SC_OP_INVALID)
 +              return;
 +
 +      radio_on = !ath_is_rfkill_set(sc);
 +
 +      /*
 +       * enable/disable radio only when there is a
 +       * state change in RF switch
 +       */
 +      if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) {
 +              enum rfkill_state state;
 +
 +              if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) {
 +                      state = radio_on ? RFKILL_STATE_SOFT_BLOCKED
 +                              : RFKILL_STATE_HARD_BLOCKED;
 +              } else if (radio_on) {
 +                      ath_radio_enable(sc);
 +                      state = RFKILL_STATE_UNBLOCKED;
                } else {
 -                      ath_node_get(sc, (u8 *)addr);
 +                      ath_radio_disable(sc);
 +                      state = RFKILL_STATE_HARD_BLOCKED;
                }
 -              spin_unlock_irqrestore(&sc->node_lock, flags);
 -              break;
 -      case STA_NOTIFY_REMOVE:
 -              if (!an)
 -                      DPRINTF(sc, ATH_DBG_FATAL,
 -                              "%s: Removal of a non-existent node\n",
 -                              __func__);
 -              else {
 -                      ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
 -                      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n",
 -                              __func__,
 -                              print_mac(mac, addr));
 +
 +              if (state == RFKILL_STATE_HARD_BLOCKED)
 +                      sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED;
 +              else
 +                      sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED;
 +
 +              rfkill_force_state(sc->rf_kill.rfkill, state);
 +      }
 +
 +      queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll,
 +                         msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL));
 +}
 +
 +/* s/w rfkill handler */
 +static int ath_sw_toggle_radio(void *data, enum rfkill_state state)
 +{
 +      struct ath_softc *sc = data;
 +
 +      switch (state) {
 +      case RFKILL_STATE_SOFT_BLOCKED:
 +              if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED |
 +                  SC_OP_RFKILL_SW_BLOCKED)))
 +                      ath_radio_disable(sc);
 +              sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED;
 +              return 0;
 +      case RFKILL_STATE_UNBLOCKED:
 +              if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) {
 +                      sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED;
 +                      if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) {
 +                              DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the"
 +                                      "radio as it is disabled by h/w \n");
 +                              return -EPERM;
 +                      }
 +                      ath_radio_enable(sc);
                }
 -              break;
 +              return 0;
        default:
 -              break;
 +              return -EINVAL;
        }
  }
  
 -static int ath9k_conf_tx(struct ieee80211_hw *hw,
 -                       u16 queue,
 -                       const struct ieee80211_tx_queue_params *params)
 +/* Init s/w rfkill */
 +static int ath_init_sw_rfkill(struct ath_softc *sc)
  {
 -      struct ath_softc *sc = hw->priv;
 -      struct ath9k_tx_queue_info qi;
 -      int ret = 0, qnum;
 -
 -      if (queue >= WME_NUM_AC)
 -              return 0;
 +      sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy),
 +                                           RFKILL_TYPE_WLAN);
 +      if (!sc->rf_kill.rfkill) {
 +              DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n");
 +              return -ENOMEM;
 +      }
  
 -      qi.tqi_aifs = params->aifs;
 -      qi.tqi_cwmin = params->cw_min;
 -      qi.tqi_cwmax = params->cw_max;
 -      qi.tqi_burstTime = params->txop;
 -      qnum = ath_get_hal_qnum(queue, sc);
 +      snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
 +              "ath9k-%s:rfkill", wiphy_name(sc->hw->wiphy));
 +      sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name;
 +      sc->rf_kill.rfkill->data = sc;
 +      sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
 +      sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
 +      sc->rf_kill.rfkill->user_claim_unsupported = 1;
  
 -      DPRINTF(sc, ATH_DBG_CONFIG,
 -              "%s: Configure tx [queue/halq] [%d/%d],  "
 -              "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
 -              __func__,
 -              queue,
 -              qnum,
 -              params->aifs,
 -              params->cw_min,
 -              params->cw_max,
 -              params->txop);
 +      return 0;
 +}
  
 -      ret = ath_txq_update(sc, qnum, &qi);
 -      if (ret)
 -              DPRINTF(sc, ATH_DBG_FATAL,
 -                      "%s: TXQ Update failed\n", __func__);
 +/* Deinitialize rfkill */
 +static void ath_deinit_rfkill(struct ath_softc *sc)
 +{
 +      if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
 +              cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
  
 -      return ret;
 +      if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) {
 +              rfkill_unregister(sc->rf_kill.rfkill);
 +              sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED;
 +              sc->rf_kill.rfkill = NULL;
 +      }
  }
 +#endif /* CONFIG_RFKILL */
  
 -static int ath9k_set_key(struct ieee80211_hw *hw,
 -                       enum set_key_cmd cmd,
 -                       const u8 *local_addr,
 -                       const u8 *addr,
 -                       struct ieee80211_key_conf *key)
 +static int ath_detach(struct ath_softc *sc)
  {
 -      struct ath_softc *sc = hw->priv;
 -      int ret = 0;
 +      struct ieee80211_hw *hw = sc->hw;
  
 -      DPRINTF(sc, ATH_DBG_KEYCACHE, " %s: Set HW Key\n", __func__);
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
  
 -      switch (cmd) {
 -      case SET_KEY:
 -              ret = ath_key_config(sc, addr, key);
 -              if (!ret) {
 -                      set_bit(key->keyidx, sc->sc_keymap);
 -                      key->hw_key_idx = key->keyidx;
 -                      /* push IV and Michael MIC generation to stack */
 -                      key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 -                      if (key->alg == ALG_TKIP)
 -                              key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
 -              }
 -              break;
 -      case DISABLE_KEY:
 -              ath_key_delete(sc, key);
 -              clear_bit(key->keyidx, sc->sc_keymap);
 -              break;
 -      default:
 -              ret = -EINVAL;
 -      }
 +      /* Deinit LED control */
 +      ath_deinit_leds(sc);
  
 -      return ret;
 -}
 +#ifdef CONFIG_RFKILL
 +      /* deinit rfkill */
 +      ath_deinit_rfkill(sc);
 +#endif
  
 -static void ath9k_ht_conf(struct ath_softc *sc,
 -                        struct ieee80211_bss_conf *bss_conf)
 -{
 -#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
 -      struct ath_ht_info *ht_info = &sc->sc_ht_info;
 +      /* Unregister hw */
  
 -      if (bss_conf->assoc_ht) {
 -              ht_info->ext_chan_offset =
 -                      bss_conf->ht_bss_conf->bss_cap &
 -                              IEEE80211_HT_IE_CHA_SEC_OFFSET;
 +      ieee80211_unregister_hw(hw);
  
 -              if (!(bss_conf->ht_conf->cap &
 -                      IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
 -                          (bss_conf->ht_bss_conf->bss_cap &
 -                              IEEE80211_HT_IE_CHA_WIDTH))
 -                      ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
 -              else
 -                      ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
 +      /* unregister Rate control */
 +      ath_rate_control_unregister();
  
 -              ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
 -              ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
 -                                      bss_conf->ht_conf->ampdu_factor);
 -              ht_info->mpdudensity =
 -                      parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
 +      /* tx/rx cleanup */
  
 -      }
 +      ath_rx_cleanup(sc);
 +      ath_tx_cleanup(sc);
  
 -#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
 +      /* Deinit */
 +
 +      ath_deinit(sc);
 +
 +      return 0;
  }
  
 -static void ath9k_bss_assoc_info(struct ath_softc *sc,
 -                               struct ieee80211_bss_conf *bss_conf)
 +static int ath_attach(u16 devid,
 +                    struct ath_softc *sc)
  {
        struct ieee80211_hw *hw = sc->hw;
 -      struct ieee80211_channel *curchan = hw->conf.channel;
 -      struct ath_vap *avp;
 -      int pos;
 -      DECLARE_MAC_BUF(mac);
 +      int error = 0;
  
 -      if (bss_conf->assoc) {
 -              DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n",
 -                      __func__,
 -                      bss_conf->aid);
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__);
  
 -              avp = sc->sc_vaps[0];
 -              if (avp == NULL) {
 -                      DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
 -                              __func__);
 -                      return;
 -              }
 +      error = ath_init(devid, sc);
 +      if (error != 0)
 +              return error;
  
 -              /* New association, store aid */
 -              if (avp->av_opmode == ATH9K_M_STA) {
 -                      sc->sc_curaid = bss_conf->aid;
 -                      ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
 -                                             sc->sc_curaid);
 -              }
 +      /* Init nodes */
  
 -              /* Configure the beacon */
 -              ath_beacon_config(sc, 0);
 -              sc->sc_beacons = 1;
 +      INIT_LIST_HEAD(&sc->node_list);
 +      spin_lock_init(&sc->node_lock);
  
 -              /* Reset rssi stats */
 -              sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
 -              sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
 -              sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
 -              sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
 +      /* get mac address from hardware and set in mac80211 */
  
 -              /* Update chainmask */
 -              ath_update_chainmask(sc, bss_conf->assoc_ht);
 +      SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
  
 -              DPRINTF(sc, ATH_DBG_CONFIG,
 -                      "%s: bssid %s aid 0x%x\n",
 -                      __func__,
 -                      print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
 +      /* setup channels and rates */
  
 -              DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
 -                      __func__,
 -                      curchan->center_freq);
 +      sc->sbands[IEEE80211_BAND_2GHZ].channels =
 +              sc->channels[IEEE80211_BAND_2GHZ];
 +      sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
 +              sc->rates[IEEE80211_BAND_2GHZ];
 +      sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
  
 -              pos = ath_get_channel(sc, curchan);
 -              if (pos == -1) {
 -                      DPRINTF(sc, ATH_DBG_FATAL,
 -                              "%s: Invalid channel\n", __func__);
 -                      return;
 -              }
 +      if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
 +              /* Setup HT capabilities for 2.4Ghz*/
 +              setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
  
 -              if (hw->conf.ht_conf.ht_supported)
 -                      sc->sc_ah->ah_channels[pos].chanmode =
 -                              ath_get_extchanmode(sc, curchan);
 -              else
 -                      sc->sc_ah->ah_channels[pos].chanmode =
 -                              (curchan->band == IEEE80211_BAND_2GHZ) ?
 -                              CHANNEL_G : CHANNEL_A;
 +      hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 +              &sc->sbands[IEEE80211_BAND_2GHZ];
  
 -              /* set h/w channel */
 -              if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
 -                      DPRINTF(sc, ATH_DBG_FATAL,
 -                              "%s: Unable to set channel\n",
 -                              __func__);
 +      if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
 +              sc->sbands[IEEE80211_BAND_5GHZ].channels =
 +                      sc->channels[IEEE80211_BAND_5GHZ];
 +              sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
 +                      sc->rates[IEEE80211_BAND_5GHZ];
 +              sc->sbands[IEEE80211_BAND_5GHZ].band =
 +                      IEEE80211_BAND_5GHZ;
  
 -              ath_rate_newstate(sc, avp);
 -              /* Update ratectrl about the new state */
 -              ath_rc_node_update(hw, avp->rc_node);
 -      } else {
 -              DPRINTF(sc, ATH_DBG_CONFIG,
 -              "%s: Bss Info DISSOC\n", __func__);
 -              sc->sc_curaid = 0;
 +              if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
 +                      /* Setup HT capabilities for 5Ghz*/
 +                      setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
 +
 +              hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 +                      &sc->sbands[IEEE80211_BAND_5GHZ];
        }
 -}
  
 -static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 -                                 struct ieee80211_vif *vif,
 -                                 struct ieee80211_bss_conf *bss_conf,
 -                                 u32 changed)
 -{
 -      struct ath_softc *sc = hw->priv;
 +      /* FIXME: Have to figure out proper hw init values later */
  
 -      if (changed & BSS_CHANGED_ERP_PREAMBLE) {
 -              DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed PREAMBLE %d\n",
 -                      __func__,
 -                      bss_conf->use_short_preamble);
 -              if (bss_conf->use_short_preamble)
 -                      sc->sc_flags |= ATH_PREAMBLE_SHORT;
 -              else
 -                      sc->sc_flags &= ~ATH_PREAMBLE_SHORT;
 -      }
 +      hw->queues = 4;
 +      hw->ampdu_queues = 1;
  
 -      if (changed & BSS_CHANGED_ERP_CTS_PROT) {
 -              DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed CTS PROT %d\n",
 -                      __func__,
 -                      bss_conf->use_cts_prot);
 -              if (bss_conf->use_cts_prot &&
 -                  hw->conf.channel->band != IEEE80211_BAND_5GHZ)
 -                      sc->sc_flags |= ATH_PROTECT_ENABLE;
 -              else
 -                      sc->sc_flags &= ~ATH_PROTECT_ENABLE;
 +      /* Register rate control */
 +      hw->rate_control_algorithm = "ath9k_rate_control";
 +      error = ath_rate_control_register();
 +      if (error != 0) {
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: Unable to register rate control "
 +                      "algorithm:%d\n", __func__, error);
 +              ath_rate_control_unregister();
 +              goto bad;
        }
  
 -      if (changed & BSS_CHANGED_HT) {
 -              DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n",
 -                      __func__,
 -                      bss_conf->assoc_ht);
 -              ath9k_ht_conf(sc, bss_conf);
 +      error = ieee80211_register_hw(hw);
 +      if (error != 0) {
 +              ath_rate_control_unregister();
 +              goto bad;
        }
  
 -      if (changed & BSS_CHANGED_ASSOC) {
 -              DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
 -                      __func__,
 -                      bss_conf->assoc);
 -              ath9k_bss_assoc_info(sc, bss_conf);
 -      }
 -}
 +      /* Initialize LED control */
 +      ath_init_leds(sc);
  
 -static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
 -{
 -      u64 tsf;
 -      struct ath_softc *sc = hw->priv;
 -      struct ath_hal *ah = sc->sc_ah;
 +#ifdef CONFIG_RFKILL
 +      /* Initialze h/w Rfkill */
 +      if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
 +              INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
  
 -      tsf = ath9k_hw_gettsf64(ah);
 +      /* Initialize s/w rfkill */
 +      if (ath_init_sw_rfkill(sc))
 +              goto detach;
 +#endif
  
 -      return tsf;
 -}
 +      /* initialize tx/rx engine */
  
 -static void ath9k_reset_tsf(struct ieee80211_hw *hw)
 -{
 -      struct ath_softc *sc = hw->priv;
 -      struct ath_hal *ah = sc->sc_ah;
 +      error = ath_tx_init(sc, ATH_TXBUF);
 +      if (error != 0)
 +              goto detach;
  
 -      ath9k_hw_reset_tsf(ah);
 +      error = ath_rx_init(sc, ATH_RXBUF);
 +      if (error != 0)
 +              goto detach;
 +
 +      return 0;
 +detach:
 +      ath_detach(sc);
 +bad:
 +      return error;
  }
  
 -static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 -                     enum ieee80211_ampdu_mlme_action action,
 -                     const u8 *addr,
 -                     u16 tid,
 -                     u16 *ssn)
 +static int ath9k_start(struct ieee80211_hw *hw)
  {
        struct ath_softc *sc = hw->priv;
 -      int ret = 0;
 +      struct ieee80211_channel *curchan = hw->conf.channel;
 +      int error = 0, pos;
  
 -      switch (action) {
 -      case IEEE80211_AMPDU_RX_START:
 -              ret = ath_rx_aggr_start(sc, addr, tid, ssn);
 -              if (ret < 0)
 -                      DPRINTF(sc, ATH_DBG_FATAL,
 -                              "%s: Unable to start RX aggregation\n",
 -                              __func__);
 -              break;
 -      case IEEE80211_AMPDU_RX_STOP:
 -              ret = ath_rx_aggr_stop(sc, addr, tid);
 -              if (ret < 0)
 -                      DPRINTF(sc, ATH_DBG_FATAL,
 -                              "%s: Unable to stop RX aggregation\n",
 -                              __func__);
 -              break;
 -      case IEEE80211_AMPDU_TX_START:
 -              ret = ath_tx_aggr_start(sc, addr, tid, ssn);
 -              if (ret < 0)
 -                      DPRINTF(sc, ATH_DBG_FATAL,
 -                              "%s: Unable to start TX aggregation\n",
 -                              __func__);
 -              else
 -                      ieee80211_start_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid);
 -              break;
 -      case IEEE80211_AMPDU_TX_STOP:
 -              ret = ath_tx_aggr_stop(sc, addr, tid);
 -              if (ret < 0)
 -                      DPRINTF(sc, ATH_DBG_FATAL,
 -                              "%s: Unable to stop TX aggregation\n",
 -                              __func__);
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with "
 +              "initial channel: %d MHz\n", __func__, curchan->center_freq);
  
 -              ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid);
 -              break;
 -      default:
 +      /* setup initial channel */
 +
 +      pos = ath_get_channel(sc, curchan);
 +      if (pos == -1) {
 +              DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
 +              return -EINVAL;
 +      }
 +
 +      sc->sc_ah->ah_channels[pos].chanmode =
 +              (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
 +
 +      /* open ath_dev */
 +      error = ath_open(sc, &sc->sc_ah->ah_channels[pos]);
 +      if (error) {
                DPRINTF(sc, ATH_DBG_FATAL,
 -                      "%s: Unknown AMPDU action\n", __func__);
 +                      "%s: Unable to complete ath_open\n", __func__);
 +              return error;
        }
  
 -      return ret;
 +#ifdef CONFIG_RFKILL
 +      /* Start rfkill polling */
 +      if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
 +              queue_delayed_work(sc->hw->workqueue,
 +                                 &sc->rf_kill.rfkill_poll, 0);
 +
 +      if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
 +              if (rfkill_register(sc->rf_kill.rfkill)) {
 +                      DPRINTF(sc, ATH_DBG_FATAL,
 +                                      "Unable to register rfkill\n");
 +                      rfkill_free(sc->rf_kill.rfkill);
 +
 +                      /* Deinitialize the device */
 +                      if (sc->pdev->irq)
 +                              free_irq(sc->pdev->irq, sc);
 +                      ath_detach(sc);
 +                      pci_iounmap(sc->pdev, sc->mem);
 +                      pci_release_region(sc->pdev, 0);
 +                      pci_disable_device(sc->pdev);
 +                      ieee80211_free_hw(hw);
 +                      return -EIO;
 +              } else {
 +                      sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
 +              }
 +      }
 +#endif
 +
 +      ieee80211_wake_queues(hw);
 +      return 0;
  }
  
 -static struct ieee80211_ops ath9k_ops = {
 -      .tx                 = ath9k_tx,
 -      .start              = ath9k_start,
 -      .stop               = ath9k_stop,
 -      .add_interface      = ath9k_add_interface,
 -      .remove_interface   = ath9k_remove_interface,
 -      .config             = ath9k_config,
 -      .config_interface   = ath9k_config_interface,
 -      .configure_filter   = ath9k_configure_filter,
 -      .get_stats          = NULL,
 -      .sta_notify         = ath9k_sta_notify,
 -      .conf_tx            = ath9k_conf_tx,
 -      .get_tx_stats       = NULL,
 -      .bss_info_changed   = ath9k_bss_info_changed,
 -      .set_tim            = NULL,
 -      .set_key            = ath9k_set_key,
 -      .hw_scan            = NULL,
 -      .get_tkip_seq       = NULL,
 -      .set_rts_threshold  = NULL,
 -      .set_frag_threshold = NULL,
 -      .set_retry_limit    = NULL,
 -      .get_tsf            = ath9k_get_tsf,
 -      .reset_tsf          = ath9k_reset_tsf,
 -      .tx_last_beacon     = NULL,
 -      .ampdu_action       = ath9k_ampdu_action
 -};
 +static int ath9k_tx(struct ieee80211_hw *hw,
 +                  struct sk_buff *skb)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      int hdrlen, padsize;
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  
 -void ath_get_beaconconfig(struct ath_softc *sc,
 -                        int if_id,
 -                        struct ath_beacon_config *conf)
 +      /*
 +       * As a temporary workaround, assign seq# here; this will likely need
 +       * to be cleaned up to work better with Beacon transmission and virtual
 +       * BSSes.
 +       */
 +      if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 +              struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 +              if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
 +                      sc->seq_no += 0x10;
 +              hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
 +              hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
 +      }
 +
 +      /* Add the padding after the header if this is not already done */
 +      hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 +      if (hdrlen & 3) {
 +              padsize = hdrlen % 4;
 +              if (skb_headroom(skb) < padsize)
 +                      return -1;
 +              skb_push(skb, padsize);
 +              memmove(skb->data, skb->data + padsize, hdrlen);
 +      }
 +
 +      DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting packet, skb: %p\n",
 +              __func__,
 +              skb);
 +
 +      if (ath_tx_start(sc, skb) != 0) {
 +              DPRINTF(sc, ATH_DBG_XMIT, "%s: TX failed\n", __func__);
 +              dev_kfree_skb_any(skb);
 +              /* FIXME: Check for proper return value from ATH_DEV */
 +              return 0;
 +      }
 +
 +      return 0;
 +}
 +
 +static void ath9k_stop(struct ieee80211_hw *hw)
  {
 -      struct ieee80211_hw *hw = sc->hw;
 +      struct ath_softc *sc = hw->priv;
 +      int error;
  
 -      /* fill in beacon config data */
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__);
  
 -      conf->beacon_interval = hw->conf.beacon_int;
 -      conf->listen_interval = 100;
 -      conf->dtim_count = 1;
 -      conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
 +      error = ath_suspend(sc);
 +      if (error)
 +              DPRINTF(sc, ATH_DBG_CONFIG,
 +                      "%s: Device is no longer present\n", __func__);
 +
 +      ieee80211_stop_queues(hw);
 +
 +#ifdef CONFIG_RFKILL
 +      if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
 +              cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
 +#endif
  }
  
 -int ath_update_beacon(struct ath_softc *sc,
 -                    int if_id,
 -                    struct ath_beacon_offset *bo,
 -                    struct sk_buff *skb,
 -                    int mcast)
 +static int ath9k_add_interface(struct ieee80211_hw *hw,
 +                             struct ieee80211_if_init_conf *conf)
  {
 +      struct ath_softc *sc = hw->priv;
 +      int error, ic_opmode = 0;
 +
 +      /* Support only vap for now */
 +
 +      if (sc->sc_nvaps)
 +              return -ENOBUFS;
 +
 +      switch (conf->type) {
 +      case NL80211_IFTYPE_STATION:
 +              ic_opmode = ATH9K_M_STA;
 +              break;
 +      case NL80211_IFTYPE_ADHOC:
 +              ic_opmode = ATH9K_M_IBSS;
 +              break;
 +      case NL80211_IFTYPE_AP:
 +              ic_opmode = ATH9K_M_HOSTAP;
 +              break;
 +      default:
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: Interface type %d not yet supported\n",
 +                      __func__, conf->type);
 +              return -EOPNOTSUPP;
 +      }
 +
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a VAP of type: %d\n",
 +              __func__,
 +              ic_opmode);
 +
 +      error = ath_vap_attach(sc, 0, conf->vif, ic_opmode);
 +      if (error) {
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: Unable to attach vap, error: %d\n",
 +                      __func__, error);
 +              return error;
 +      }
 +
        return 0;
  }
  
 -void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 -                   struct ath_xmit_status *tx_status, struct ath_node *an)
 +static void ath9k_remove_interface(struct ieee80211_hw *hw,
 +                                 struct ieee80211_if_init_conf *conf)
  {
 -      struct ieee80211_hw *hw = sc->hw;
 -      struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_vap *avp;
 +      int error;
  
 -      DPRINTF(sc, ATH_DBG_XMIT,
 -              "%s: TX complete: skb: %p\n", __func__, skb);
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__);
  
 -      if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
 -              tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
 -              /* free driver's private data area of tx_info */
 -              if (tx_info->driver_data[0] != NULL)
 -                      kfree(tx_info->driver_data[0]);
 -                      tx_info->driver_data[0] = NULL;
 +      avp = sc->sc_vaps[0];
 +      if (avp == NULL) {
 +              DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
 +                      __func__);
 +              return;
        }
  
 -      if (tx_status->flags & ATH_TX_BAR) {
 -              tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 -              tx_status->flags &= ~ATH_TX_BAR;
 +#ifdef CONFIG_SLOW_ANT_DIV
 +      ath_slow_ant_div_stop(&sc->sc_antdiv);
 +#endif
 +
 +      /* Update ratectrl */
 +      ath_rate_newstate(sc, avp);
 +
 +      /* Reclaim beacon resources */
 +      if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
 +          sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
 +              ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
 +              ath_beacon_return(sc, avp);
        }
  
 -      if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
 -              if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
 -                      /* Frame was not ACKed, but an ACK was expected */
 -                      tx_info->status.excessive_retries = 1;
 -              }
 -      } else {
 -              /* Frame was ACKed */
 -              tx_info->flags |= IEEE80211_TX_STAT_ACK;
 +      /* Set interrupt mask */
 +      sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
 +      ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
 +      sc->sc_flags &= ~SC_OP_BEACONS;
 +
 +      error = ath_vap_detach(sc, 0);
 +      if (error)
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: Unable to detach vap, error: %d\n",
 +                      __func__, error);
 +}
 +
 +static int ath9k_config(struct ieee80211_hw *hw,
 +                      struct ieee80211_conf *conf)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ieee80211_channel *curchan = hw->conf.channel;
 +      int pos;
 +
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
 +              __func__,
 +              curchan->center_freq);
 +
 +      pos = ath_get_channel(sc, curchan);
 +      if (pos == -1) {
 +              DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
 +              return -EINVAL;
        }
  
 -      tx_info->status.retry_count = tx_status->retries;
 +      sc->sc_ah->ah_channels[pos].chanmode =
 +              (curchan->band == IEEE80211_BAND_2GHZ) ?
 +              CHANNEL_G : CHANNEL_A;
  
 -      ieee80211_tx_status(hw, skb);
 -      if (an)
 -              ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
 +      if (sc->sc_curaid && hw->conf.ht_conf.ht_supported)
 +              sc->sc_ah->ah_channels[pos].chanmode =
 +                      ath_get_extchanmode(sc, curchan);
 +
 +      sc->sc_config.txpowlimit = 2 * conf->power_level;
 +
 +      /* set h/w channel */
 +      if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
 +              DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n",
 +                      __func__);
 +
 +      return 0;
  }
  
 -int ath__rx_indicate(struct ath_softc *sc,
 -                   struct sk_buff *skb,
 -                   struct ath_recv_status *status,
 -                   u16 keyix)
 +static int ath9k_config_interface(struct ieee80211_hw *hw,
 +                                struct ieee80211_vif *vif,
 +                                struct ieee80211_if_conf *conf)
  {
 -      struct ieee80211_hw *hw = sc->hw;
 -      struct ath_node *an = NULL;
 -      struct ieee80211_rx_status rx_status;
 -      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 -      int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 -      int padsize;
 -      enum ATH_RX_TYPE st;
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_hal *ah = sc->sc_ah;
 +      struct ath_vap *avp;
 +      u32 rfilt = 0;
 +      int error, i;
 +      DECLARE_MAC_BUF(mac);
  
 -      /* see if any padding is done by the hw and remove it */
 -      if (hdrlen & 3) {
 -              padsize = hdrlen % 4;
 -              memmove(skb->data + padsize, skb->data, hdrlen);
 -              skb_pull(skb, padsize);
 +      avp = sc->sc_vaps[0];
 +      if (avp == NULL) {
 +              DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
 +                      __func__);
 +              return -EINVAL;
        }
  
 -      /* remove FCS before passing up to protocol stack */
 -      skb_trim(skb, (skb->len - FCS_LEN));
 +      /* TODO: Need to decide which hw opmode to use for multi-interface
 +       * cases */
 +      if (vif->type == NL80211_IFTYPE_AP &&
 +          ah->ah_opmode != ATH9K_M_HOSTAP) {
 +              ah->ah_opmode = ATH9K_M_HOSTAP;
 +              ath9k_hw_setopmode(ah);
 +              ath9k_hw_write_associd(ah, sc->sc_myaddr, 0);
 +              /* Request full reset to get hw opmode changed properly */
 +              sc->sc_flags |= SC_OP_FULL_RESET;
 +      }
  
 -      /* Prepare rx status */
 -      ath9k_rx_prepare(sc, skb, status, &rx_status);
 +      if ((conf->changed & IEEE80211_IFCC_BSSID) &&
 +          !is_zero_ether_addr(conf->bssid)) {
 +              switch (vif->type) {
 +              case NL80211_IFTYPE_STATION:
 +              case NL80211_IFTYPE_ADHOC:
 +                      /* Update ratectrl about the new state */
 +                      ath_rate_newstate(sc, avp);
  
 -      if (!(keyix == ATH9K_RXKEYIX_INVALID) &&
 -          !(status->flags & ATH_RX_DECRYPT_ERROR)) {
 -              rx_status.flag |= RX_FLAG_DECRYPTED;
 -      } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
 -                 && !(status->flags & ATH_RX_DECRYPT_ERROR)
 -                 && skb->len >= hdrlen + 4) {
 -              keyix = skb->data[hdrlen + 3] >> 6;
 +                      /* Set BSSID */
 +                      memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN);
 +                      sc->sc_curaid = 0;
 +                      ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
 +                                             sc->sc_curaid);
  
 -              if (test_bit(keyix, sc->sc_keymap))
 -                      rx_status.flag |= RX_FLAG_DECRYPTED;
 +                      /* Set aggregation protection mode parameters */
 +                      sc->sc_config.ath_aggr_prot = 0;
 +
 +                      /*
 +                       * Reset our TSF so that its value is lower than the
 +                       * beacon that we are trying to catch.
 +                       * Only then hw will update its TSF register with the
 +                       * new beacon. Reset the TSF before setting the BSSID
 +                       * to avoid allowing in any frames that would update
 +                       * our TSF only to have us clear it
 +                       * immediately thereafter.
 +                       */
 +                      ath9k_hw_reset_tsf(sc->sc_ah);
 +
 +                      /* Disable BMISS interrupt when we're not associated */
 +                      ath9k_hw_set_interrupts(sc->sc_ah,
 +                                      sc->sc_imask &
 +                                      ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS));
 +                      sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
 +
 +                      DPRINTF(sc, ATH_DBG_CONFIG,
 +                              "%s: RX filter 0x%x bssid %s aid 0x%x\n",
 +                              __func__, rfilt,
 +                              print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
 +
 +                      /* need to reconfigure the beacon */
 +                      sc->sc_flags &= ~SC_OP_BEACONS ;
 +
 +                      break;
 +              default:
 +                      break;
 +              }
        }
  
 -      spin_lock_bh(&sc->node_lock);
 -      an = ath_node_find(sc, hdr->addr2);
 -      spin_unlock_bh(&sc->node_lock);
 +      if ((conf->changed & IEEE80211_IFCC_BEACON) &&
 +          ((vif->type == NL80211_IFTYPE_ADHOC) ||
 +           (vif->type == NL80211_IFTYPE_AP))) {
 +              /*
 +               * Allocate and setup the beacon frame.
 +               *
 +               * Stop any previous beacon DMA.  This may be
 +               * necessary, for example, when an ibss merge
 +               * causes reconfiguration; we may be called
 +               * with beacon transmission active.
 +               */
 +              ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
  
 -      if (an) {
 -              ath_rx_input(sc, an,
 -                           hw->conf.ht_conf.ht_supported,
 -                           skb, status, &st);
 +              error = ath_beacon_alloc(sc, 0);
 +              if (error != 0)
 +                      return error;
 +
 +              ath_beacon_sync(sc, 0);
        }
 -      if (!an || (st != ATH_RX_CONSUMED))
 -              __ieee80211_rx(hw, skb, &rx_status);
 +
 +      /* Check for WLAN_CAPABILITY_PRIVACY ? */
 +      if ((avp->av_opmode != NL80211_IFTYPE_STATION)) {
 +              for (i = 0; i < IEEE80211_WEP_NKID; i++)
 +                      if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
 +                              ath9k_hw_keysetmac(sc->sc_ah,
 +                                                 (u16)i,
 +                                                 sc->sc_curbssid);
 +      }
 +
 +      /* Only legacy IBSS for now */
 +      if (vif->type == NL80211_IFTYPE_ADHOC)
 +              ath_update_chainmask(sc, 0);
  
        return 0;
  }
  
 -int ath_rx_subframe(struct ath_node *an,
 -                  struct sk_buff *skb,
 -                  struct ath_recv_status *status)
 +#define SUPPORTED_FILTERS                     \
 +      (FIF_PROMISC_IN_BSS |                   \
 +      FIF_ALLMULTI |                          \
 +      FIF_CONTROL |                           \
 +      FIF_OTHER_BSS |                         \
 +      FIF_BCN_PRBRESP_PROMISC |               \
 +      FIF_FCSFAIL)
 +
 +/* FIXME: sc->sc_full_reset ? */
 +static void ath9k_configure_filter(struct ieee80211_hw *hw,
 +                                 unsigned int changed_flags,
 +                                 unsigned int *total_flags,
 +                                 int mc_count,
 +                                 struct dev_mc_list *mclist)
  {
 -      struct ath_softc *sc = an->an_sc;
 -      struct ieee80211_hw *hw = sc->hw;
 -      struct ieee80211_rx_status rx_status;
 +      struct ath_softc *sc = hw->priv;
 +      u32 rfilt;
  
 -      /* Prepare rx status */
 -      ath9k_rx_prepare(sc, skb, status, &rx_status);
 -      if (!(status->flags & ATH_RX_DECRYPT_ERROR))
 -              rx_status.flag |= RX_FLAG_DECRYPTED;
 +      changed_flags &= SUPPORTED_FILTERS;
 +      *total_flags &= SUPPORTED_FILTERS;
  
 -      __ieee80211_rx(hw, skb, &rx_status);
 +      sc->rx_filter = *total_flags;
 +      rfilt = ath_calcrxfilter(sc);
 +      ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
  
 -      return 0;
 -}
 +      if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
 +              if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
 +                      ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0);
 +      }
  
 -enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc)
 -{
 -      return sc->sc_ht_info.tx_chan_width;
 +      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set HW RX filter: 0x%x\n",
 +              __func__, sc->rx_filter);
  }
  
 -static int ath_detach(struct ath_softc *sc)
 +static void ath9k_sta_notify(struct ieee80211_hw *hw,
 +                           struct ieee80211_vif *vif,
 +                           enum sta_notify_cmd cmd,
 +                           struct ieee80211_sta *sta)
  {
 -      struct ieee80211_hw *hw = sc->hw;
 -
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_node *an;
 +      unsigned long flags;
 +      DECLARE_MAC_BUF(mac);
  
 -      /* Unregister hw */
 +      spin_lock_irqsave(&sc->node_lock, flags);
 +      an = ath_node_find(sc, sta->addr);
 +      spin_unlock_irqrestore(&sc->node_lock, flags);
  
 -      ieee80211_unregister_hw(hw);
 +      switch (cmd) {
 +      case STA_NOTIFY_ADD:
 +              spin_lock_irqsave(&sc->node_lock, flags);
 +              if (!an) {
 +                      ath_node_attach(sc, sta->addr, 0);
 +                      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n",
 +                              __func__, print_mac(mac, sta->addr));
 +              } else {
 +                      ath_node_get(sc, sta->addr);
 +              }
 +              spin_unlock_irqrestore(&sc->node_lock, flags);
 +              break;
 +      case STA_NOTIFY_REMOVE:
 +              if (!an)
 +                      DPRINTF(sc, ATH_DBG_FATAL,
 +                              "%s: Removal of a non-existent node\n",
 +                              __func__);
 +              else {
 +                      ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
 +                      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n",
 +                              __func__,
 +                              print_mac(mac, sta->addr));
 +              }
 +              break;
 +      default:
 +              break;
 +      }
 +}
  
 -      /* unregister Rate control */
 -      ath_rate_control_unregister();
 +static int ath9k_conf_tx(struct ieee80211_hw *hw,
 +                       u16 queue,
 +                       const struct ieee80211_tx_queue_params *params)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath9k_tx_queue_info qi;
 +      int ret = 0, qnum;
  
 -      /* tx/rx cleanup */
 +      if (queue >= WME_NUM_AC)
 +              return 0;
  
 -      ath_rx_cleanup(sc);
 -      ath_tx_cleanup(sc);
 +      qi.tqi_aifs = params->aifs;
 +      qi.tqi_cwmin = params->cw_min;
 +      qi.tqi_cwmax = params->cw_max;
 +      qi.tqi_burstTime = params->txop;
 +      qnum = ath_get_hal_qnum(queue, sc);
  
 -      /* Deinit */
 +      DPRINTF(sc, ATH_DBG_CONFIG,
 +              "%s: Configure tx [queue/halq] [%d/%d],  "
 +              "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
 +              __func__,
 +              queue,
 +              qnum,
 +              params->aifs,
 +              params->cw_min,
 +              params->cw_max,
 +              params->txop);
  
 -      ath_deinit(sc);
 +      ret = ath_txq_update(sc, qnum, &qi);
 +      if (ret)
 +              DPRINTF(sc, ATH_DBG_FATAL,
 +                      "%s: TXQ Update failed\n", __func__);
  
 -      return 0;
 +      return ret;
  }
  
 -static int ath_attach(u16 devid,
 -                    struct ath_softc *sc)
 +static int ath9k_set_key(struct ieee80211_hw *hw,
 +                       enum set_key_cmd cmd,
 +                       const u8 *local_addr,
 +                       const u8 *addr,
 +                       struct ieee80211_key_conf *key)
  {
 -      struct ieee80211_hw *hw = sc->hw;
 -      int error = 0;
 +      struct ath_softc *sc = hw->priv;
 +      int ret = 0;
  
 -      DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__);
 +      DPRINTF(sc, ATH_DBG_KEYCACHE, " %s: Set HW Key\n", __func__);
  
 -      error = ath_init(devid, sc);
 -      if (error != 0)
 -              return error;
 +      switch (cmd) {
 +      case SET_KEY:
 +              ret = ath_key_config(sc, addr, key);
 +              if (!ret) {
 +                      set_bit(key->keyidx, sc->sc_keymap);
 +                      key->hw_key_idx = key->keyidx;
 +                      /* push IV and Michael MIC generation to stack */
 +                      key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 +                      if (key->alg == ALG_TKIP)
 +                              key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
 +              }
 +              break;
 +      case DISABLE_KEY:
 +              ath_key_delete(sc, key);
 +              clear_bit(key->keyidx, sc->sc_keymap);
-               sc->sc_keytype = ATH9K_CIPHER_CLR;
 +              break;
 +      default:
 +              ret = -EINVAL;
 +      }
  
 -      /* Init nodes */
 +      return ret;
 +}
  
 -      INIT_LIST_HEAD(&sc->node_list);
 -      spin_lock_init(&sc->node_lock);
 +static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 +                                 struct ieee80211_vif *vif,
 +                                 struct ieee80211_bss_conf *bss_conf,
 +                                 u32 changed)
 +{
 +      struct ath_softc *sc = hw->priv;
  
 -      /* get mac address from hardware and set in mac80211 */
 +      if (changed & BSS_CHANGED_ERP_PREAMBLE) {
 +              DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed PREAMBLE %d\n",
 +                      __func__,
 +                      bss_conf->use_short_preamble);
 +              if (bss_conf->use_short_preamble)
 +                      sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
 +              else
 +                      sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
 +      }
  
 -      SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
 +      if (changed & BSS_CHANGED_ERP_CTS_PROT) {
 +              DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed CTS PROT %d\n",
 +                      __func__,
 +                      bss_conf->use_cts_prot);
 +              if (bss_conf->use_cts_prot &&
 +                  hw->conf.channel->band != IEEE80211_BAND_5GHZ)
 +                      sc->sc_flags |= SC_OP_PROTECT_ENABLE;
 +              else
 +                      sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
 +      }
  
 -      /* setup channels and rates */
 +      if (changed & BSS_CHANGED_HT) {
 +              DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n",
 +                      __func__,
 +                      bss_conf->assoc_ht);
 +              ath9k_ht_conf(sc, bss_conf);
 +      }
  
 -      sc->sbands[IEEE80211_BAND_2GHZ].channels =
 -              sc->channels[IEEE80211_BAND_2GHZ];
 -      sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
 -              sc->rates[IEEE80211_BAND_2GHZ];
 -      sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
 +      if (changed & BSS_CHANGED_ASSOC) {
 +              DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
 +                      __func__,
 +                      bss_conf->assoc);
 +              ath9k_bss_assoc_info(sc, bss_conf);
 +      }
 +}
  
 -      if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
 -              /* Setup HT capabilities for 2.4Ghz*/
 -              setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
 +static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
 +{
 +      u64 tsf;
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_hal *ah = sc->sc_ah;
  
 -      hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 -              &sc->sbands[IEEE80211_BAND_2GHZ];
 +      tsf = ath9k_hw_gettsf64(ah);
  
 -      if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
 -              sc->sbands[IEEE80211_BAND_5GHZ].channels =
 -                      sc->channels[IEEE80211_BAND_5GHZ];
 -              sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
 -                      sc->rates[IEEE80211_BAND_5GHZ];
 -              sc->sbands[IEEE80211_BAND_5GHZ].band =
 -                      IEEE80211_BAND_5GHZ;
 +      return tsf;
 +}
  
 -              if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
 -                      /* Setup HT capabilities for 5Ghz*/
 -                      setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
 +static void ath9k_reset_tsf(struct ieee80211_hw *hw)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_hal *ah = sc->sc_ah;
  
 -              hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 -                      &sc->sbands[IEEE80211_BAND_5GHZ];
 -      }
 +      ath9k_hw_reset_tsf(ah);
 +}
  
 -      /* FIXME: Have to figure out proper hw init values later */
 +static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 +                     enum ieee80211_ampdu_mlme_action action,
 +                     struct ieee80211_sta *sta,
 +                     u16 tid, u16 *ssn)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      int ret = 0;
  
 -      hw->queues = 4;
 -      hw->ampdu_queues = 1;
 +      switch (action) {
 +      case IEEE80211_AMPDU_RX_START:
 +              ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn);
 +              if (ret < 0)
 +                      DPRINTF(sc, ATH_DBG_FATAL,
 +                              "%s: Unable to start RX aggregation\n",
 +                              __func__);
 +              break;
 +      case IEEE80211_AMPDU_RX_STOP:
 +              ret = ath_rx_aggr_stop(sc, sta->addr, tid);
 +              if (ret < 0)
 +                      DPRINTF(sc, ATH_DBG_FATAL,
 +                              "%s: Unable to stop RX aggregation\n",
 +                              __func__);
 +              break;
 +      case IEEE80211_AMPDU_TX_START:
 +              ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn);
 +              if (ret < 0)
 +                      DPRINTF(sc, ATH_DBG_FATAL,
 +                              "%s: Unable to start TX aggregation\n",
 +                              __func__);
 +              else
 +                      ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
 +              break;
 +      case IEEE80211_AMPDU_TX_STOP:
 +              ret = ath_tx_aggr_stop(sc, sta->addr, tid);
 +              if (ret < 0)
 +                      DPRINTF(sc, ATH_DBG_FATAL,
 +                              "%s: Unable to stop TX aggregation\n",
 +                              __func__);
  
 -      /* Register rate control */
 -      hw->rate_control_algorithm = "ath9k_rate_control";
 -      error = ath_rate_control_register();
 -      if (error != 0) {
 +              ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
 +              break;
 +      default:
                DPRINTF(sc, ATH_DBG_FATAL,
 -                      "%s: Unable to register rate control "
 -                      "algorithm:%d\n", __func__, error);
 -              ath_rate_control_unregister();
 -              goto bad;
 -      }
 -
 -      error = ieee80211_register_hw(hw);
 -      if (error != 0) {
 -              ath_rate_control_unregister();
 -              goto bad;
 +                      "%s: Unknown AMPDU action\n", __func__);
        }
  
 -      /* initialize tx/rx engine */
 -
 -      error = ath_tx_init(sc, ATH_TXBUF);
 -      if (error != 0)
 -              goto bad1;
 -
 -      error = ath_rx_init(sc, ATH_RXBUF);
 -      if (error != 0)
 -              goto bad1;
 -
 -      return 0;
 -bad1:
 -      ath_detach(sc);
 -bad:
 -      return error;
 +      return ret;
  }
  
 +static struct ieee80211_ops ath9k_ops = {
 +      .tx                 = ath9k_tx,
 +      .start              = ath9k_start,
 +      .stop               = ath9k_stop,
 +      .add_interface      = ath9k_add_interface,
 +      .remove_interface   = ath9k_remove_interface,
 +      .config             = ath9k_config,
 +      .config_interface   = ath9k_config_interface,
 +      .configure_filter   = ath9k_configure_filter,
 +      .get_stats          = NULL,
 +      .sta_notify         = ath9k_sta_notify,
 +      .conf_tx            = ath9k_conf_tx,
 +      .get_tx_stats       = NULL,
 +      .bss_info_changed   = ath9k_bss_info_changed,
 +      .set_tim            = NULL,
 +      .set_key            = ath9k_set_key,
 +      .hw_scan            = NULL,
 +      .get_tkip_seq       = NULL,
 +      .set_rts_threshold  = NULL,
 +      .set_frag_threshold = NULL,
 +      .set_retry_limit    = NULL,
 +      .get_tsf            = ath9k_get_tsf,
 +      .reset_tsf          = ath9k_reset_tsf,
 +      .tx_last_beacon     = NULL,
 +      .ampdu_action       = ath9k_ampdu_action
 +};
 +
  static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  {
        void __iomem *mem;
                goto bad2;
        }
  
 -      hw->flags = IEEE80211_HW_SIGNAL_DBM |
 +      hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 +              IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 +              IEEE80211_HW_SIGNAL_DBM |
                IEEE80211_HW_NOISE_DBM;
  
 +      hw->wiphy->interface_modes =
 +              BIT(NL80211_IFTYPE_AP) |
 +              BIT(NL80211_IFTYPE_STATION) |
 +              BIT(NL80211_IFTYPE_ADHOC);
 +
        SET_IEEE80211_DEV(hw, &pdev->dev);
        pci_set_drvdata(pdev, hw);
  
@@@ -1784,10 -1411,17 +1781,17 @@@ static void ath_pci_remove(struct pci_d
  {
        struct ieee80211_hw *hw = pci_get_drvdata(pdev);
        struct ath_softc *sc = hw->priv;
+       enum ath9k_int status;
  
-       if (pdev->irq)
+       if (pdev->irq) {
+               ath9k_hw_set_interrupts(sc->sc_ah, 0);
+               /* clear the ISR */
+               ath9k_hw_getisr(sc->sc_ah, &status);
 -              sc->sc_invalid = 1;
++              sc->sc_flags |= SC_OP_INVALID;
                free_irq(pdev->irq, sc);
+       }
        ath_detach(sc);
        pci_iounmap(pdev, sc->mem);
        pci_release_region(pdev, 0);
        pci_disable_device(pdev);
  
  static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
  {
 +      struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 +      struct ath_softc *sc = hw->priv;
 +
 +      ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
 +
 +#ifdef CONFIG_RFKILL
 +      if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
 +              cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
 +#endif
 +
        pci_save_state(pdev);
        pci_disable_device(pdev);
        pci_set_power_state(pdev, 3);
  
  static int ath_pci_resume(struct pci_dev *pdev)
  {
 +      struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 +      struct ath_softc *sc = hw->priv;
        u32 val;
        int err;
  
        if ((val & 0x0000ff00) != 0)
                pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
  
 +      /* Enable LED */
 +      ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
 +                          AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 +      ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
 +
 +#ifdef CONFIG_RFKILL
 +      /*
 +       * check the h/w rfkill state on resume
 +       * and start the rfkill poll timer
 +       */
 +      if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
 +              queue_delayed_work(sc->hw->workqueue,
 +                                 &sc->rf_kill.rfkill_poll, 0);
 +#endif
 +
        return 0;
  }
  
index 3fc6641e8bf750a3d34c05768f3296abcf05bb96,8b332e11a656729f078b47099ba044f2f33aef38..25929059c7dc8d1aaf14f18eeb0e9c5f2ee7f46b
@@@ -59,6 -59,79 +59,6 @@@ static u32 bits_per_symbol[][2] = 
  
  #define IS_HT_RATE(_rate)     ((_rate) & 0x80)
  
 -/*
 - * Insert a chain of ath_buf (descriptors) on a multicast txq
 - * but do NOT start tx DMA on this queue.
 - * NB: must be called with txq lock held
 - */
 -
 -static void ath_tx_mcastqaddbuf(struct ath_softc *sc,
 -                              struct ath_txq *txq,
 -                              struct list_head *head)
 -{
 -      struct ath_hal *ah = sc->sc_ah;
 -      struct ath_buf *bf;
 -
 -      if (list_empty(head))
 -              return;
 -
 -      /*
 -       * Insert the frame on the outbound list and
 -       * pass it on to the hardware.
 -       */
 -      bf = list_first_entry(head, struct ath_buf, list);
 -
 -      /*
 -       * The CAB queue is started from the SWBA handler since
 -       * frames only go out on DTIM and to avoid possible races.
 -       */
 -      ath9k_hw_set_interrupts(ah, 0);
 -
 -      /*
 -       * If there is anything in the mcastq, we want to set
 -       * the "more data" bit in the last item in the queue to
 -       * indicate that there is "more data". It makes sense to add
 -       * it here since you are *always* going to have
 -       * more data when adding to this queue, no matter where
 -       * you call from.
 -       */
 -
 -      if (txq->axq_depth) {
 -              struct ath_buf *lbf;
 -              struct ieee80211_hdr *hdr;
 -
 -              /*
 -               * Add the "more data flag" to the last frame
 -               */
 -
 -              lbf = list_entry(txq->axq_q.prev, struct ath_buf, list);
 -              hdr = (struct ieee80211_hdr *)
 -                      ((struct sk_buff *)(lbf->bf_mpdu))->data;
 -              hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
 -      }
 -
 -      /*
 -       * Now, concat the frame onto the queue
 -       */
 -      list_splice_tail_init(head, &txq->axq_q);
 -      txq->axq_depth++;
 -      txq->axq_totalqueued++;
 -      txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
 -
 -      DPRINTF(sc, ATH_DBG_QUEUE,
 -              "%s: txq depth = %d\n", __func__, txq->axq_depth);
 -      if (txq->axq_link != NULL) {
 -              *txq->axq_link = bf->bf_daddr;
 -              DPRINTF(sc, ATH_DBG_XMIT,
 -                      "%s: link[%u](%p)=%llx (%p)\n",
 -                      __func__,
 -                      txq->axq_qnum, txq->axq_link,
 -                      ito64(bf->bf_daddr), bf->bf_desc);
 -      }
 -      txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
 -      ath9k_hw_set_interrupts(ah, sc->sc_imask);
 -}
 -
  /*
   * Insert a chain of ath_buf (descriptors) on a txq and
   * assume the descriptors are already chained together by caller.
@@@ -204,6 -277,8 +204,6 @@@ static int ath_tx_prepare(struct ath_so
        __le16 fc;
        u8 *qc;
  
 -      memset(txctl, 0, sizeof(struct ath_tx_control));
 -
        txctl->dev = sc;
        hdr = (struct ieee80211_hdr *)skb->data;
        hdrlen = ieee80211_get_hdrlen_from_skb(skb);
        }
  
        txctl->if_id = 0;
 -      txctl->nextfraglen = 0;
        txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3);
        txctl->txpower = MAX_RATE_POWER; /* FIXME */
  
                txctl->keyix = tx_info->control.hw_key->hw_key_idx;
                txctl->frmlen += tx_info->control.icv_len;
  
-               if (sc->sc_keytype == ATH9K_CIPHER_WEP)
+               if (tx_info->control.hw_key->alg == ALG_WEP)
                        txctl->keytype = ATH9K_KEY_TYPE_WEP;
-               else if (sc->sc_keytype == ATH9K_CIPHER_TKIP)
+               else if (tx_info->control.hw_key->alg == ALG_TKIP)
                        txctl->keytype = ATH9K_KEY_TYPE_TKIP;
-               else if (sc->sc_keytype == ATH9K_CIPHER_AES_CCM)
+               else if (tx_info->control.hw_key->alg == ALG_CCMP)
                        txctl->keytype = ATH9K_KEY_TYPE_AES;
        }
  
  
        /* Fill qnum */
  
 -      txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
 -      txq = &sc->sc_txq[txctl->qnum];
 +      if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) {
 +              txctl->qnum = 0;
 +              txq = sc->sc_cabq;
 +      } else {
 +              txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
 +              txq = &sc->sc_txq[txctl->qnum];
 +      }
        spin_lock_bh(&txq->axq_lock);
  
        /* Try to avoid running out of descriptors */
 -      if (txq->axq_depth >= (ATH_TXBUF - 20)) {
 +      if (txq->axq_depth >= (ATH_TXBUF - 20) &&
 +          !(txctl->flags & ATH9K_TXDESC_CAB)) {
                DPRINTF(sc, ATH_DBG_FATAL,
                        "%s: TX queue: %d is full, depth: %d\n",
                        __func__,
  
        /* Fill flags */
  
 -      txctl->flags = ATH9K_TXDESC_CLRDMASK;    /* needed for crypto errors */
 +      txctl->flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
  
        if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
                txctl->flags |= ATH9K_TXDESC_NOACK;
                 * incremented by the fragmentation routine.
                 */
                if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) &&
 -                      txctl->ht && sc->sc_txaggr) {
 +                  txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
                        struct ath_atx_tid *tid;
  
                        tid = ATH_AN_2_TID(txctl->an, txctl->tidno);
        }
        rix = rcs[0].rix;
  
 -      /*
 -       * Calculate duration.  This logically belongs in the 802.11
 -       * layer but it lacks sufficient information to calculate it.
 -       */
 -      if ((txctl->flags & ATH9K_TXDESC_NOACK) == 0 && !ieee80211_is_ctl(fc)) {
 -              u16 dur;
 +      if (ieee80211_has_morefrags(fc) ||
 +          (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
                /*
 -               * XXX not right with fragmentation.
 -               */
 -              if (sc->sc_flags & ATH_PREAMBLE_SHORT)
 -                      dur = rt->info[rix].spAckDuration;
 -              else
 -                      dur = rt->info[rix].lpAckDuration;
 -
 -              if (le16_to_cpu(hdr->frame_control) &
 -                              IEEE80211_FCTL_MOREFRAGS) {
 -                      dur += dur;  /* Add additional 'SIFS + ACK' */
 -
 -                      /*
 -                      ** Compute size of next fragment in order to compute
 -                      ** durations needed to update NAV.
 -                      ** The last fragment uses the ACK duration only.
 -                      ** Add time for next fragment.
 -                      */
 -                      dur += ath9k_hw_computetxtime(sc->sc_ah, rt,
 -                                      txctl->nextfraglen,
 -                                      rix, sc->sc_flags & ATH_PREAMBLE_SHORT);
 -              }
 -
 -              if (ieee80211_has_morefrags(fc) ||
 -                   (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
 -                      /*
 -                      **  Force hardware to use computed duration for next
 -                      **  fragment by disabling multi-rate retry, which
 -                      **  updates duration based on the multi-rate
 -                      **  duration table.
 -                      */
 -                      rcs[1].tries = rcs[2].tries = rcs[3].tries = 0;
 -                      rcs[1].rix = rcs[2].rix = rcs[3].rix = 0;
 -                      /* reset tries but keep rate index */
 -                      rcs[0].tries = ATH_TXMAXTRY;
 -              }
 -
 -              hdr->duration_id = cpu_to_le16(dur);
 +              **  Force hardware to use computed duration for next
 +              **  fragment by disabling multi-rate retry, which
 +              **  updates duration based on the multi-rate
 +              **  duration table.
 +              */
 +              rcs[1].tries = rcs[2].tries = rcs[3].tries = 0;
 +              rcs[1].rix = rcs[2].rix = rcs[3].rix = 0;
 +              /* reset tries but keep rate index */
 +              rcs[0].tries = ATH_TXMAXTRY;
        }
  
        /*
        if (is_multicast_ether_addr(hdr->addr1)) {
                antenna = sc->sc_mcastantenna + 1;
                sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1;
 -      } else
 -              antenna = sc->sc_txantenna;
 +      }
  
 -#ifdef USE_LEGACY_HAL
 -      txctl->antenna = antenna;
 -#endif
        return 0;
  }
  
@@@ -396,6 -502,7 +396,6 @@@ static void ath_tx_complete_buf(struct 
  {
        struct sk_buff *skb = bf->bf_mpdu;
        struct ath_xmit_status tx_status;
 -      dma_addr_t *pa;
  
        /*
         * Set retry information.
        if (!txok) {
                tx_status.flags |= ATH_TX_ERROR;
  
 -              if (bf->bf_isxretried)
 +              if (bf_isxretried(bf))
                        tx_status.flags |= ATH_TX_XRETRY;
        }
        /* Unmap this frame */
 -      pa = get_dma_mem_context(bf, bf_dmacontext);
        pci_unmap_single(sc->pdev,
 -                       *pa,
 +                       bf->bf_dmacontext,
                         skb->len,
                         PCI_DMA_TODEVICE);
        /* complete this frame */
@@@ -521,7 -629,7 +521,7 @@@ static int ath_tx_num_badfrms(struct at
        if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
                return 0;
  
 -      isaggr = bf->bf_isaggr;
 +      isaggr = bf_isaggr(bf);
        if (isaggr) {
                seq_st = ATH_DS_BA_SEQ(ds);
                memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
@@@ -543,7 -651,7 +543,7 @@@ static void ath_tx_set_retry(struct ath
        struct sk_buff *skb;
        struct ieee80211_hdr *hdr;
  
 -      bf->bf_isretried = 1;
 +      bf->bf_state.bf_type |= BUF_RETRY;
        bf->bf_retries++;
  
        skb = bf->bf_mpdu;
@@@ -590,7 -698,7 +590,7 @@@ static u32 ath_pkt_duration(struct ath_
        u8 rc;
        int streams, pktlen;
  
 -      pktlen = bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen;
 +      pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
        rc = rt->info[rix].rateCode;
  
        /*
@@@ -634,7 -742,7 +634,7 @@@ static void ath_buf_set_rate(struct ath
        int i, flags, rtsctsena = 0, dynamic_mimops = 0;
        u32 ctsduration = 0;
        u8 rix = 0, cix, ctsrate = 0;
 -      u32 aggr_limit_with_rts = sc->sc_rtsaggrlimit;
 +      u32 aggr_limit_with_rts = ah->ah_caps.rts_aggr_limit;
        struct ath_node *an = (struct ath_node *) bf->bf_node;
  
        /*
         * let rate series flags determine which rates will actually
         * use RTS.
         */
 -      if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf->bf_isdata) {
 +      if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) {
                BUG_ON(!an);
                /*
                 * 802.11g protection not needed, use our default behavior
                 * and the second aggregate should have any protection at all.
                 */
                if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) {
 -                      if (!bf->bf_aggrburst) {
 +                      if (!bf_isaggrburst(bf)) {
                                flags = ATH9K_TXDESC_RTSENA;
                                dynamic_mimops = 1;
                        } else {
         * Set protection if aggregate protection on
         */
        if (sc->sc_config.ath_aggr_prot &&
 -          (!bf->bf_isaggr || (bf->bf_isaggr && bf->bf_al < 8192))) {
 +          (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
                flags = ATH9K_TXDESC_RTSENA;
                cix = rt->info[sc->sc_protrix].controlRate;
                rtsctsena = 1;
        /*
         *  For AR5416 - RTS cannot be followed by a frame larger than 8K.
         */
 -      if (bf->bf_isaggr && (bf->bf_al > aggr_limit_with_rts)) {
 +      if (bf_isaggr(bf) && (bf->bf_al > aggr_limit_with_rts)) {
                /*
                 * Ensure that in the case of SM Dynamic power save
                 * while we are bursting the second aggregate the
        /* NB: cix is set above where RTS/CTS is enabled */
        BUG_ON(cix == 0xff);
        ctsrate = rt->info[cix].rateCode |
 -              (bf->bf_shpreamble ? rt->info[cix].shortPreamble : 0);
 +              (bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0);
  
        /*
         * Setup HAL rate series
                rix = bf->bf_rcs[i].rix;
  
                series[i].Rate = rt->info[rix].rateCode |
 -                      (bf->bf_shpreamble ? rt->info[rix].shortPreamble : 0);
 +                      (bf_isshpreamble(bf) ? rt->info[rix].shortPreamble : 0);
  
                series[i].Tries = bf->bf_rcs[i].tries;
  
                        sc, rix, bf,
                        (bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0,
                        (bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG),
 -                      bf->bf_shpreamble);
 +                      bf_isshpreamble(bf));
  
                if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) &&
                    (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) {
                         */
                        series[i].ChSel = sc->sc_tx_chainmask;
                } else {
 -                      if (bf->bf_ht)
 +                      if (bf_isht(bf))
                                series[i].ChSel =
                                        ath_chainmask_sel_logic(sc, an);
                        else
                 *     use the precalculated ACK durations.
                 */
                if (flags & ATH9K_TXDESC_RTSENA) {    /* SIFS + CTS */
 -                      ctsduration += bf->bf_shpreamble ?
 +                      ctsduration += bf_isshpreamble(bf) ?
                                rt->info[cix].spAckDuration :
                                rt->info[cix].lpAckDuration;
                }
                ctsduration += series[0].PktDuration;
  
                if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */
 -                      ctsduration += bf->bf_shpreamble ?
 +                      ctsduration += bf_isshpreamble(bf) ?
                                rt->info[rix].spAckDuration :
                                rt->info[rix].lpAckDuration;
                }
         * set dur_update_en for l-sig computation except for PS-Poll frames
         */
        ath9k_hw_set11n_ratescenario(ah, ds, lastds,
 -                                  !bf->bf_ispspoll,
 -                                  ctsrate,
 -                                  ctsduration,
 -                                  series, 4, flags);
 +                                   !bf_ispspoll(bf),
 +                                   ctsrate,
 +                                   ctsduration,
 +                                   series, 4, flags);
        if (sc->sc_config.ath_aggr_prot && flags)
                ath9k_hw_set11n_burstduration(ah, ds, 8192);
  }
@@@ -850,7 -958,7 +850,7 @@@ static int ath_tx_send_normal(struct at
        BUG_ON(list_empty(bf_head));
  
        bf = list_first_entry(bf_head, struct ath_buf, list);
 -      bf->bf_isampdu = 0; /* regular HT frame */
 +      bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */
  
        skb = (struct sk_buff *)bf->bf_mpdu;
        tx_info = IEEE80211_SKB_CB(skb);
@@@ -890,7 -998,7 +890,7 @@@ static void ath_tx_flush_tid(struct ath
  
        while (!list_empty(&tid->buf_q)) {
                bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
 -              ASSERT(!bf->bf_isretried);
 +              ASSERT(!bf_isretried(bf));
                list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
                ath_tx_send_normal(sc, txq, tid, &bf_head);
        }
@@@ -917,7 -1025,7 +917,7 @@@ static void ath_tx_complete_aggr_rifs(s
        int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
        int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
  
 -      isaggr = bf->bf_isaggr;
 +      isaggr = bf_isaggr(bf);
        if (isaggr) {
                if (txok) {
                        if (ATH_DS_TX_BA(ds)) {
                                 * when perform internal reset in this routine.
                                 * Only enable reset in STA mode for now.
                                 */
 -                              if (sc->sc_opmode == ATH9K_M_STA)
 +                              if (sc->sc_ah->ah_opmode == ATH9K_M_STA)
                                        needreset = 1;
                        }
                } else {
                                        ath_tx_set_retry(sc, bf);
                                        txpending = 1;
                                } else {
 -                                      bf->bf_isxretried = 1;
 +                                      bf->bf_state.bf_type |= BUF_XRETRY;
                                        txfail = 1;
                                        sendbar = 1;
                                }
                                                tbf->bf_lastfrm->bf_desc);
  
                                        /* copy the DMA context */
 -                                      copy_dma_mem_context(
 -                                              get_dma_mem_context(tbf,
 -                                                      bf_dmacontext),
 -                                              get_dma_mem_context(bf_last,
 -                                                      bf_dmacontext));
 +                                      tbf->bf_dmacontext =
 +                                              bf_last->bf_dmacontext;
                                }
                                list_add_tail(&tbf->list, &bf_head);
                        } else {
                                 * software retry
                                 */
                                ath9k_hw_cleartxdesc(sc->sc_ah,
 -                                      bf->bf_lastfrm->bf_desc);
 +                                                   bf->bf_lastfrm->bf_desc);
                        }
  
                        /*
        }
  
        if (needreset)
 -              ath_internal_reset(sc);
 +              ath_reset(sc, false);
  
        return;
  }
@@@ -1220,7 -1331,7 +1220,7 @@@ static int ath_tx_processq(struct ath_s
  
                txq->axq_depth--;
  
 -              if (bf->bf_isaggr)
 +              if (bf_isaggr(bf))
                        txq->axq_aggr_depth--;
  
                txok = (ds->ds_txstat.ts_status == 0);
                        spin_unlock_bh(&sc->sc_txbuflock);
                }
  
 -              if (!bf->bf_isampdu) {
 +              if (!bf_isampdu(bf)) {
                        /*
                         * This frame is sent out as a single frame.
                         * Use hardware retry status for this frame.
                         */
                        bf->bf_retries = ds->ds_txstat.ts_longretry;
                        if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
 -                              bf->bf_isxretried = 1;
 +                              bf->bf_state.bf_type |= BUF_XRETRY;
                        nbad = 0;
                } else {
                        nbad = ath_tx_num_badfrms(sc, bf, txok);
                        if (ds->ds_txstat.ts_status == 0)
                                nacked++;
  
 -                      if (bf->bf_isdata) {
 +                      if (bf_isdata(bf)) {
                                if (isrifs)
                                        tmp_ds = bf->bf_rifslast->bf_desc;
                                else
                /*
                 * Complete this transmit unit
                 */
 -              if (bf->bf_isampdu)
 +              if (bf_isampdu(bf))
                        ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok);
                else
                        ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
                /*
                 * schedule any pending packets if aggregation is enabled
                 */
 -              if (sc->sc_txaggr)
 +              if (sc->sc_flags & SC_OP_TXAGGR)
                        ath_txq_schedule(sc, txq);
                spin_unlock_bh(&txq->axq_lock);
        }
@@@ -1319,9 -1430,10 +1319,9 @@@ static void ath_drain_txdataq(struct at
        struct ath_hal *ah = sc->sc_ah;
        int i;
        int npend = 0;
 -      enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
  
        /* XXX return value */
 -      if (!sc->sc_invalid) {
 +      if (!(sc->sc_flags & SC_OP_INVALID)) {
                for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                        if (ATH_TXQ_SETUP(sc, i)) {
                                ath_tx_stopdma(sc, &sc->sc_txq[i]);
                        "%s: Unable to stop TxDMA. Reset HAL!\n", __func__);
  
                spin_lock_bh(&sc->sc_resetlock);
 -              if (!ath9k_hw_reset(ah, sc->sc_opmode,
 -                      &sc->sc_curchan, ht_macmode,
 -                      sc->sc_tx_chainmask, sc->sc_rx_chainmask,
 -                      sc->sc_ht_extprotspacing, true, &status)) {
 +              if (!ath9k_hw_reset(ah,
 +                                  sc->sc_ah->ah_curchan,
 +                                  sc->sc_ht_info.tx_chan_width,
 +                                  sc->sc_tx_chainmask, sc->sc_rx_chainmask,
 +                                  sc->sc_ht_extprotspacing, true, &status)) {
  
                        DPRINTF(sc, ATH_DBG_FATAL,
                                "%s: unable to reset hardware; hal status %u\n",
@@@ -1370,7 -1481,7 +1370,7 @@@ static void ath_tx_addto_baw(struct ath
  {
        int index, cindex;
  
 -      if (bf->bf_isretried)
 +      if (bf_isretried(bf))
                return;
  
        index  = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
@@@ -1405,7 -1516,7 +1405,7 @@@ static int ath_tx_send_ampdu(struct ath
        BUG_ON(list_empty(bf_head));
  
        bf = list_first_entry(bf_head, struct ath_buf, list);
 -      bf->bf_isampdu = 1;
 +      bf->bf_state.bf_type |= BUF_AMPDU;
        bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */
        bf->bf_tidno = txctl->tidno;
  
@@@ -1749,7 -1860,7 +1749,7 @@@ static void ath_tx_sched_aggr(struct at
                if (bf->bf_nframes == 1) {
                        ASSERT(bf->bf_lastfrm == bf_last);
  
 -                      bf->bf_isaggr = 0;
 +                      bf->bf_state.bf_type &= ~BUF_AGGR;
                        /*
                         * clear aggr bits for every descriptor
                         * XXX TODO: is there a way to optimize it?
                /*
                 * setup first desc with rate and aggr info
                 */
 -              bf->bf_isaggr  = 1;
 +              bf->bf_state.bf_type |= BUF_AGGR;
                ath_buf_set_rate(sc, bf);
                ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
  
@@@ -1814,7 -1925,7 +1814,7 @@@ static void ath_tid_drain(struct ath_so
                list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
  
                /* update baw for software retried frame */
 -              if (bf->bf_isretried)
 +              if (bf_isretried(bf))
                        ath_tx_update_baw(sc, tid, bf->bf_seqno);
  
                /*
@@@ -1879,18 -1990,13 +1879,18 @@@ static int ath_tx_start_dma(struct ath_
        struct list_head bf_head;
        struct ath_desc *ds;
        struct ath_hal *ah = sc->sc_ah;
 -      struct ath_txq *txq = &sc->sc_txq[txctl->qnum];
 +      struct ath_txq *txq;
        struct ath_tx_info_priv *tx_info_priv;
        struct ath_rc_series *rcs;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct ieee80211_tx_info *tx_info =  IEEE80211_SKB_CB(skb);
        __le16 fc = hdr->frame_control;
  
 +      if (unlikely(txctl->flags & ATH9K_TXDESC_CAB))
 +              txq = sc->sc_cabq;
 +      else
 +              txq = &sc->sc_txq[txctl->qnum];
 +
        /* For each sglist entry, allocate an ath_buf for DMA */
        INIT_LIST_HEAD(&bf_head);
        spin_lock_bh(&sc->sc_txbuflock);
        /* set up this buffer */
        ATH_TXBUF_RESET(bf);
        bf->bf_frmlen = txctl->frmlen;
 -      bf->bf_isdata = ieee80211_is_data(fc);
 -      bf->bf_isbar = ieee80211_is_back_req(fc);
 -      bf->bf_ispspoll = ieee80211_is_pspoll(fc);
 +
 +      ieee80211_is_data(fc) ?
 +              (bf->bf_state.bf_type |= BUF_DATA) :
 +              (bf->bf_state.bf_type &= ~BUF_DATA);
 +      ieee80211_is_back_req(fc) ?
 +              (bf->bf_state.bf_type |= BUF_BAR) :
 +              (bf->bf_state.bf_type &= ~BUF_BAR);
 +      ieee80211_is_pspoll(fc) ?
 +              (bf->bf_state.bf_type |= BUF_PSPOLL) :
 +              (bf->bf_state.bf_type &= ~BUF_PSPOLL);
 +      (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ?
 +              (bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) :
 +              (bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE);
 +
        bf->bf_flags = txctl->flags;
 -      bf->bf_shpreamble = sc->sc_flags & ATH_PREAMBLE_SHORT;
        bf->bf_keytype = txctl->keytype;
        tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
        rcs = tx_info_priv->rcs;
        /*
         * Save the DMA context in the first ath_buf
         */
 -      copy_dma_mem_context(get_dma_mem_context(bf, bf_dmacontext),
 -                           get_dma_mem_context(txctl, dmacontext));
 +      bf->bf_dmacontext = txctl->dmacontext;
  
        /*
         * Formulate first tx descriptor with tx controls.
                            ds);                /* first descriptor */
  
        bf->bf_lastfrm = bf;
 -      bf->bf_ht = txctl->ht;
 +      (txctl->ht) ?
 +              (bf->bf_state.bf_type |= BUF_HT) :
 +              (bf->bf_state.bf_type &= ~BUF_HT);
  
        spin_lock_bh(&txq->axq_lock);
  
 -      if (txctl->ht && sc->sc_txaggr) {
 +      if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
                struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno);
                if (ath_aggr_query(sc, an, txctl->tidno)) {
                        /*
                        bf->bf_tidno = txctl->tidno;
                }
  
 -              if (is_multicast_ether_addr(hdr->addr1)) {
 -                      struct ath_vap *avp = sc->sc_vaps[txctl->if_id];
 -
 -                      /*
 -                       * When servicing one or more stations in power-save
 -                       * mode (or) if there is some mcast data waiting on
 -                       * mcast queue (to prevent out of order delivery of
 -                       * mcast,bcast packets) multicast frames must be
 -                       * buffered until after the beacon. We use the private
 -                       * mcast queue for that.
 -                       */
 -                      /* XXX? more bit in 802.11 frame header */
 -                      spin_lock_bh(&avp->av_mcastq.axq_lock);
 -                      if (txctl->ps || avp->av_mcastq.axq_depth)
 -                              ath_tx_mcastqaddbuf(sc,
 -                                      &avp->av_mcastq, &bf_head);
 -                      else
 -                              ath_tx_txqaddbuf(sc, txq, &bf_head);
 -                      spin_unlock_bh(&avp->av_mcastq.axq_lock);
 -              } else
 -                      ath_tx_txqaddbuf(sc, txq, &bf_head);
 +              ath_tx_txqaddbuf(sc, txq, &bf_head);
        }
        spin_unlock_bh(&txq->axq_lock);
        return 0;
  
  static void xmit_map_sg(struct ath_softc *sc,
                        struct sk_buff *skb,
 -                      dma_addr_t *pa,
                        struct ath_tx_control *txctl)
  {
        struct ath_xmit_status tx_status;
        struct ath_atx_tid *tid;
        struct scatterlist sg;
  
 -      *pa = pci_map_single(sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
 +      txctl->dmacontext = pci_map_single(sc->pdev, skb->data,
 +                                         skb->len, PCI_DMA_TODEVICE);
  
        /* setup S/G list */
        memset(&sg, 0, sizeof(struct scatterlist));
 -      sg_dma_address(&sg) = *pa;
 +      sg_dma_address(&sg) = txctl->dmacontext;
        sg_dma_len(&sg) = skb->len;
  
        if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) {
                /*
                 *  We have to do drop frame here.
                 */
 -              pci_unmap_single(sc->pdev, *pa, skb->len, PCI_DMA_TODEVICE);
 +              pci_unmap_single(sc->pdev, txctl->dmacontext,
 +                               skb->len, PCI_DMA_TODEVICE);
  
                tx_status.retries = 0;
                tx_status.flags = ATH_TX_ERROR;
  
 -              if (txctl->ht && sc->sc_txaggr) {
 +              if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
                        /* Reclaim the seqno. */
                        tid = ATH_AN_2_TID((struct ath_node *)
                                txctl->an, txctl->tidno);
@@@ -2048,7 -2162,7 +2048,7 @@@ int ath_tx_init(struct ath_softc *sc, i
  
                /* Setup tx descriptors */
                error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf,
 -                      "tx", nbufs * ATH_FRAG_PER_MSDU, ATH_TXDESC);
 +                      "tx", nbufs, 1);
                if (error != 0) {
                        DPRINTF(sc, ATH_DBG_FATAL,
                                "%s: failed to allocate tx descriptors: %d\n",
@@@ -2289,7 -2403,6 +2289,7 @@@ int ath_tx_start(struct ath_softc *sc, 
        struct ath_tx_control txctl;
        int error = 0;
  
 +      memset(&txctl, 0, sizeof(struct ath_tx_control));
        error = ath_tx_prepare(sc, skb, &txctl);
        if (error == 0)
                /*
                 * ath_tx_start_dma() will be called either synchronously
                 * or asynchrounsly once DMA is complete.
                 */
 -              xmit_map_sg(sc, skb,
 -                          get_dma_mem_context(&txctl, dmacontext),
 -                          &txctl);
 +              xmit_map_sg(sc, skb, &txctl);
        else
                ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
  
  
  void ath_tx_tasklet(struct ath_softc *sc)
  {
 -      u64 tsf = ath9k_hw_gettsf64(sc->sc_ah);
 -      int i, nacked = 0;
 +      int i;
        u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
  
        ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
         */
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
 -                      nacked += ath_tx_processq(sc, &sc->sc_txq[i]);
 +                      ath_tx_processq(sc, &sc->sc_txq[i]);
        }
 -      if (nacked)
 -              sc->sc_lastrx = tsf;
  }
  
  void ath_tx_draintxq(struct ath_softc *sc,
  
                spin_unlock_bh(&txq->axq_lock);
  
 -              if (bf->bf_isampdu)
 +              if (bf_isampdu(bf))
                        ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0);
                else
                        ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
        }
  
        /* flush any pending frames if aggregation is enabled */
 -      if (sc->sc_txaggr) {
 +      if (sc->sc_flags & SC_OP_TXAGGR) {
                if (!retry_tx) {
                        spin_lock_bh(&txq->axq_lock);
                        ath_txq_drain_pending_buffers(sc, txq,
@@@ -2391,7 -2509,7 +2391,7 @@@ void ath_draintxq(struct ath_softc *sc
  {
        /* stop beacon queue. The beacon will be freed when
         * we go to INIT state */
 -      if (!sc->sc_invalid) {
 +      if (!(sc->sc_flags & SC_OP_INVALID)) {
                (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
                DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__,
                        ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq));
@@@ -2418,7 -2536,7 +2418,7 @@@ enum ATH_AGGR_CHECK ath_tx_aggr_check(s
        struct ath_atx_tid *txtid;
        DECLARE_MAC_BUF(mac);
  
 -      if (!sc->sc_txaggr)
 +      if (!(sc->sc_flags & SC_OP_TXAGGR))
                return AGGR_NOT_REQUIRED;
  
        /* ADDBA exchange must be completed before sending aggregates */
@@@ -2465,7 -2583,7 +2465,7 @@@ int ath_tx_aggr_start(struct ath_softc 
                return -1;
        }
  
 -      if (sc->sc_txaggr) {
 +      if (sc->sc_flags & SC_OP_TXAGGR) {
                txtid = ATH_AN_2_TID(an, tid);
                txtid->addba_exchangeinprogress = 1;
                ath_tx_pause_tid(sc, txtid);
@@@ -2529,7 -2647,7 +2529,7 @@@ void ath_tx_aggr_teardown(struct ath_so
        spin_lock_bh(&txq->axq_lock);
        while (!list_empty(&txtid->buf_q)) {
                bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
 -              if (!bf->bf_isretried) {
 +              if (!bf_isretried(bf)) {
                        /*
                         * NB: it's based on the assumption that
                         * software retried frame will always stay
@@@ -2625,7 -2743,7 +2625,7 @@@ void ath_txq_schedule(struct ath_softc 
  
  void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
  {
 -      if (sc->sc_txaggr) {
 +      if (sc->sc_flags & SC_OP_TXAGGR) {
                struct ath_atx_tid *tid;
                struct ath_atx_ac *ac;
                int tidno, acno;
@@@ -2737,7 -2855,7 +2737,7 @@@ void ath_tx_node_cleanup(struct ath_sof
  
  void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an)
  {
 -      if (sc->sc_txaggr) {
 +      if (sc->sc_flags & SC_OP_TXAGGR) {
                struct ath_atx_tid *tid;
                int tidno, i;
  
                }
        }
  }
 +
 +void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
 +{
 +      int hdrlen, padsize;
 +      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 +      struct ath_tx_control txctl;
 +
 +      /*
 +       * As a temporary workaround, assign seq# here; this will likely need
 +       * to be cleaned up to work better with Beacon transmission and virtual
 +       * BSSes.
 +       */
 +      if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 +              struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 +              if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
 +                      sc->seq_no += 0x10;
 +              hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
 +              hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
 +      }
 +
 +      /* Add the padding after the header if this is not already done */
 +      hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 +      if (hdrlen & 3) {
 +              padsize = hdrlen % 4;
 +              if (skb_headroom(skb) < padsize) {
 +                      DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ padding "
 +                              "failed\n", __func__);
 +                      dev_kfree_skb_any(skb);
 +                      return;
 +              }
 +              skb_push(skb, padsize);
 +              memmove(skb->data, skb->data + padsize, hdrlen);
 +      }
 +
 +      DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting CABQ packet, skb: %p\n",
 +              __func__,
 +              skb);
 +
 +      memset(&txctl, 0, sizeof(struct ath_tx_control));
 +      txctl.flags = ATH9K_TXDESC_CAB;
 +      if (ath_tx_prepare(sc, skb, &txctl) == 0) {
 +              /*
 +               * Start DMA mapping.
 +               * ath_tx_start_dma() will be called either synchronously
 +               * or asynchrounsly once DMA is complete.
 +               */
 +              xmit_map_sg(sc, skb, &txctl);
 +      } else {
 +              ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
 +              DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__);
 +              dev_kfree_skb_any(skb);
 +      }
 +}
 +
index 96902da7d6618ddd573338bba606b2f4c83c7ae0,34ae125d5384dadf769b0134aa0a878af471fc17..713753781f4007eb44ec93090f40c27e452474a1
@@@ -24,7 -24,6 +24,7 @@@
  
  #include "rfkill.h"
  #include "b43.h"
 +#include "phy_common.h"
  
  #include <linux/kmod.h>
  
@@@ -44,23 -43,6 +44,6 @@@ static bool b43_is_hw_radio_enabled(str
        return 0;
  }
  
- /* Update the rfkill state */
- static void b43_rfkill_update_state(struct b43_wldev *dev)
- {
-       struct b43_rfkill *rfk = &(dev->wl->rfkill);
-       if (!dev->radio_hw_enable) {
-               rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED;
-               return;
-       }
-       if (!dev->phy.radio_on)
-               rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
-       else
-               rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
- }
  /* The poll callback for the hardware button. */
  static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
  {
@@@ -78,7 -60,6 +61,6 @@@
        if (unlikely(enabled != dev->radio_hw_enable)) {
                dev->radio_hw_enable = enabled;
                report_change = 1;
-               b43_rfkill_update_state(dev);
                b43info(wl, "Radio hardware status changed to %s\n",
                        enabled ? "ENABLED" : "DISABLED");
        }
@@@ -115,11 -96,11 +97,11 @@@ static int b43_rfkill_soft_toggle(void 
                        goto out_unlock;
                }
                if (!dev->phy.radio_on)
 -                      b43_radio_turn_on(dev);
 +                      b43_software_rfkill(dev, state);
                break;
        case RFKILL_STATE_SOFT_BLOCKED:
                if (dev->phy.radio_on)
 -                      b43_radio_turn_off(dev, 0);
 +                      b43_software_rfkill(dev, state);
                break;
        default:
                b43warn(wl, "Received unexpected rfkill state %d.\n", state);
@@@ -188,11 -169,6 +170,11 @@@ void b43_rfkill_init(struct b43_wldev *
                        "The built-in radio LED will not work.\n");
  #endif /* CONFIG_RFKILL_INPUT */
  
 +#if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE)
 +      b43warn(wl, "The rfkill-input subsystem is not available. "
 +              "The built-in radio LED will not work.\n");
 +#endif
 +
        err = input_register_polled_device(rfk->poll_dev);
        if (err)
                goto err_unreg_rfk;
diff --combined include/net/netlink.h
index 76c43ff38f64178d98d6d911bcd9651a4969075c,208fe5a385469d95245ba6d9264d797e8f737127..3643bbb8e585e4018cbd66606d64c12a7edf84ac
   * Nested Attributes Construction:
   *   nla_nest_start(skb, type)                start a nested attribute
   *   nla_nest_end(skb, nla)           finalize a nested attribute
 - *   nla_nest_compat_start(skb, type, start a nested compat attribute
 - *                       len, data)
 - *   nla_nest_compat_end(skb, type)   finalize a nested compat attribute
   *   nla_nest_cancel(skb, nla)                cancel nested attribute construction
   *
   * Attribute Length Calculations:
   *   nla_find_nested()                        find attribute in nested attributes
   *   nla_parse()                      parse and validate stream of attrs
   *   nla_parse_nested()                       parse nested attribuets
 - *   nla_parse_nested_compat()                parse nested compat attributes
   *   nla_for_each_attr()              loop over all attributes
   *   nla_for_each_nested()            loop over the nested attributes
   *=========================================================================
@@@ -698,7 -702,7 +698,7 @@@ static inline int nla_len(const struct 
   */
  static inline int nla_ok(const struct nlattr *nla, int remaining)
  {
-       return remaining >= sizeof(*nla) &&
+       return remaining >= (int) sizeof(*nla) &&
               nla->nla_len >= sizeof(*nla) &&
               nla->nla_len <= remaining;
  }
@@@ -747,6 -751,39 +747,6 @@@ static inline int nla_parse_nested(stru
        return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
  }
  
 -/**
 - * nla_parse_nested_compat - parse nested compat attributes
 - * @tb: destination array with maxtype+1 elements
 - * @maxtype: maximum attribute type to be expected
 - * @nla: attribute containing the nested attributes
 - * @data: pointer to point to contained structure
 - * @len: length of contained structure
 - * @policy: validation policy
 - *
 - * Parse a nested compat attribute. The compat attribute contains a structure
 - * and optionally a set of nested attributes. On success the data pointer
 - * points to the nested data and tb contains the parsed attributes
 - * (see nla_parse).
 - */
 -static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype,
 -                                          struct nlattr *nla,
 -                                          const struct nla_policy *policy,
 -                                          int len)
 -{
 -      int nested_len = nla_len(nla) - NLA_ALIGN(len);
 -
 -      if (nested_len < 0)
 -              return -EINVAL;
 -      if (nested_len >= nla_attr_size(0))
 -              return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len),
 -                               nested_len, policy);
 -      memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
 -      return 0;
 -}
 -
 -#define nla_parse_nested_compat(tb, maxtype, nla, policy, data, len) \
 -({    data = nla_len(nla) >= len ? nla_data(nla) : NULL; \
 -      __nla_parse_nested_compat(tb, maxtype, nla, policy, len); })
  /**
   * nla_put_u8 - Add a u8 netlink attribute to a socket buffer
   * @skb: socket buffer to add attribute to
@@@ -993,6 -1030,51 +993,6 @@@ static inline int nla_nest_end(struct s
        return skb->len;
  }
  
 -/**
 - * nla_nest_compat_start - Start a new level of nested compat attributes
 - * @skb: socket buffer to add attributes to
 - * @attrtype: attribute type of container
 - * @attrlen: length of structure
 - * @data: pointer to structure
 - *
 - * Start a nested compat attribute that contains both a structure and
 - * a set of nested attributes.
 - *
 - * Returns the container attribute
 - */
 -static inline struct nlattr *nla_nest_compat_start(struct sk_buff *skb,
 -                                                 int attrtype, int attrlen,
 -                                                 const void *data)
 -{
 -      struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
 -
 -      if (nla_put(skb, attrtype, attrlen, data) < 0)
 -              return NULL;
 -      if (nla_nest_start(skb, attrtype) == NULL) {
 -              nlmsg_trim(skb, start);
 -              return NULL;
 -      }
 -      return start;
 -}
 -
 -/**
 - * nla_nest_compat_end - Finalize nesting of compat attributes
 - * @skb: socket buffer the attributes are stored in
 - * @start: container attribute
 - *
 - * Corrects the container attribute header to include the all
 - * appeneded attributes.
 - *
 - * Returns the total data length of the skb.
 - */
 -static inline int nla_nest_compat_end(struct sk_buff *skb, struct nlattr *start)
 -{
 -      struct nlattr *nest = (void *)start + NLMSG_ALIGN(start->nla_len);
 -
 -      start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
 -      return nla_nest_end(skb, nest);
 -}
 -
  /**
   * nla_nest_cancel - Cancel nesting of attributes
   * @skb: socket buffer the message is stored in
diff --combined net/core/dev.c
index 2cc258b7accec4c2f82c4dc5f3a88bc7c61b1df8,e8eb2b478344cfcc3e0540d2cb15b94f9c7c1dc5..7091040e32ac53e255e99aa4d2c62b9a9056ca7f
  #include <linux/if_arp.h>
  #include <linux/if_vlan.h>
  #include <linux/ip.h>
+ #include <net/ip.h>
  #include <linux/ipv6.h>
  #include <linux/in.h>
  #include <linux/jhash.h>
@@@ -890,7 -891,7 +891,7 @@@ int dev_alloc_name(struct net_device *d
   *    Change name of a device, can pass format strings "eth%d".
   *    for wildcarding.
   */
 -int dev_change_name(struct net_device *dev, char *newname)
 +int dev_change_name(struct net_device *dev, const char *newname)
  {
        char oldname[IFNAMSIZ];
        int err = 0;
                err = dev_alloc_name(dev, newname);
                if (err < 0)
                        return err;
 -              strcpy(newname, dev->name);
        }
        else if (__dev_get_by_name(net, newname))
                return -EEXIST;
@@@ -952,38 -954,6 +953,38 @@@ rollback
        return err;
  }
  
 +/**
 + *    dev_set_alias - change ifalias of a device
 + *    @dev: device
 + *    @alias: name up to IFALIASZ
 + *    @len: limit of bytes to copy from info
 + *
 + *    Set ifalias for a device,
 + */
 +int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
 +{
 +      ASSERT_RTNL();
 +
 +      if (len >= IFALIASZ)
 +              return -EINVAL;
 +
 +      if (!len) {
 +              if (dev->ifalias) {
 +                      kfree(dev->ifalias);
 +                      dev->ifalias = NULL;
 +              }
 +              return 0;
 +      }
 +
 +      dev->ifalias = krealloc(dev->ifalias, len+1, GFP_KERNEL);
 +      if (!dev->ifalias)
 +              return -ENOMEM;
 +
 +      strlcpy(dev->ifalias, alias, len+1);
 +      return len;
 +}
 +
 +
  /**
   *    netdev_features_change - device changes features
   *    @dev: device to cause notification
@@@ -1698,7 -1668,7 +1699,7 @@@ static u16 simple_tx_hash(struct net_de
  {
        u32 addr1, addr2, ports;
        u32 hash, ihl;
-       u8 ip_proto;
+       u8 ip_proto = 0;
  
        if (unlikely(!simple_tx_hashrnd_initialized)) {
                get_random_bytes(&simple_tx_hashrnd, 4);
        }
  
        switch (skb->protocol) {
 -      case __constant_htons(ETH_P_IP):
 +      case htons(ETH_P_IP):
-               ip_proto = ip_hdr(skb)->protocol;
+               if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)))
+                       ip_proto = ip_hdr(skb)->protocol;
                addr1 = ip_hdr(skb)->saddr;
                addr2 = ip_hdr(skb)->daddr;
                ihl = ip_hdr(skb)->ihl;
                break;
 -      case __constant_htons(ETH_P_IPV6):
 +      case htons(ETH_P_IPV6):
                ip_proto = ipv6_hdr(skb)->nexthdr;
                addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
                addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
@@@ -3331,12 -3302,6 +3333,12 @@@ static void dev_addr_discard(struct net
        netif_addr_unlock_bh(dev);
  }
  
 +/**
 + *    dev_get_flags - get flags reported to userspace
 + *    @dev: device
 + *
 + *    Get the combination of flag bits exported through APIs to userspace.
 + */
  unsigned dev_get_flags(const struct net_device *dev)
  {
        unsigned flags;
        return flags;
  }
  
 +/**
 + *    dev_change_flags - change device settings
 + *    @dev: device
 + *    @flags: device state flags
 + *
 + *    Change settings on device based state flags. The flags are
 + *    in the userspace exported format.
 + */
  int dev_change_flags(struct net_device *dev, unsigned flags)
  {
        int ret, changes;
        return ret;
  }
  
 +/**
 + *    dev_set_mtu - Change maximum transfer unit
 + *    @dev: device
 + *    @new_mtu: new transfer unit
 + *
 + *    Change the maximum transfer size of the network device.
 + */
  int dev_set_mtu(struct net_device *dev, int new_mtu)
  {
        int err;
        return err;
  }
  
 +/**
 + *    dev_set_mac_address - Change Media Access Control Address
 + *    @dev: device
 + *    @sa: new address
 + *
 + *    Change the hardware (MAC) address of the device
 + */
  int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
  {
        int err;
@@@ -4379,12 -4322,7 +4381,12 @@@ void free_netdev(struct net_device *dev
        put_device(&dev->dev);
  }
  
 -/* Synchronize with packet receive processing. */
 +/**
 + *    synchronize_net -  Synchronize with packet receive processing
 + *
 + *    Wait for packets currently being received to be done.
 + *    Does not block later packets from starting.
 + */
  void synchronize_net(void)
  {
        might_sleep();
@@@ -4686,7 -4624,7 +4688,7 @@@ netdev_dma_event(struct dma_client *cli
  }
  
  /**
 - * netdev_dma_regiser - register the networking subsystem as a DMA client
 + * netdev_dma_register - register the networking subsystem as a DMA client
   */
  static int __init netdev_dma_register(void)
  {
@@@ -4732,12 -4670,6 +4734,12 @@@ int netdev_compute_features(unsigned lo
                one |= NETIF_F_GSO_SOFTWARE;
        one |= NETIF_F_GSO;
  
 +      /*
 +       * If even one device supports a GSO protocol with software fallback,
 +       * enable it for all.
 +       */
 +      all |= one & NETIF_F_GSO_SOFTWARE;
 +
        /* If even one device supports robust GSO, enable it for all. */
        if (one & NETIF_F_GSO_ROBUST)
                all |= NETIF_F_GSO_ROBUST;
@@@ -4787,18 -4719,10 +4789,18 @@@ err_name
        return -ENOMEM;
  }
  
 -char *netdev_drivername(struct net_device *dev, char *buffer, int len)
 +/**
 + *    netdev_drivername - network driver for the device
 + *    @dev: network device
 + *    @buffer: buffer for resulting name
 + *    @len: size of buffer
 + *
 + *    Determine network driver for device.
 + */
 +char *netdev_drivername(const struct net_device *dev, char *buffer, int len)
  {
 -      struct device_driver *driver;
 -      struct device *parent;
 +      const struct device_driver *driver;
 +      const struct device *parent;
  
        if (len <= 0 || !buffer)
                return buffer;
diff --combined net/ipv4/tcp_ipv4.c
index 44aef1c1f37332b3583fbf05352afe7688faeca1,011478e46c406bd7dd75c2b2d06f578714d98606..d13688e3558d1a48728d32e13a38ba09309ec573
@@@ -618,7 -618,7 +618,7 @@@ static void tcp_v4_send_ack(struct sk_b
                        ];
        } rep;
        struct ip_reply_arg arg;
-       struct net *net = dev_net(skb->dev);
+       struct net *net = dev_net(skb->dst->dev);
  
        memset(&rep.th, 0, sizeof(struct tcphdr));
        memset(&arg, 0, sizeof(arg));
@@@ -1364,10 -1364,6 +1364,10 @@@ struct sock *tcp_v4_syn_recv_sock(struc
        tcp_mtup_init(newsk);
        tcp_sync_mss(newsk, dst_mtu(dst));
        newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
 +      if (tcp_sk(sk)->rx_opt.user_mss &&
 +          tcp_sk(sk)->rx_opt.user_mss < newtp->advmss)
 +              newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
 +
        tcp_initialize_rcv_mss(newsk);
  
  #ifdef CONFIG_TCP_MD5SIG
@@@ -1950,12 -1946,6 +1950,12 @@@ static void *listening_get_idx(struct s
        return rc;
  }
  
 +static inline int empty_bucket(struct tcp_iter_state *st)
 +{
 +      return hlist_empty(&tcp_hashinfo.ehash[st->bucket].chain) &&
 +              hlist_empty(&tcp_hashinfo.ehash[st->bucket].twchain);
 +}
 +
  static void *established_get_first(struct seq_file *seq)
  {
        struct tcp_iter_state* st = seq->private;
                struct inet_timewait_sock *tw;
                rwlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket);
  
 +              /* Lockless fast path for the common case of empty buckets */
 +              if (empty_bucket(st))
 +                      continue;
 +
                read_lock_bh(lock);
                sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
                        if (sk->sk_family != st->family ||
@@@ -2022,15 -2008,13 +2022,15 @@@ get_tw
                read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
                st->state = TCP_SEQ_STATE_ESTABLISHED;
  
 -              if (++st->bucket < tcp_hashinfo.ehash_size) {
 -                      read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
 -                      sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
 -              } else {
 -                      cur = NULL;
 -                      goto out;
 -              }
 +              /* Look for next non empty bucket */
 +              while (++st->bucket < tcp_hashinfo.ehash_size &&
 +                              empty_bucket(st))
 +                      ;
 +              if (st->bucket >= tcp_hashinfo.ehash_size)
 +                      return NULL;
 +
 +              read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
 +              sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
        } else
                sk = sk_next(sk);
  
diff --combined net/ipv6/route.c
index 776871ee22886f41631504fd6a9b740d909df9d7,63442a1e741c630cb7936702f3e0690353e11a5b..f4385a6569c2c0531ddefdd530f999768d359f88
@@@ -1003,25 -1003,6 +1003,25 @@@ int icmp6_dst_gc(void
        return more;
  }
  
 +static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg),
 +                          void *arg)
 +{
 +      struct dst_entry *dst, **pprev;
 +
 +      spin_lock_bh(&icmp6_dst_lock);
 +      pprev = &icmp6_dst_gc_list;
 +      while ((dst = *pprev) != NULL) {
 +              struct rt6_info *rt = (struct rt6_info *) dst;
 +              if (func(rt, arg)) {
 +                      *pprev = dst->next;
 +                      dst_free(dst);
 +              } else {
 +                      pprev = &dst->next;
 +              }
 +      }
 +      spin_unlock_bh(&icmp6_dst_lock);
 +}
 +
  static int ip6_dst_gc(struct dst_ops *ops)
  {
        unsigned long now = jiffies;
@@@ -1949,7 -1930,6 +1949,7 @@@ void rt6_ifdown(struct net *net, struc
        };
  
        fib6_clean_all(net, fib6_ifdown, 0, &adn);
 +      icmp6_clean_all(fib6_ifdown, &adn);
  }
  
  struct rt6_mtu_change_arg
@@@ -2708,6 -2688,8 +2708,8 @@@ int __init ip6_route_init(void
        if (ret)
                goto out_kmem_cache;
  
+       ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
        /* Registering of the loopback is done before this portion of code,
         * the loopback reference in rt6_info will not be taken, do it
         * manually for init_net */
diff --combined net/ipv6/tcp_ipv6.c
index e85f377a8f82c671a3eb3d99698fa443632d51fc,10e22fd482225c0b49c17646fa0e347a6250904f..df16b68644e79dc5a52801ddc5334d866860223e
@@@ -1050,7 -1050,7 +1050,7 @@@ static void tcp_v6_send_ack(struct sk_b
        struct tcphdr *th = tcp_hdr(skb), *t1;
        struct sk_buff *buff;
        struct flowi fl;
-       struct net *net = dev_net(skb->dev);
+       struct net *net = dev_net(skb->dst->dev);
        struct sock *ctl_sk = net->ipv6.tcp_sk;
        unsigned int tot_len = sizeof(struct tcphdr);
        __be32 *topt;
@@@ -1286,7 -1286,7 +1286,7 @@@ static struct sock * tcp_v6_syn_recv_so
                                          struct request_sock *req,
                                          struct dst_entry *dst)
  {
 -      struct inet6_request_sock *treq = inet6_rsk(req);
 +      struct inet6_request_sock *treq;
        struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
        struct tcp6_sock *newtcp6sk;
        struct inet_sock *newinet;
                return newsk;
        }
  
 +      treq = inet6_rsk(req);
        opt = np->opt;
  
        if (sk_acceptq_is_full(sk))