[haiku-commits] haiku: hrev52091 - in src: add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi . libs/compat add-ons/kernel/busses/scsi/ahci

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 10 Jul 2018 18:41:52 -0400 (EDT)

hrev52091 adds 7 changesets to branch 'master'
old head: e88a89e6765f96b7d88411cf73cefcf9d908f393
new head: ecdc1bc8e7aa72886927a76915615698a44dee4a
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=ecdc1bc8e7aa+%5Ee88a89e6765f

----------------------------------------------------------------------------

ffd36865cf3e: sata_request: Cargo-cult some behaviors from FreeBSD.
  
  See 13778#comment:3 for information on FreeBSD behaviors.
  
  I didn't manage to locate where the specification talks about this
  (but my specification-fu is rather poor), and it didn't fix the check_sense
  syslog spamming on my machine.
  
  But it seems to continue to function as before on my hardware as well as
  VirtualBox and VMware, so perhaps it might fix something else.
  
  Signed-off-by: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>

de6ea5f43f18: vfs: Move volume->ops NULL check to just after call to mount().
  
  As Rene pointed out on the mailing list, if this is NULL after the file system
  mount call occurs, then something has gone very wrong and we should treat it
  as an error.

e6f6c1b46335: freebsd11_wlan: Don't try to ifdetach if we never ifattached.
  
  The FreeBSD developers say that there are "lots of bugs around driver attach
  failures," and this looks like one of them.
  
  Hopefully helps with #12035.

e131a159c3dd: iprowifi2200: Sync with FreeBSD 11.1.
  
  Untested, but the changes are relatively minimal (mostly adapations
  to the new FreeBSD KPIs), and ttcoder recently opened a ticket (#14258)
  about it, so he can test.

77cf4765673f: iprowifi3945: Disable hardware AES.
  
  Recommended by the FreeBSD developers as "possibly broken." Hopefully
  helps with #14260.

1a353444277f: freebsd11_network: Only start_wlan if FBSD_WLAN_FEATURE is 
required.
  
  Fixes #8634.

ecdc1bc8e7aa: freebsd11_wlan: Add missing mtx_destroy of the ic_list_mtx.

                              [ Augustin Cavalier <waddlesplash@xxxxxxxxx> ]

----------------------------------------------------------------------------

13 files changed, 417 insertions(+), 269 deletions(-)
.../kernel/busses/scsi/ahci/sata_request.cpp     |  16 +-
.../kernel/busses/scsi/ahci/sata_request.h       |   3 +-
src/add-ons/kernel/drivers/network/wlan/Jamfile  |   2 +-
.../drivers/network/wlan/iprowifi2200/Jamfile    |  16 +-
.../network/wlan/iprowifi2200/dev/iwi/if_iwi.c   | 502 ++++++++++---------
.../wlan/iprowifi2200/dev/iwi/if_iwi_ioctl.h     |  25 +
.../wlan/iprowifi2200/dev/iwi/if_iwireg.h        |  67 ++-
.../wlan/iprowifi2200/dev/iwi/if_iwivar.h        |  17 +-
.../network/wlan/iprowifi3945/dev/wpi/if_wpi.c   |   2 +
src/libs/compat/freebsd11_network/compat.c       |   8 +-
.../compat/freebsd11_wlan/net80211/ieee80211.c   |  20 +-
.../freebsd11_wlan/net80211/ieee80211_haiku.cpp  |   2 +
src/system/kernel/fs/vfs.cpp                     |   6 +-

############################################################################

Commit:      ffd36865cf3e66a57f5b1c5e938d53bdbd1c9933
URL:         https://git.haiku-os.org/haiku/commit/?id=ffd36865cf3e
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Tue Jul 10 01:51:08 2018 UTC

sata_request: Cargo-cult some behaviors from FreeBSD.

See 13778#comment:3 for information on FreeBSD behaviors.

I didn't manage to locate where the specification talks about this
(but my specification-fu is rather poor), and it didn't fix the check_sense
syslog spamming on my machine.

But it seems to continue to function as before on my hardware as well as
VirtualBox and VMware, so perhaps it might fix something else.

Signed-off-by: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
index 9e06dceab6..65d22917e3 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
@@ -1,6 +1,7 @@
 /*
  * Copyright 2008, Marcus Overhagen. All rights reserved.
- * Distributed under the terms of the MIT License.
+ * Copyright 2009-2018, Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT license.
  */
 
 
@@ -12,6 +13,9 @@
 
 #define FIS_TYPE_REGISTER_HOST_TO_DEVICE 0x27
 
+#define ATA_D_LBA              0x40    /* use LBA addressing */
+#define ATA_A_4BIT             0x08    /* 4 head bits */
+
 
 sata_request::sata_request()
        :
@@ -60,7 +64,10 @@ sata_request::SetATACommand(uint8 command)
        fFis[0] = FIS_TYPE_REGISTER_HOST_TO_DEVICE;
        fFis[1] = 0x80;
                // This is a command
+       if (fCcb != NULL)
+               fFis[1] |= fCcb->target_id & 0x0f;
        fFis[2] = command;
+       fFis[15] = ATA_A_4BIT;
 }
 
 
@@ -71,8 +78,7 @@ sata_request::SetATA28Command(uint8 command, uint32 lba, 
uint8 sectorCount)
        fFis[4] = lba & 0xff;
        fFis[5] = (lba >> 8) & 0xff;
        fFis[6] = (lba >> 16) & 0xff;
-       fFis[7] = 0x40 | ((lba >> 24) & 0x0f);
-               // device
+       fFis[7] = ATA_D_LBA | ((lba >> 24) & 0x0f);
        fFis[12] = sectorCount & 0xff;
 }
 
@@ -84,8 +90,7 @@ sata_request::SetATA48Command(uint8 command, uint64 lba, 
uint16 sectorCount)
        fFis[4] = lba & 0xff;
        fFis[5] = (lba >> 8) & 0xff;
        fFis[6] = (lba >> 16) & 0xff;
-       fFis[7] = 0x40;
-               // device
+       fFis[7] = ATA_D_LBA;
        fFis[8] = (lba >> 24) & 0xff;
        fFis[9] = (lba >> 32) & 0xff;
        fFis[10] = (lba >> 40) & 0xff;
@@ -107,6 +112,7 @@ sata_request::SetATAPICommand(size_t transferLength)
 {
        fIsATAPI = true;
        SetATACommand(0xa0);
+       fFis[7] = ATA_D_LBA;
        if (1 /* isPIO */) {
                if (transferLength == 0)
                        transferLength = 2;
diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h 
b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
index 5686530fa0..5e6afad1ed 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
@@ -1,6 +1,7 @@
 /*
  * Copyright 2008, Marcus Overhagen. All rights reserved.
- * Distributed under the terms of the MIT License.
+ * Copyright 2009-2018, Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT license.
  */
 #ifndef _SATA_REQUEST_H
 #define _SATA_REQUEST_H

############################################################################

Commit:      de6ea5f43f18620795c8eebeaba56fc8874eb414
URL:         https://git.haiku-os.org/haiku/commit/?id=de6ea5f43f18
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Tue Jul 10 21:46:59 2018 UTC

vfs: Move volume->ops NULL check to just after call to mount().

As Rene pointed out on the mailing list, if this is NULL after the file system
mount call occurs, then something has gone very wrong and we should treat it
as an error.

----------------------------------------------------------------------------

diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp
index 122107e598..3b3c6bb7a5 100644
--- a/src/system/kernel/fs/vfs.cpp
+++ b/src/system/kernel/fs/vfs.cpp
@@ -7497,7 +7497,7 @@ fs_mount(char* path, const char* device, const char* 
fsName, uint32 flags,
 
                status = mount->volume->file_system->mount(mount->volume, 
device, flags,
                        args, &rootID);
-               if (status != 0)
+               if (status != B_OK || mount->volume->ops == NULL)
                        goto err2;
        } else {
                status = path_to_vnode(path, true, &coveredNode, NULL, kernel);
@@ -7523,7 +7523,7 @@ fs_mount(char* path, const char* device, const char* 
fsName, uint32 flags,
                while (volume) {
                        status = volume->file_system->mount(volume, device, 
flags, args,
                                &rootID);
-                       if (status != B_OK) {
+                       if (status != B_OK || volume->ops == NULL) {
                                if (volume->sub_volume)
                                        goto err4;
                                goto err3;
@@ -7534,7 +7534,7 @@ fs_mount(char* path, const char* device, const char* 
fsName, uint32 flags,
 
                volume = mount->volume;
                while (volume) {
-                       if (volume->ops != NULL && 
volume->ops->all_layers_mounted != NULL)
+                       if (volume->ops->all_layers_mounted != NULL)
                                volume->ops->all_layers_mounted(volume);
                        volume = volume->super_volume;
                }

############################################################################

Commit:      e6f6c1b4633532a8ad37c803dc7c65601e5b24ba
URL:         https://git.haiku-os.org/haiku/commit/?id=e6f6c1b46335
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Tue Jul 10 21:57:01 2018 UTC

Ticket:      https://dev.haiku-os.org/ticket/12035

freebsd11_wlan: Don't try to ifdetach if we never ifattached.

The FreeBSD developers say that there are "lots of bugs around driver attach
failures," and this looks like one of them.

Hopefully helps with #12035.

----------------------------------------------------------------------------

diff --git a/src/libs/compat/freebsd11_wlan/net80211/ieee80211.c 
b/src/libs/compat/freebsd11_wlan/net80211/ieee80211.c
index 858b90612d..b4f38a77fb 100644
--- a/src/libs/compat/freebsd11_wlan/net80211/ieee80211.c
+++ b/src/libs/compat/freebsd11_wlan/net80211/ieee80211.c
@@ -248,14 +248,14 @@ null_update_chw(struct ieee80211com *ic)
 
 int
 ic_printf(struct ieee80211com *ic, const char * fmt, ...)
-{ 
+{
        va_list ap;
        int retval;
 
        retval = printf("%s: ", ic->ic_name);
        va_start(ap, fmt);
        retval += vprintf(fmt, ap);
-       va_end(ap);  
+       va_end(ap);
        return (retval);
 }
 
@@ -366,6 +366,12 @@ ieee80211_ifdetach(struct ieee80211com *ic)
        LIST_REMOVE(ic, ic_next);
        mtx_unlock(&ic_list_mtx);
 
+#ifdef __HAIKU__
+       /* Have we even initialized this com? */
+       if (!ic->ic_tq)
+               return;
+#endif
+
        taskqueue_drain(taskqueue_thread, &ic->ic_restart_task);
 
        /*
@@ -644,7 +650,7 @@ ieee80211_vap_attach(struct ieee80211vap *vap, 
ifm_change_cb_t media_change,
        return 1;
 }
 
-/* 
+/*
  * Tear down vap state and reclaim the ifnet.
  * The driver is assumed to have prepared for
  * this; e.g. by turning off interrupts for the
@@ -1365,7 +1371,7 @@ addmedia(struct ifmedia *media, int caps, int addsta, int 
mode, int mword)
 #define        ADD(_ic, _s, _o) \
        ifmedia_add(media, \
                IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)
-       static const u_int mopts[IEEE80211_MODE_MAX] = { 
+       static const u_int mopts[IEEE80211_MODE_MAX] = {
            [IEEE80211_MODE_AUTO]       = IFM_AUTO,
            [IEEE80211_MODE_11A]        = IFM_IEEE80211_11A,
            [IEEE80211_MODE_11B]        = IFM_IEEE80211_11B,
@@ -1963,13 +1969,13 @@ ieee80211_rate2media(struct ieee80211com *ic, int rate, 
enum ieee80211_phymode m
        case IEEE80211_MODE_11NA:
        case IEEE80211_MODE_TURBO_A:
        case IEEE80211_MODE_STURBO_A:
-               return findmedia(rates, nitems(rates), 
+               return findmedia(rates, nitems(rates),
                    rate | IFM_IEEE80211_11A);
        case IEEE80211_MODE_11B:
-               return findmedia(rates, nitems(rates), 
+               return findmedia(rates, nitems(rates),
                    rate | IFM_IEEE80211_11B);
        case IEEE80211_MODE_FH:
-               return findmedia(rates, nitems(rates), 
+               return findmedia(rates, nitems(rates),
                    rate | IFM_IEEE80211_FH);
        case IEEE80211_MODE_AUTO:
                /* NB: ic may be NULL for some drivers */

############################################################################

Commit:      e131a159c3ddeee3dbc51d75b4538fb6446fc9cf
URL:         https://git.haiku-os.org/haiku/commit/?id=e131a159c3dd
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Tue Jul 10 22:28:02 2018 UTC

Ticket:      https://dev.haiku-os.org/ticket/14258

iprowifi2200: Sync with FreeBSD 11.1.

Untested, but the changes are relatively minimal (mostly adapations
to the new FreeBSD KPIs), and ttcoder recently opened a ticket (#14258)
about it, so he can test.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/network/wlan/Jamfile 
b/src/add-ons/kernel/drivers/network/wlan/Jamfile
index ef4e08c303..e19ceeed18 100644
--- a/src/add-ons/kernel/drivers/network/wlan/Jamfile
+++ b/src/add-ons/kernel/drivers/network/wlan/Jamfile
@@ -10,13 +10,13 @@ SubInclude HAIKU_TOP src add-ons kernel drivers network 
wlan marvell88w8335 ;
 # FreeBSD 9.3 drivers
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan atheroswifi ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan broadcom43xx ;
-SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8363 ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan ralinkwifi ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan wavelanwifi ;
 
 # FreeBSD 11.1 drivers
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan aironetwifi ;
+SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi3945 ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi4965 ;
 
diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/Jamfile 
b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/Jamfile
index 0f81e1c581..e9b723b410 100644
--- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/Jamfile
+++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/Jamfile
@@ -1,8 +1,8 @@
 SubDir HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ;
 
-UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ]
+UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd11_network compat ]
        : true ;
-UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_wlan ] : true ;
+UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd11_wlan ] : true ;
 UsePrivateHeaders net system ;
 UsePrivateKernelHeaders ;
 
@@ -10,10 +10,10 @@ UsePrivateKernelHeaders ;
 Includes [ FGristFiles kernel_c++_structs.h ]
        : <src!system!kernel>kernel_c++_struct_sizes.h ;
 
-SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ] 
-       -Wno-format 
-       -Wno-unused 
-       -Wno-uninitialized 
+SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ]
+       -Wno-format
+       -Wno-unused
+       -Wno-uninitialized
        -Werror ;
 
 UseHeaders [ FDirName $(SUBDIR) ] : true ;
@@ -24,8 +24,8 @@ KernelAddon iprowifi2200 :
        if_iwi.c
        glue.c
        :
-       libfreebsd_wlan.a
-       libfreebsd_network.a
+       libfreebsd11_wlan.a
+       libfreebsd11_network.a
        ;
 
 # Note: Due to licensing restrictions, we can only distribute the archive.
diff --git 
a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c 
b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c
index 6d17b95611..c5a4b481f7 100644
--- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c
+++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: releng/11.2/sys/dev/iwi/if_iwi.c 332288 2018-04-08 
16:54:07Z brooks $");
 
 /*-
  * Intel(R) PRO/Wireless 2200BG/2225BG/2915ABG driver
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
 
 #include <net/bpf.h>
 #include <net/if.h>
+#include <net/if_var.h>
 #include <net/if_arp.h>
 #include <net/ethernet.h>
 #include <net/if_dl.h>
@@ -83,6 +84,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/iwi/if_iwireg.h>
 #include <dev/iwi/if_iwivar.h>
+#include <dev/iwi/if_iwi_ioctl.h>
 
 #define IWI_DEBUG
 #ifdef IWI_DEBUG
@@ -128,10 +130,19 @@ static const struct iwi_ident iwi_ident_table[] = {
        { 0, 0, NULL }
 };
 
+static const uint8_t def_chan_2ghz[] =
+       { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
+static const uint8_t def_chan_5ghz_band1[] =
+       { 36, 40, 44, 48, 52, 56, 60, 64 };
+static const uint8_t def_chan_5ghz_band2[] =
+       { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 };
+static const uint8_t def_chan_5ghz_band3[] =
+       { 149, 153, 157, 161, 165 };
+
 static struct ieee80211vap *iwi_vap_create(struct ieee80211com *,
-                   const char name[IFNAMSIZ], int unit, enum ieee80211_opmode 
opmode, int flags,
-                   const uint8_t bssid[IEEE80211_ADDR_LEN],
-                   const uint8_t mac[IEEE80211_ADDR_LEN]);
+                   const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
+                   const uint8_t [IEEE80211_ADDR_LEN],
+                   const uint8_t [IEEE80211_ADDR_LEN]);
 static void    iwi_vap_delete(struct ieee80211vap *);
 static void    iwi_dma_map_addr(void *, bus_dma_segment_t *, int, int);
 static int     iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *,
@@ -152,8 +163,7 @@ static void iwi_node_free(struct ieee80211_node *);
 static void    iwi_media_status(struct ifnet *, struct ifmediareq *);
 static int     iwi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
 static void    iwi_wme_init(struct iwi_softc *);
-static int     iwi_wme_setparams(struct iwi_softc *, struct ieee80211com *);
-static void    iwi_update_wme(void *, int);
+static int     iwi_wme_setparams(struct iwi_softc *);
 static int     iwi_wme_update(struct ieee80211com *);
 static uint16_t        iwi_read_prom_word(struct iwi_softc *, uint8_t);
 static void    iwi_frame_intr(struct iwi_softc *, struct iwi_rx_data *, int,
@@ -164,14 +174,15 @@ static void       iwi_tx_intr(struct iwi_softc *, struct 
iwi_tx_ring *);
 static void    iwi_intr(void *);
 static int     iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t);
 static void    iwi_write_ibssnode(struct iwi_softc *, const u_int8_t [], int);
-static int     iwi_tx_start(struct ifnet *, struct mbuf *,
+static int     iwi_tx_start(struct iwi_softc *, struct mbuf *,
                    struct ieee80211_node *, int);
 static int     iwi_raw_xmit(struct ieee80211_node *, struct mbuf *,
                    const struct ieee80211_bpf_params *);
-static void    iwi_start_locked(struct ifnet *);
-static void    iwi_start(struct ifnet *);
+static void    iwi_start(struct iwi_softc *);
+static int     iwi_transmit(struct ieee80211com *, struct mbuf *);
 static void    iwi_watchdog(void *);
-static int     iwi_ioctl(struct ifnet *, u_long, caddr_t);
+static int     iwi_ioctl(struct ieee80211com *, u_long, void *);
+static void    iwi_parent(struct ieee80211com *);
 static void    iwi_stop_master(struct iwi_softc *);
 static int     iwi_reset(struct iwi_softc *);
 static int     iwi_load_ucode(struct iwi_softc *, const struct iwi_fw *);
@@ -202,6 +213,9 @@ static void iwi_radio_off(void *, int);
 static void    iwi_sysctlattach(struct iwi_softc *);
 static void    iwi_led_event(struct iwi_softc *, int);
 static void    iwi_ledattach(struct iwi_softc *);
+static void    iwi_collect_bands(struct ieee80211com *, uint8_t [], size_t);
+static void    iwi_getradiocaps(struct ieee80211com *, int, int *,
+                   struct ieee80211_channel []);
 
 static int iwi_probe(device_t);
 static int iwi_attach(device_t);
@@ -267,23 +281,15 @@ static int
 iwi_attach(device_t dev)
 {
        struct iwi_softc *sc = device_get_softc(dev);
-       struct ifnet *ifp;
-       struct ieee80211com *ic;
+       struct ieee80211com *ic = &sc->sc_ic;
        uint16_t val;
        int i, error;
-       uint8_t bands;
-       uint8_t macaddr[IEEE80211_ADDR_LEN];
 
        sc->sc_dev = dev;
-
-       ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
-       if (ifp == NULL) {
-               device_printf(dev, "can not if_alloc()\n");
-               return ENXIO;
-       }
-       ic = ifp->if_l2com;
+       sc->sc_ledevent = ticks;
 
        IWI_LOCK_INIT(sc);
+       mbufq_init(&sc->sc_snd, ifqmaxlen);
 
        sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx);
 
@@ -291,7 +297,6 @@ iwi_attach(device_t dev)
        TASK_INIT(&sc->sc_radiofftask, 0, iwi_radio_off, sc);
        TASK_INIT(&sc->sc_restarttask, 0, iwi_restart, sc);
        TASK_INIT(&sc->sc_disassoctask, 0, iwi_disassoc, sc);
-       TASK_INIT(&sc->sc_wmetask, 0, iwi_update_wme, sc);
        TASK_INIT(&sc->sc_monitortask, 0, iwi_monitor_scan, sc);
 
        callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
@@ -351,17 +356,8 @@ iwi_attach(device_t dev)
 
        iwi_wme_init(sc);
 
-       ifp->if_softc = sc;
-       if_initname(ifp, device_get_name(dev), device_get_unit(dev));
-       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-       ifp->if_init = iwi_init;
-       ifp->if_ioctl = iwi_ioctl;
-       ifp->if_start = iwi_start;
-       IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
-       ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
-       IFQ_SET_READY(&ifp->if_snd);
-
-       ic->ic_ifp = ifp;
+       ic->ic_softc = sc;
+       ic->ic_name = device_get_nameunit(dev);
        ic->ic_opmode = IEEE80211_M_STA;
        ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
 
@@ -381,23 +377,19 @@ iwi_attach(device_t dev)
 
        /* read MAC address from EEPROM */
        val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
-       macaddr[0] = val & 0xff;
-       macaddr[1] = val >> 8;
+       ic->ic_macaddr[0] = val & 0xff;
+       ic->ic_macaddr[1] = val >> 8;
        val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1);
-       macaddr[2] = val & 0xff;
-       macaddr[3] = val >> 8;
+       ic->ic_macaddr[2] = val & 0xff;
+       ic->ic_macaddr[3] = val >> 8;
        val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2);
-       macaddr[4] = val & 0xff;
-       macaddr[5] = val >> 8;
-       
-       bands = 0;
-       setbit(&bands, IEEE80211_MODE_11B);
-       setbit(&bands, IEEE80211_MODE_11G);
-       if (pci_get_device(dev) >= 0x4223) 
-               setbit(&bands, IEEE80211_MODE_11A);
-       ieee80211_init_channels(ic, NULL, &bands);
-
-       ieee80211_ifattach(ic, macaddr);
+       ic->ic_macaddr[4] = val & 0xff;
+       ic->ic_macaddr[5] = val >> 8;
+
+       iwi_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
+           ic->ic_channels);
+
+       ieee80211_ifattach(ic);
        /* override default methods */
        ic->ic_node_alloc = iwi_node_alloc;
        sc->sc_node_free = ic->ic_node_free;
@@ -412,6 +404,10 @@ iwi_attach(device_t dev)
 
        ic->ic_vap_create = iwi_vap_create;
        ic->ic_vap_delete = iwi_vap_delete;
+       ic->ic_ioctl = iwi_ioctl;
+       ic->ic_transmit = iwi_transmit;
+       ic->ic_parent = iwi_parent;
+       ic->ic_getradiocaps = iwi_getradiocaps;
 
        ieee80211_radiotap_attach(ic,
            &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -446,8 +442,7 @@ static int
 iwi_detach(device_t dev)
 {
        struct iwi_softc *sc = device_get_softc(dev);
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
 
        bus_teardown_intr(dev, sc->irq, sc->sc_ih);
 
@@ -478,22 +473,20 @@ iwi_detach(device_t dev)
            sc->mem);
 
        delete_unrhdr(sc->sc_unr);
+       mbufq_drain(&sc->sc_snd);
 
        IWI_LOCK_DESTROY(sc);
 
-       if_free(ifp);
-
        return 0;
 }
 
 static struct ieee80211vap *
-iwi_vap_create(struct ieee80211com *ic,
-       const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, int 
flags,
-       const uint8_t bssid[IEEE80211_ADDR_LEN],
-       const uint8_t mac[IEEE80211_ADDR_LEN])
+iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
+    enum ieee80211_opmode opmode, int flags,
+    const uint8_t bssid[IEEE80211_ADDR_LEN],
+    const uint8_t mac[IEEE80211_ADDR_LEN])
 {
-       struct ifnet *ifp = ic->ic_ifp;
-       struct iwi_softc *sc = ifp->if_softc;
+       struct iwi_softc *sc = ic->ic_softc;
        struct iwi_vap *ivp;
        struct ieee80211vap *vap;
        int i;
@@ -515,12 +508,9 @@ iwi_vap_create(struct ieee80211com *ic,
        if (iwi_init_fw_dma(sc, i))
                return NULL;
 
-       ivp = (struct iwi_vap *) malloc(sizeof(struct iwi_vap),
-           M_80211_VAP, M_NOWAIT | M_ZERO);
-       if (ivp == NULL)
-               return NULL;
+       ivp = malloc(sizeof(struct iwi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
        vap = &ivp->iwi_vap;
-       ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+       ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
        /* override the default, the setting comes from the linux driver */
        vap->iv_bmissthreshold = 24;
        /* override with driver methods */
@@ -528,7 +518,8 @@ iwi_vap_create(struct ieee80211com *ic,
        vap->iv_newstate = iwi_newstate;
 
        /* complete setup */
-       ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status);
+       ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status,
+           mac);
        ic->ic_opmode = opmode;
        return vap;
 }
@@ -564,7 +555,7 @@ iwi_alloc_cmd_ring(struct iwi_softc *sc, struct 
iwi_cmd_ring *ring, int count)
 
        error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0,
            BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
-           count * IWI_CMD_DESC_SIZE, 1, count * IWI_CMD_DESC_SIZE, 0, 
+           count * IWI_CMD_DESC_SIZE, 1, count * IWI_CMD_DESC_SIZE, 0,
            NULL, NULL, &ring->desc_dmat);
        if (error != 0) {
                device_printf(sc->sc_dev, "could not create desc DMA tag\n");
@@ -609,7 +600,7 @@ iwi_free_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring 
*ring)
        }
 
        if (ring->desc_dmat != NULL)
-               bus_dma_tag_destroy(ring->desc_dmat);   
+               bus_dma_tag_destroy(ring->desc_dmat);
 }
 
 static int
@@ -626,7 +617,7 @@ iwi_alloc_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring 
*ring, int count,
 
        error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0,
            BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
-           count * IWI_TX_DESC_SIZE, 1, count * IWI_TX_DESC_SIZE, 0, NULL, 
+           count * IWI_TX_DESC_SIZE, 1, count * IWI_TX_DESC_SIZE, 0, NULL,
            NULL, &ring->desc_dmat);
        if (error != 0) {
                device_printf(sc->sc_dev, "could not create desc DMA tag\n");
@@ -780,7 +771,7 @@ iwi_alloc_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring 
*ring, int count)
                        goto fail;
                }
 
-               data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+               data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
                if (data->m == NULL) {
                        device_printf(sc->sc_dev,
                            "could not allocate rx mbuf\n");
@@ -855,9 +846,9 @@ static int
 iwi_suspend(device_t dev)
 {
        struct iwi_softc *sc = device_get_softc(dev);
+       struct ieee80211com *ic = &sc->sc_ic;
 
-       iwi_stop(sc);
-
+       ieee80211_suspend_all(ic);
        return 0;
 }
 
@@ -865,13 +856,11 @@ static int
 iwi_resume(device_t dev)
 {
        struct iwi_softc *sc = device_get_softc(dev);
-       struct ifnet *ifp = sc->sc_ifp;
+       struct ieee80211com *ic = &sc->sc_ic;
 
        pci_write_config(dev, 0x41, 0, 1);
 
-       if (ifp->if_flags & IFF_UP)
-               iwi_init(sc);
-
+       ieee80211_resume_all(ic);
        return 0;
 }
 
@@ -893,7 +882,7 @@ static void
 iwi_node_free(struct ieee80211_node *ni)
 {
        struct ieee80211com *ic = ni->ni_ic;
-       struct iwi_softc *sc = ic->ic_ifp->if_softc;
+       struct iwi_softc *sc = ic->ic_softc;
        struct iwi_node *in = (struct iwi_node *)ni;
 
        if (in->in_station != -1) {
@@ -905,7 +894,7 @@ iwi_node_free(struct ieee80211_node *ni)
        sc->sc_node_free(ni);
 }
 
-/* 
+/*
  * Convert h/w rate code to IEEE rate code.
  */
 static int
@@ -937,11 +926,14 @@ iwi_media_status(struct ifnet *ifp, struct ifmediareq 
*imr)
 {
        struct ieee80211vap *vap = ifp->if_softc;
        struct ieee80211com *ic = vap->iv_ic;
-       struct iwi_softc *sc = ic->ic_ifp->if_softc;
+       struct iwi_softc *sc = ic->ic_softc;
+       struct ieee80211_node *ni;
 
        /* read current transmission rate from adapter */
-       vap->iv_bss->ni_txrate =
+       ni = ieee80211_ref_node(vap->iv_bss);
+       ni->ni_txrate =
            iwi_cvtrate(CSR_READ_4(sc, IWI_CSR_CURRENT_TX_RATE));
+       ieee80211_free_node(ni);
        ieee80211_media_status(ifp, imr);
 }
 
@@ -950,8 +942,7 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state 
nstate, int arg)
 {
        struct iwi_vap *ivp = IWI_VAP(vap);
        struct ieee80211com *ic = vap->iv_ic;
-       struct ifnet *ifp = ic->ic_ifp;
-       struct iwi_softc *sc = ifp->if_softc;
+       struct iwi_softc *sc = ic->ic_softc;
        IWI_LOCK_DECL;
 
        DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
@@ -1054,8 +1045,9 @@ iwi_wme_init(struct iwi_softc *sc)
 }
 
 static int
-iwi_wme_setparams(struct iwi_softc *sc, struct ieee80211com *ic)
+iwi_wme_setparams(struct iwi_softc *sc)
 {
+       struct ieee80211com *ic = &sc->sc_ic;
        const struct wmeParams *wmep;
        int ac;
 
@@ -1075,23 +1067,12 @@ iwi_wme_setparams(struct iwi_softc *sc, struct 
ieee80211com *ic)
 #undef IWI_USEC
 #undef IWI_EXP2
 
-static void
-iwi_update_wme(void *arg, int npending)
-{
-       struct ieee80211com *ic = arg;
-       struct iwi_softc *sc = ic->ic_ifp->if_softc;
-       IWI_LOCK_DECL;
-
-       IWI_LOCK(sc);
-       (void) iwi_wme_setparams(sc, ic);
-       IWI_UNLOCK(sc);
-}
-
 static int
 iwi_wme_update(struct ieee80211com *ic)
 {
-       struct iwi_softc *sc = ic->ic_ifp->if_softc;
+       struct iwi_softc *sc = ic->ic_softc;
        struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+       IWI_LOCK_DECL;
 
        /*
         * We may be called to update the WME parameters in
@@ -1101,8 +1082,11 @@ iwi_wme_update(struct ieee80211com *ic)
         * to the adapter as part of the work iwi_auth_and_assoc
         * does.
         */
-       if (vap->iv_state == IEEE80211_S_RUN)
-               ieee80211_runtask(ic, &sc->sc_wmetask);
+       if (vap->iv_state == IEEE80211_S_RUN) {
+               IWI_LOCK(sc);
+               iwi_wme_setparams(sc);
+               IWI_UNLOCK(sc);
+       }
        return (0);
 }
 
@@ -1184,8 +1168,7 @@ iwi_read_prom_word(struct iwi_softc *sc, uint8_t addr)
 static void
 iwi_setcurchan(struct iwi_softc *sc, int chan)
 {
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
 
        sc->curchan = chan;
        ieee80211_radiotap_chan_change(ic);
@@ -1195,8 +1178,7 @@ static void
 iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
     struct iwi_frame *frame)
 {
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
        struct mbuf *mnew, *m;
        struct ieee80211_node *ni;
        int type, error, framelen;
@@ -1230,9 +1212,9 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data 
*data, int i,
         * drop the received packet and reuse the old mbuf. In the unlikely
         * case that the old mbuf can't be reloaded either, explicitly panic.
         */
-       mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+       mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
        if (mnew == NULL) {
-               ifp->if_ierrors++;
+               counter_u64_add(ic->ic_ierrors, 1);
                return;
        }
 
@@ -1253,7 +1235,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data 
*data, int i,
                        panic("%s: could not load old rx mbuf",
                            device_get_name(sc->sc_dev));
                }
-               ifp->if_ierrors++;
+               counter_u64_add(ic->ic_ierrors, 1);
                return;
        }
 
@@ -1266,7 +1248,6 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data 
*data, int i,
        CSR_WRITE_4(sc, data->reg, data->physaddr);
 
        /* finalize mbuf */
-       m->m_pkthdr.rcvif = ifp;
        m->m_pkthdr.len = m->m_len = sizeof (struct iwi_hdr) +
            sizeof (struct iwi_frame) + framelen;
 
@@ -1349,8 +1330,8 @@ iwi_checkforqos(struct ieee80211vap *vap,
        frm += 2;
 
        wme = NULL;
-       while (frm < efrm) {
-               IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1], return);
+       while (efrm - frm > 1) {
+               IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
                switch (*frm) {
                case IEEE80211_ELEMID_VENDOR:
                        if (iswmeoui(frm))
@@ -1360,16 +1341,44 @@ iwi_checkforqos(struct ieee80211vap *vap,
                frm += frm[1] + 2;
        }
 
-       ni = vap->iv_bss;
+       ni = ieee80211_ref_node(vap->iv_bss);
        ni->ni_capinfo = capinfo;
        ni->ni_associd = associd & 0x3fff;
        if (wme != NULL)
                ni->ni_flags |= IEEE80211_NODE_QOS;
        else
                ni->ni_flags &= ~IEEE80211_NODE_QOS;
+       ieee80211_free_node(ni);
 #undef SUBTYPE
 }
 
+static void
+iwi_notif_link_quality(struct iwi_softc *sc, struct iwi_notif *notif)
+{
+       struct iwi_notif_link_quality *lq;
+       int len;
+
+       len = le16toh(notif->len);
+
+       DPRINTFN(5, ("Notification (%u) - len=%d, sizeof=%zu\n",
+           notif->type,
+           len,
+           sizeof(struct iwi_notif_link_quality)
+           ));
+
+       /* enforce length */
+       if (len != sizeof(struct iwi_notif_link_quality)) {
+               DPRINTFN(5, ("Notification: (%u) too short (%d)\n",
+                   notif->type,
+                   len));
+               return;
+       }
+
+       lq = (struct iwi_notif_link_quality *)(notif + 1);
+       memcpy(&sc->sc_linkqual, lq, sizeof(sc->sc_linkqual));
+       sc->sc_linkqual_valid = 1;
+}
+
 /*
  * Task queue callbacks for iwi_notification_intr used to avoid LOR's.
  */
@@ -1377,8 +1386,7 @@ iwi_checkforqos(struct ieee80211vap *vap,
 static void
 iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
 {
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
        struct iwi_notif_scan_channel *chan;
        struct iwi_notif_scan_complete *scan;
@@ -1539,9 +1547,12 @@ iwi_notification_intr(struct iwi_softc *sc, struct 
iwi_notif *notif)
 
        case IWI_NOTIF_TYPE_CALIBRATION:
        case IWI_NOTIF_TYPE_NOISE:
-       case IWI_NOTIF_TYPE_LINK_QUALITY:
+               /* XXX handle? */
                DPRINTFN(5, ("Notification (%u)\n", notif->type));
                break;
+       case IWI_NOTIF_TYPE_LINK_QUALITY:
+               iwi_notif_link_quality(sc, notif);
+               break;
 
        default:
                DPRINTF(("unknown notification type %u flags 0x%x len %u\n",
@@ -1596,47 +1607,33 @@ iwi_rx_intr(struct iwi_softc *sc)
 static void
 iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq)
 {
-       struct ifnet *ifp = sc->sc_ifp;
        struct iwi_tx_data *data;
        uint32_t hw;
 
        hw = CSR_READ_4(sc, txq->csr_ridx);
 
-       for (; txq->next != hw;) {
+       while (txq->next != hw) {
                data = &txq->data[txq->next];
-
+               DPRINTFN(15, ("tx done idx=%u\n", txq->next));
                bus_dmamap_sync(txq->data_dmat, data->map,
                    BUS_DMASYNC_POSTWRITE);
                bus_dmamap_unload(txq->data_dmat, data->map);
-               if (data->m->m_flags & M_TXCB)
-                       ieee80211_process_callback(data->ni, data->m, 0/*XXX*/);
-               m_freem(data->m);
-               data->m = NULL;
-               ieee80211_free_node(data->ni);
+               ieee80211_tx_complete(data->ni, data->m, 0);
                data->ni = NULL;
-
-               DPRINTFN(15, ("tx done idx=%u\n", txq->next));
-
-               ifp->if_opackets++;
-
+               data->m = NULL;
                txq->queued--;
                txq->next = (txq->next + 1) % IWI_TX_RING_COUNT;
        }
-
        sc->sc_tx_timer = 0;
-       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
        if (sc->sc_softled)
                iwi_led_event(sc, IWI_LED_TX);
-
-       iwi_start_locked(ifp);
+       iwi_start(sc);
 }
 
 static void
 iwi_fatal_error_intr(struct iwi_softc *sc)
 {
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
 
        device_printf(sc->sc_dev, "firmware error\n");
@@ -1652,10 +1649,8 @@ iwi_fatal_error_intr(struct iwi_softc *sc)
 static void
 iwi_radio_off_intr(struct iwi_softc *sc)
 {
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
 
-       ieee80211_runtask(ic, &sc->sc_radiofftask);
+       ieee80211_runtask(&sc->sc_ic, &sc->sc_radiofftask);
 }
 
 static void
@@ -1774,10 +1769,9 @@ iwi_write_ibssnode(struct iwi_softc *sc,
 }
 
 static int
-iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni,
+iwi_tx_start(struct iwi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
     int ac)
 {
-       struct iwi_softc *sc = ifp->if_softc;
        struct ieee80211vap *vap = ni->ni_vap;
        struct ieee80211com *ic = ni->ni_ic;
        struct iwi_node *in = (struct iwi_node *)ni;
@@ -1820,9 +1814,10 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct 
ieee80211_node *ni,
                                in->in_station = alloc_unr(sc->sc_unr);
                                if (in->in_station == -1) {
                                        /* h/w table is full */
+                                       if_inc_counter(ni->ni_vap->iv_ifp,
+                                           IFCOUNTER_OERRORS, 1);
                                        m_freem(m0);
                                        ieee80211_free_node(ni);
-                                       ifp->if_oerrors++;
                                        return 0;
                                }
                                iwi_write_ibssnode(sc,
@@ -1847,7 +1842,7 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct 
ieee80211_node *ni,
        } else
                staid = 0;
 
-       if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
+       if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_crypto_encap(ni, m0);
                if (k == NULL) {
                        m_freem(m0);
@@ -1882,7 +1877,7 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct 
ieee80211_node *ni,
                return error;
        }
        if (error != 0) {
-               mnew = m_defrag(m0, M_DONTWAIT);
+               mnew = m_defrag(m0, M_NOWAIT);
                if (mnew == NULL) {
                        device_printf(sc->sc_dev,
                            "could not defragment mbuf\n");
@@ -1948,127 +1943,141 @@ iwi_raw_xmit(struct ieee80211_node *ni, struct mbuf 
*m,
        return 0;
 }
 
+static int
+iwi_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+       struct iwi_softc *sc = ic->ic_softc;
+       int error;
+       IWI_LOCK_DECL;
+
+       IWI_LOCK(sc);
+       if (!sc->sc_running) {
+               IWI_UNLOCK(sc);
+               return (ENXIO);
+       }
+       error = mbufq_enqueue(&sc->sc_snd, m);
+       if (error) {
+               IWI_UNLOCK(sc);
+               return (error);
+       }
+       iwi_start(sc);
+       IWI_UNLOCK(sc);
+       return (0);
+}
+
 static void
-iwi_start_locked(struct ifnet *ifp)
+iwi_start(struct iwi_softc *sc)
 {
-       struct iwi_softc *sc = ifp->if_softc;
        struct mbuf *m;
        struct ieee80211_node *ni;
        int ac;
 
        IWI_LOCK_ASSERT(sc);
 
-       if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-               return;
-
-       for (;;) {
-               IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
-               if (m == NULL)
-                       break;
+       while ((m =  mbufq_dequeue(&sc->sc_snd)) != NULL) {
                ac = M_WME_GETAC(m);
                if (sc->txq[ac].queued > IWI_TX_RING_COUNT - 8) {
                        /* there is no place left in this ring; tail drop */
                        /* XXX tail drop */
-                       IFQ_DRV_PREPEND(&ifp->if_snd, m);
-                       ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+                       mbufq_prepend(&sc->sc_snd, m);
                        break;
                }
-
                ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
-               if (iwi_tx_start(ifp, m, ni, ac) != 0) {
+               if (iwi_tx_start(sc, m, ni, ac) != 0) {
+                       if_inc_counter(ni->ni_vap->iv_ifp,
+                           IFCOUNTER_OERRORS, 1);
                        ieee80211_free_node(ni);
-                       ifp->if_oerrors++;
                        break;
                }
-
                sc->sc_tx_timer = 5;
        }
 }
 
-static void
-iwi_start(struct ifnet *ifp)
-{
-       struct iwi_softc *sc = ifp->if_softc;
-       IWI_LOCK_DECL;
-
-       IWI_LOCK(sc);
-       iwi_start_locked(ifp);
-       IWI_UNLOCK(sc);
-}
-
 static void
 iwi_watchdog(void *arg)
 {
        struct iwi_softc *sc = arg;
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
 
        IWI_LOCK_ASSERT(sc);
 
        if (sc->sc_tx_timer > 0) {
                if (--sc->sc_tx_timer == 0) {
-                       if_printf(ifp, "device timeout\n");
-                       ifp->if_oerrors++;
+                       device_printf(sc->sc_dev, "device timeout\n");
+                       counter_u64_add(ic->ic_oerrors, 1);
                        ieee80211_runtask(ic, &sc->sc_restarttask);
                }
        }
        if (sc->sc_state_timer > 0) {
                if (--sc->sc_state_timer == 0) {
-                       if_printf(ifp, "firmware stuck in state %d, 
resetting\n",
+                       device_printf(sc->sc_dev,
+                           "firmware stuck in state %d, resetting\n",
                            sc->fw_state);
-                       if (sc->fw_state == IWI_FW_SCANNING) {
-                               struct ieee80211com *ic = ifp->if_l2com;
+                       if (sc->fw_state == IWI_FW_SCANNING)
                                
ieee80211_cancel_scan(TAILQ_FIRST(&ic->ic_vaps));
-                       }
                        ieee80211_runtask(ic, &sc->sc_restarttask);
                        sc->sc_state_timer = 3;
                }
        }
        if (sc->sc_busy_timer > 0) {
                if (--sc->sc_busy_timer == 0) {
-                       if_printf(ifp, "firmware command timeout, resetting\n");
+                       device_printf(sc->sc_dev,
+                           "firmware command timeout, resetting\n");
                        ieee80211_runtask(ic, &sc->sc_restarttask);
                }
        }
        callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
 }
 
+static void
+iwi_parent(struct ieee80211com *ic)
+{
+       struct iwi_softc *sc = ic->ic_softc;
+       int startall = 0;
+       IWI_LOCK_DECL;
+
+       IWI_LOCK(sc);
+       if (ic->ic_nrunning > 0) {
+               if (!sc->sc_running) {
+                       iwi_init_locked(sc);
+                       startall = 1;
+               }
+       } else if (sc->sc_running)
+               iwi_stop_locked(sc);
+       IWI_UNLOCK(sc);
+       if (startall)
+               ieee80211_start_all(ic);
+}
+
 static int
-iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+iwi_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
 {
-       struct iwi_softc *sc = ifp->if_softc;
-       struct ieee80211com *ic = ifp->if_l2com;
-       struct ifreq *ifr = (struct ifreq *) data;
-       int error = 0, startall = 0;
+       struct ifreq *ifr = data;
+       struct iwi_softc *sc = ic->ic_softc;
+       int error;
        IWI_LOCK_DECL;
 
+       IWI_LOCK(sc);
        switch (cmd) {
-       case SIOCSIFFLAGS:
-               IWI_LOCK(sc);
-               if (ifp->if_flags & IFF_UP) {
-                       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-                               iwi_init_locked(sc);
-                               startall = 1;
-                       }
-               } else {
-                       if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-                               iwi_stop_locked(sc);
-               }
-               IWI_UNLOCK(sc);
-               if (startall)
-                       ieee80211_start_all(ic);
-               break;
-       case SIOCGIFMEDIA:
-               error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
+#ifndef __HAIKU__
+       case SIOCGIWISTATS:
+               /* XXX validate permissions/memory/etc? */
+               error = copyout(&sc->sc_linkqual, ifr_data_get_ptr(ifr),
+                   sizeof(struct iwi_notif_link_quality));
                break;
-       case SIOCGIFADDR:
-               error = ether_ioctl(ifp, cmd, data);
+#endif
+       case SIOCZIWISTATS:
+               memset(&sc->sc_linkqual, 0,
+                   sizeof(struct iwi_notif_link_quality));
+               error = 0;
                break;
        default:
-               error = EINVAL;
+               error = ENOTTY;
                break;
        }
-       return error;
+       IWI_UNLOCK(sc);
+
+       return (error);
 }
 
 static void
@@ -2547,8 +2556,7 @@ iwi_setwepkeys(struct iwi_softc *sc, struct ieee80211vap 
*vap)
 static int
 iwi_config(struct iwi_softc *sc)
 {
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
        struct iwi_configuration config;
        struct iwi_rateset rs;
        struct iwi_txpower power;
@@ -2557,8 +2565,8 @@ iwi_config(struct iwi_softc *sc)
 
        IWI_LOCK_ASSERT(sc);
 
-       DPRINTF(("Setting MAC address to %6D\n", IF_LLADDR(ifp), ":"));
-       error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
+       DPRINTF(("Setting MAC address to %6D\n", ic->ic_macaddr, ":"));
+       error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_macaddr,
            IEEE80211_ADDR_LEN);
        if (error != 0)
                return error;
@@ -2678,7 +2686,7 @@ iwi_monitor_scan(void *arg, int npending)
 static int
 iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan)
 {
-       struct ieee80211com *ic;
+       struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211_channel *chan;
        struct ieee80211_scan_state *ss;
        struct iwi_scan_ext scan;
@@ -2695,7 +2703,6 @@ iwi_scanchan(struct iwi_softc *sc, unsigned long 
maxdwell, int allchan)
        }
        IWI_STATE_BEGIN(sc, IWI_FW_SCANNING);
 
-       ic = sc->sc_ifp->if_l2com;
        ss = ic->ic_scan;
 
        memset(&scan, 0, sizeof scan);
@@ -2809,7 +2816,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct 
ieee80211vap *vap)
 {
        struct ieee80211com *ic = vap->iv_ic;
        struct ifnet *ifp = vap->iv_ifp;
-       struct ieee80211_node *ni = vap->iv_bss;
+       struct ieee80211_node *ni;
        struct iwi_configuration config;
        struct iwi_associate *assoc = &sc->assoc;
        struct iwi_rateset rs;
@@ -2819,6 +2826,8 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct 
ieee80211vap *vap)
 
        IWI_LOCK_ASSERT(sc);
 
+       ni = ieee80211_ref_node(vap->iv_bss);
+
        if (sc->flags & IWI_FLAG_ASSOCIATED) {
                DPRINTF(("Already associated\n"));
                return (-1);
@@ -2899,7 +2908,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct 
ieee80211vap *vap)
 
        if ((vap->iv_flags & IEEE80211_F_WME) && ni->ni_ies.wme_ie != NULL) {
                /* NB: don't treat WME setup as failure */
-               if (iwi_wme_setparams(sc, ic) == 0 && iwi_wme_setie(sc) == 0)
+               if (iwi_wme_setparams(sc) == 0 && iwi_wme_setie(sc) == 0)
                        assoc->policy |= htole16(IWI_POLICY_WME);
                /* XXX complain on failure? */
        }
@@ -2931,7 +2940,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct 
ieee80211vap *vap)
                 * key setup.  This typically is due to a user app bug
                 * but if we blindly grab the key the firmware will
                 * barf so avoid it for now.
-                */ 
+                */
                if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE)
                        assoc->auth |= vap->iv_def_txkey << 4;
 
@@ -2977,6 +2986,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc, struct 
ieee80211vap *vap)
            le16toh(assoc->intval)));
        error = iwi_cmd(sc, IWI_CMD_ASSOCIATE, assoc, sizeof *assoc);
 done:
+       ieee80211_free_node(ni);
        if (error)
                IWI_STATE_END(sc, IWI_FW_ASSOCIATING);
 
@@ -3079,7 +3089,6 @@ error:
 static void
 iwi_init_locked(struct iwi_softc *sc)
 {
-       struct ifnet *ifp = sc->sc_ifp;
        struct iwi_rx_data *data;
        int i;
 
@@ -3153,8 +3162,7 @@ iwi_init_locked(struct iwi_softc *sc)
        }
 
        callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
-       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-       ifp->if_drv_flags |= IFF_DRV_RUNNING;
+       sc->sc_running = 1;
        return;
 fail:
        IWI_STATE_END(sc, IWI_FW_LOADING);
@@ -3166,15 +3174,14 @@ static void
 iwi_init(void *priv)
 {
        struct iwi_softc *sc = priv;
-       struct ifnet *ifp = sc->sc_ifp;
-       struct ieee80211com *ic = ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
        IWI_LOCK_DECL;
 
        IWI_LOCK(sc);
        iwi_init_locked(sc);
        IWI_UNLOCK(sc);
 
-       if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+       if (sc->sc_running)
                ieee80211_start_all(ic);
 }
 
@@ -3182,11 +3189,10 @@ static void
 iwi_stop_locked(void *priv)
 {
        struct iwi_softc *sc = priv;
-       struct ifnet *ifp = sc->sc_ifp;
 
        IWI_LOCK_ASSERT(sc);
 
-       ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+       sc->sc_running = 0;
 
        if (sc->sc_softled) {
                callout_stop(&sc->sc_ledtimer);
@@ -3247,7 +3253,7 @@ static void
 iwi_radio_on(void *arg, int pending)
 {
        struct iwi_softc *sc = arg;
-       struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
 
        device_printf(sc->sc_dev, "radio turned on\n");
 
@@ -3268,10 +3274,7 @@ iwi_rfkill_poll(void *arg)
         * it is enabled so we must poll for the latter.
         */
        if (!iwi_getrfkill(sc)) {
-               struct ifnet *ifp = sc->sc_ifp;
-               struct ieee80211com *ic = ifp->if_l2com;
-
-               ieee80211_runtask(ic, &sc->sc_radiontask);
+               ieee80211_runtask(&sc->sc_ic, &sc->sc_radiontask);
                return;
        }
        callout_reset(&sc->sc_rftimer, 2*hz, iwi_rfkill_poll, sc);
@@ -3281,7 +3284,7 @@ static void
 iwi_radio_off(void *arg, int pending)
 {
        struct iwi_softc *sc = arg;
-       struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+       struct ieee80211com *ic = &sc->sc_ic;
        IWI_LOCK_DECL;
 
        device_printf(sc->sc_dev, "radio turned off\n");
@@ -3418,7 +3421,6 @@ iwi_led_blink(struct iwi_softc *sc, int on, int off)
 static void
 iwi_led_event(struct iwi_softc *sc, int event)
 {
-#define        N(a)    (sizeof(a)/sizeof(a[0]))
        /* NB: on/off times from the Atheros NDIS driver, w/ permission */
        static const struct {
                u_int           rate;           /* tx/rx iwi rate */
@@ -3448,13 +3450,13 @@ iwi_led_event(struct iwi_softc *sc, int event)
                return;
        switch (event) {
        case IWI_LED_POLL:
-               j = N(blinkrates)-1;
+               j = nitems(blinkrates)-1;
                break;
        case IWI_LED_TX:
                /* read current transmission rate from adapter */
                txrate = CSR_READ_4(sc, IWI_CSR_CURRENT_TX_RATE);
                if (blinkrates[sc->sc_txrix].rate != txrate) {
-                       for (j = 0; j < N(blinkrates)-1; j++)
+                       for (j = 0; j < nitems(blinkrates)-1; j++)
                                if (blinkrates[j].rate == txrate)
                                        break;
                        sc->sc_txrix = j;
@@ -3463,7 +3465,7 @@ iwi_led_event(struct iwi_softc *sc, int event)
                break;
        case IWI_LED_RX:
                if (blinkrates[sc->sc_rxrix].rate != sc->sc_rxrate) {
-                       for (j = 0; j < N(blinkrates)-1; j++)
+                       for (j = 0; j < nitems(blinkrates)-1; j++)
                                if (blinkrates[j].rate == sc->sc_rxrate)
                                        break;
                        sc->sc_rxrix = j;
@@ -3474,7 +3476,6 @@ iwi_led_event(struct iwi_softc *sc, int event)
        /* XXX beware of overflow */
        iwi_led_blink(sc, (blinkrates[j].timeOn * hz) / 1000,
                (blinkrates[j].timeOff * hz) / 1000);
-#undef N
 }
 
 static int
@@ -3545,8 +3546,8 @@ iwi_scan_start(struct ieee80211com *ic)
 static void
 iwi_set_channel(struct ieee80211com *ic)
 {
-       struct ifnet *ifp = ic->ic_ifp;
-       struct iwi_softc *sc = ifp->if_softc;
+       struct iwi_softc *sc = ic->ic_softc;
+
        if (sc->fw_state == IWI_FW_IDLE)
                iwi_setcurchan(sc, ic->ic_curchan->ic_ieee);
 }
@@ -3555,8 +3556,7 @@ static void
 iwi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
 {
        struct ieee80211vap *vap = ss->ss_vap;
-       struct ifnet *ifp = vap->iv_ic->ic_ifp;
-       struct iwi_softc *sc = ifp->if_softc;
+       struct iwi_softc *sc = vap->iv_ic->ic_softc;
        IWI_LOCK_DECL;
 
        IWI_LOCK(sc);
@@ -3574,8 +3574,7 @@ iwi_scan_mindwell(struct ieee80211_scan_state *ss)
 static void
 iwi_scan_end(struct ieee80211com *ic)
 {
-       struct ifnet *ifp = ic->ic_ifp;
-       struct iwi_softc *sc = ifp->if_softc;
+       struct iwi_softc *sc = ic->ic_softc;
        IWI_LOCK_DECL;
 
        IWI_LOCK(sc);
@@ -3585,3 +3584,40 @@ iwi_scan_end(struct ieee80211com *ic)
                iwi_cmd(sc, IWI_CMD_ABORT_SCAN, NULL, 0);
        IWI_UNLOCK(sc);
 }
+
+static void
+iwi_collect_bands(struct ieee80211com *ic, uint8_t bands[], size_t bands_sz)
+{
+       struct iwi_softc *sc = ic->ic_softc;
+       device_t dev = sc->sc_dev;
+
+       memset(bands, 0, bands_sz);
+       setbit(bands, IEEE80211_MODE_11B);
+       setbit(bands, IEEE80211_MODE_11G);
+       if (pci_get_device(dev) >= 0x4223)
+               setbit(bands, IEEE80211_MODE_11A);
+}
+
+static void
+iwi_getradiocaps(struct ieee80211com *ic,
+    int maxchans, int *nchans, struct ieee80211_channel chans[])
+{
+       uint8_t bands[IEEE80211_MODE_BYTES];
+
+       iwi_collect_bands(ic, bands, sizeof(bands));
+       *nchans = 0;
+       if (isset(bands, IEEE80211_MODE_11B) || isset(bands, 
IEEE80211_MODE_11G))
+               ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
+                   def_chan_2ghz, nitems(def_chan_2ghz), bands, 0);
+       if (isset(bands, IEEE80211_MODE_11A)) {
+               ieee80211_add_channel_list_5ghz(chans, maxchans, nchans,
+                   def_chan_5ghz_band1, nitems(def_chan_5ghz_band1),
+                   bands, 0);
+               ieee80211_add_channel_list_5ghz(chans, maxchans, nchans,
+                   def_chan_5ghz_band2, nitems(def_chan_5ghz_band2),
+                   bands, 0);
+               ieee80211_add_channel_list_5ghz(chans, maxchans, nchans,
+                   def_chan_5ghz_band3, nitems(def_chan_5ghz_band3),
+                   bands, 0);
+       }
+}
diff --git 
a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi_ioctl.h 
b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi_ioctl.h
new file mode 100644
index 0000000000..565e135626
--- /dev/null
+++ 
b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi_ioctl.h
@@ -0,0 +1,25 @@
+/*-
+ * Copyright (c) 2014 Adrian Chadd <adrian@xxxxxxxxxxx>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: releng/11.2/sys/dev/iwi/if_iwi_ioctl.h 263920 2014-03-29 
19:53:04Z adrian $
+ */
+#ifndef        __IF_IWI_IOCTL_H__
+#define        __IF_IWI_IOCTL_H__
+
+/* XXX how should I pick appropriate ioctl numbers? */
+#define        SIOCGIWISTATS           _IOWR('i', 147, struct ifreq)
+#define        SIOCZIWISTATS           _IOWR('i', 148, struct ifreq)
+
+#endif /* __IF_IWI_IOCTL_H__ */
diff --git 
a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwireg.h 
b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwireg.h
index fb56fa59bb..06c4eadf65 100644
--- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwireg.h
+++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwireg.h
@@ -1,4 +1,4 @@
-/*     $FreeBSD$       */
+/*     $FreeBSD: releng/11.2/sys/dev/iwi/if_iwireg.h 331722 2018-03-29 
02:50:57Z eadler $      */
 
 /*-
  * Copyright (c) 2004, 2005
@@ -221,6 +221,7 @@ struct iwi_notif_association {
 /* structure for notification IWI_NOTIF_TYPE_SCAN_CHANNEL */
 struct iwi_notif_scan_channel {
        uint8_t nchan;
+       /* XXX this is iwi_cmd_stats, and a u8 reserved field */
        uint8_t reserved[47];
 } __packed;
 
@@ -239,6 +240,68 @@ struct iwi_notif_beacon_state {
        uint32_t number;
 } __packed;
 
+/* structure(s) for notification IWI_NOTIF_TYPE_LINK_QUALITY */
+
+#define RX_FREE_BUFFERS 32
+#define RX_LOW_WATERMARK 8
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
+
+// Used for passing to driver number of successes and failures per rate
+struct iwi_rate_histogram {
+        union {
+                uint32_t a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+                uint32_t b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+                uint32_t g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+        } success;
+        union {
+                uint32_t a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+                uint32_t b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+                uint32_t g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+        } failed;
+} __packed;
+
+/* statistics command response */
+struct iwi_cmd_stats {
+       uint8_t cmd_id;
+       uint8_t seq_num;
+       uint16_t good_sfd;
+       uint16_t bad_plcp;
+       uint16_t wrong_bssid;
+       uint16_t valid_mpdu;
+       uint16_t bad_mac_header;
+       uint16_t reserved_frame_types;
+       uint16_t rx_ina;
+       uint16_t bad_crc32;
+       uint16_t invalid_cts;
+       uint16_t invalid_acks;
+       uint16_t long_distance_ina_fina;
+       uint16_t dsp_silence_unreachable;
+       uint16_t accumulated_rssi;
+       uint16_t rx_ovfl_frame_tossed;
+       uint16_t rssi_silence_threshold;
+       uint16_t rx_ovfl_frame_supplied;
+       uint16_t last_rx_frame_signal;
+       uint16_t last_rx_frame_noise;
+       uint16_t rx_autodetec_no_ofdm;
+       uint16_t rx_autodetec_no_barker;
+       uint16_t reserved;
+} __packed;
+
+#define        SILENCE_OVER_THRESH             (1)
+#define        SILENCE_UNDER_THRESH            (2)
+
+struct iwi_notif_link_quality {
+       struct iwi_cmd_stats stats;
+       uint8_t rate;
+       uint8_t modulation;
+       struct iwi_rate_histogram histogram;
+       uint8_t silence_notification_type;   /* SILENCE_OVER/UNDER_THRESH */
+       uint16_t silence_count;
+} __packed;
+
 /* received frame header */
 struct iwi_frame {
        uint32_t        reserved1[2];
@@ -418,7 +481,7 @@ struct iwi_scan {
 #define IWI_SCAN_TYPES                 5
 
 /* scan result codes */
-#define IWI_SCAN_COMPLETED             1 /* scan compeleted sucessfully */
+#define        IWI_SCAN_COMPLETED              1 /* scan compeleted 
successfully */
 #define IWI_SCAN_ABORTED               2 /* scan was aborted by the driver */
 
 /* structure for command IWI_CMD_SCAN_EXT */
diff --git 
a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h 
b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h
index c733c0f9d8..98c88d027b 100644
--- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h
+++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h
@@ -1,4 +1,4 @@
-/*     $FreeBSD$       */
+/*     $FreeBSD: releng/11.2/sys/dev/iwi/if_iwivar.h 331722 2018-03-29 
02:50:57Z eadler $      */
 
 /*-
  * Copyright (c) 2004, 2005
@@ -125,11 +125,13 @@ struct iwi_vap {
 #define        IWI_VAP(vap)    ((struct iwi_vap *)(vap))
 
 struct iwi_softc {
-       struct ifnet            *sc_ifp;
-       void                    (*sc_node_free)(struct ieee80211_node *);
+       struct mtx              sc_mtx;
+       struct ieee80211com     sc_ic;
+       struct mbufq            sc_snd;
        device_t                sc_dev;
 
-       struct mtx              sc_mtx;
+       void                    (*sc_node_free)(struct ieee80211_node *);
+
        uint8_t                 sc_mcast[IEEE80211_ADDR_LEN];
        struct unrhdr           *sc_unr;
 
@@ -190,10 +192,10 @@ struct iwi_softc {
        struct task             sc_radiofftask; /* radio off processing */
        struct task             sc_restarttask; /* restart adapter processing */
        struct task             sc_disassoctask;
-       struct task             sc_wmetask;     /* set wme parameters */
        struct task             sc_monitortask;
 
-       unsigned int            sc_softled : 1, /* enable LED gpio status */
+       unsigned int            sc_running : 1, /* initialized */
+                               sc_softled : 1, /* enable LED gpio status */
                                sc_ledstate: 1, /* LED on/off state */
                                sc_blinking: 1; /* LED blink operation active */
        u_int                   sc_nictype;     /* NIC type from EEPROM */
@@ -216,6 +218,9 @@ struct iwi_softc {
        struct iwi_rx_radiotap_header sc_rxtap;
        struct iwi_tx_radiotap_header sc_txtap;
 
+       struct iwi_notif_link_quality sc_linkqual;
+       int                     sc_linkqual_valid;
+
 #if defined(__HAIKU__)
        uint32_t sc_intr_status;
 #endif

############################################################################

Commit:      77cf4765673fed9b70de03f11a2c93e8e856061a
URL:         https://git.haiku-os.org/haiku/commit/?id=77cf4765673f
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Tue Jul 10 22:33:19 2018 UTC

Ticket:      https://dev.haiku-os.org/ticket/14260

iprowifi3945: Disable hardware AES.

Recommended by the FreeBSD developers as "possibly broken." Hopefully
helps with #14260.

----------------------------------------------------------------------------

diff --git 
a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpi.c 
b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpi.c
index 826ba36158..525b2e88b2 100644
--- a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpi.c
+++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpi.c
@@ -468,8 +468,10 @@ wpi_attach(device_t dev)
                | IEEE80211_C_PMGT              /* Station-side power mgmt */
                ;
 
+#ifndef __HAIKU__
        ic->ic_cryptocaps =
                  IEEE80211_CRYPTO_AES_CCM;
+#endif
 
        /*
         * Read in the eeprom and also setup the channels for

############################################################################

Commit:      1a353444277f2bcc9ff4cbe5c8fa577ed0f9fb6e
URL:         https://git.haiku-os.org/haiku/commit/?id=1a353444277f
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Tue Jul 10 22:40:21 2018 UTC

Ticket:      https://dev.haiku-os.org/ticket/8634

freebsd11_network: Only start_wlan if FBSD_WLAN_FEATURE is required.

Fixes #8634.

----------------------------------------------------------------------------

diff --git a/src/libs/compat/freebsd11_network/compat.c 
b/src/libs/compat/freebsd11_network/compat.c
index d717e59290..de3a9e9f4a 100644
--- a/src/libs/compat/freebsd11_network/compat.c
+++ b/src/libs/compat/freebsd11_network/compat.c
@@ -453,7 +453,7 @@ device_attach(device_t device)
        if (result == 0)
                atomic_or(&device->flags, DEVICE_ATTACHED);
 
-       if (result == 0)
+       if (result == 0 && HAIKU_DRIVER_REQUIRES(FBSD_WLAN_FEATURE))
                result = start_wlan(device);
 
        return result;
@@ -467,8 +467,10 @@ device_detach(device_t device)
                return B_ERROR;
 
        if ((atomic_and(&device->flags, ~DEVICE_ATTACHED) & DEVICE_ATTACHED) != 0
-               && device->methods.detach != NULL) {
-               int result = stop_wlan(device);
+                       && device->methods.detach != NULL) {
+               int result = 0;
+               if (HAIKU_DRIVER_REQUIRES(FBSD_WLAN_FEATURE))
+                       result = stop_wlan(device);
                if (result != 0) {
                        atomic_or(&device->flags, DEVICE_ATTACHED);
                        return result;

############################################################################

Revision:    hrev52091
Commit:      ecdc1bc8e7aa72886927a76915615698a44dee4a
URL:         https://git.haiku-os.org/haiku/commit/?id=ecdc1bc8e7aa
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Tue Jul 10 22:41:05 2018 UTC

freebsd11_wlan: Add missing mtx_destroy of the ic_list_mtx.

----------------------------------------------------------------------------

diff --git a/src/libs/compat/freebsd11_wlan/net80211/ieee80211_haiku.cpp 
b/src/libs/compat/freebsd11_wlan/net80211/ieee80211_haiku.cpp
index 5b317e3521..ec6b42c4e9 100644
--- a/src/libs/compat/freebsd11_wlan/net80211/ieee80211_haiku.cpp
+++ b/src/libs/compat/freebsd11_wlan/net80211/ieee80211_haiku.cpp
@@ -112,6 +112,8 @@ init_wlan_stack(void)
 void
 uninit_wlan_stack(void)
 {
+       mtx_destroy(&ic_list_mtx);
+
        if (sNotificationModule != NULL)
                put_module(NET_NOTIFICATIONS_MODULE_NAME);
 }


Other related posts: