The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linuxkpi/common/src/linux_80211.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2020-2022 The FreeBSD Foundation
    3  * Copyright (c) 2020-2022 Bjoern A. Zeeb
    4  *
    5  * This software was developed by Björn Zeeb under sponsorship from
    6  * the FreeBSD Foundation.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * Public functions are called linuxkpi_*().
   32  * Internal (static) functions are called lkpi_*().
   33  *
   34  * The internal structures holding metadata over public structures are also
   35  * called lkpi_xxx (usually with a member at the end called xxx).
   36  * Note: we do not replicate the structure names but the general variable names
   37  * for these (e.g., struct hw -> struct lkpi_hw, struct sta -> struct lkpi_sta).
   38  * There are macros to access one from the other.
   39  * We call the internal versions lxxx (e.g., hw -> lhw, sta -> lsta).
   40  */
   41 
   42 #include <sys/cdefs.h>
   43 __FBSDID("$FreeBSD$");
   44 
   45 #include <sys/param.h>
   46 #include <sys/types.h>
   47 #include <sys/kernel.h>
   48 #include <sys/errno.h>
   49 #include <sys/malloc.h>
   50 #include <sys/module.h>
   51 #include <sys/mutex.h>
   52 #include <sys/socket.h>
   53 #include <sys/sysctl.h>
   54 #include <sys/queue.h>
   55 #include <sys/taskqueue.h>
   56 #include <sys/libkern.h>
   57 
   58 #include <net/if.h>
   59 #include <net/if_var.h>
   60 #include <net/if_media.h>
   61 #include <net/ethernet.h>
   62 
   63 #include <net80211/ieee80211_var.h>
   64 #include <net80211/ieee80211_proto.h>
   65 #include <net80211/ieee80211_ratectl.h>
   66 #include <net80211/ieee80211_radiotap.h>
   67 
   68 #define LINUXKPI_NET80211
   69 #include <net/mac80211.h>
   70 
   71 #include <linux/workqueue.h>
   72 #include "linux_80211.h"
   73 
   74 #define LKPI_80211_WME
   75 /* #define      LKPI_80211_HW_CRYPTO */
   76 
   77 static MALLOC_DEFINE(M_LKPI80211, "lkpi80211", "LinuxKPI 80211 compat");
   78 
   79 /* -------------------------------------------------------------------------- */
   80 
   81 /* Keep public for as long as header files are using it too. */
   82 int linuxkpi_debug_80211;
   83 
   84 #ifdef LINUXKPI_DEBUG_80211
   85 SYSCTL_DECL(_compat_linuxkpi);
   86 SYSCTL_NODE(_compat_linuxkpi, OID_AUTO, 80211, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
   87     "LinuxKPI 802.11 compatibility layer");
   88 
   89 SYSCTL_INT(_compat_linuxkpi_80211, OID_AUTO, debug, CTLFLAG_RWTUN,
   90     &linuxkpi_debug_80211, 0, "LinuxKPI 802.11 debug level");
   91 
   92 #define UNIMPLEMENTED           if (linuxkpi_debug_80211 & D80211_TODO)         \
   93     printf("XXX-TODO %s:%d: UNIMPLEMENTED\n", __func__, __LINE__)
   94 #define TRACEOK()               if (linuxkpi_debug_80211 & D80211_TRACEOK)      \
   95     printf("XXX-TODO %s:%d: TRACEPOINT\n", __func__, __LINE__)
   96 #else
   97 #define UNIMPLEMENTED           do { } while (0)
   98 #define TRACEOK()               do { } while (0)
   99 #endif
  100 
  101 /* #define      PREP_TX_INFO_DURATION   (IEEE80211_TRANS_WAIT * 1000) */
  102 #ifndef PREP_TX_INFO_DURATION
  103 #define PREP_TX_INFO_DURATION   0 /* Let the driver do its thing. */
  104 #endif
  105 
  106 /* c.f. ieee80211_ioctl.c */
  107 static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
  108 
  109 /* This is DSAP | SSAP | CTRL | ProtoID/OrgCode{3}. */
  110 const uint8_t rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
  111 
  112 /* IEEE 802.11-05/0257r1 */
  113 const uint8_t bridge_tunnel_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
  114 
  115 const uint8_t tid_to_mac80211_ac[] = {
  116         IEEE80211_AC_BE,
  117         IEEE80211_AC_BK,
  118         IEEE80211_AC_BK,
  119         IEEE80211_AC_BE,
  120         IEEE80211_AC_VI,
  121         IEEE80211_AC_VI,
  122         IEEE80211_AC_VO,
  123         IEEE80211_AC_VO,
  124 #if 0
  125         IEEE80211_AC_VO, /* We treat MGMT as TID 8, which is set as AC_VO */
  126 #endif
  127 };
  128 
  129 const struct cfg80211_ops linuxkpi_mac80211cfgops = {
  130         /*
  131          * XXX TODO need a "glue layer" to link cfg80211 ops to
  132          * mac80211 and to the driver or net80211.
  133          * Can we pass some on 1:1? Need to compare the (*f)().
  134          */
  135 };
  136 
  137 static struct lkpi_sta *lkpi_find_lsta_by_ni(struct lkpi_vif *,
  138     struct ieee80211_node *);
  139 static void lkpi_80211_txq_task(void *, int);
  140 static void lkpi_ieee80211_free_skb_mbuf(void *);
  141 #ifdef LKPI_80211_WME
  142 static int lkpi_wme_update(struct lkpi_hw *, struct ieee80211vap *, bool);
  143 #endif
  144 
  145 static void
  146 lkpi_lsta_dump(struct lkpi_sta *lsta, struct ieee80211_node *ni,
  147     const char *_f, int _l)
  148 {
  149 
  150 #ifdef LINUXKPI_DEBUG_80211
  151         if ((linuxkpi_debug_80211 & D80211_TRACE_STA) == 0)
  152                 return;
  153         if (lsta == NULL)
  154                 return;
  155 
  156         printf("%s:%d lsta %p ni %p sta %p\n",
  157             _f, _l, lsta, ni, &lsta->sta);
  158         if (ni != NULL)
  159                 ieee80211_dump_node(NULL, ni);
  160         printf("\ttxq_task txq len %d mtx\n", mbufq_len(&lsta->txq));
  161         printf("\tkc %p state %d added_to_drv %d in_mgd %d\n",
  162                 lsta->kc, lsta->state, lsta->added_to_drv, lsta->in_mgd);
  163 #endif
  164 }
  165 
  166 static void
  167 lkpi_lsta_remove(struct lkpi_sta *lsta, struct lkpi_vif *lvif)
  168 {
  169         struct ieee80211_node *ni;
  170 
  171         ni = lsta->ni;
  172 
  173         LKPI_80211_LVIF_LOCK(lvif);
  174         TAILQ_REMOVE(&lvif->lsta_head, lsta, lsta_entry);
  175         LKPI_80211_LVIF_UNLOCK(lvif);
  176 
  177         lsta->ni = NULL;
  178         ni->ni_drv_data = NULL;
  179         if (ni != NULL)
  180                 ieee80211_free_node(ni);
  181 
  182         IMPROVE("more from lkpi_ic_node_free() should happen here.");
  183 
  184         free(lsta, M_LKPI80211);
  185 }
  186 
  187 static struct lkpi_sta *
  188 lkpi_lsta_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
  189     struct ieee80211_hw *hw, struct ieee80211_node *ni)
  190 {
  191         struct lkpi_sta *lsta;
  192         struct lkpi_vif *lvif;
  193         struct ieee80211_vif *vif;
  194         struct ieee80211_sta *sta;
  195         int band, i, tid;
  196 
  197         lsta = malloc(sizeof(*lsta) + hw->sta_data_size, M_LKPI80211,
  198             M_NOWAIT | M_ZERO);
  199         if (lsta == NULL)
  200                 return (NULL);
  201 
  202         lsta->added_to_drv = false;
  203         lsta->state = IEEE80211_STA_NOTEXIST;
  204 #if 0
  205         /*
  206          * This needs to be done in node_init() as ieee80211_alloc_node()
  207          * will initialise the refcount after us.
  208          */
  209         lsta->ni = ieee80211_ref_node(ni);
  210 #endif
  211         /* The back-pointer "drv_data" to net80211_node let's us get lsta. */
  212         ni->ni_drv_data = lsta;
  213 
  214         lvif = VAP_TO_LVIF(vap);
  215         vif = LVIF_TO_VIF(lvif);
  216         sta = LSTA_TO_STA(lsta);
  217 
  218         IEEE80211_ADDR_COPY(sta->addr, mac);
  219 
  220         /* TXQ */
  221         for (tid = 0; tid < nitems(sta->txq); tid++) {
  222                 struct lkpi_txq *ltxq;
  223 
  224                 /* We are not limiting ourselves to hw.queues here. */
  225                 ltxq = malloc(sizeof(*ltxq) + hw->txq_data_size,
  226                     M_LKPI80211, M_NOWAIT | M_ZERO);
  227                 if (ltxq == NULL)
  228                         goto cleanup;
  229                 /* iwlwifi//mvm/sta.c::tid_to_mac80211_ac[] */
  230                 if (tid == IEEE80211_NUM_TIDS) {
  231                         if (!ieee80211_hw_check(hw, STA_MMPDU_TXQ)) {
  232                                 free(ltxq, M_LKPI80211);
  233                                 continue;
  234                         }
  235                         IMPROVE("AP/if we support non-STA here too");
  236                         ltxq->txq.ac = IEEE80211_AC_VO;
  237                 } else {
  238                         ltxq->txq.ac = tid_to_mac80211_ac[tid & 7];
  239                 }
  240                 ltxq->seen_dequeue = false;
  241                 ltxq->txq.vif = vif;
  242                 ltxq->txq.tid = tid;
  243                 ltxq->txq.sta = sta;
  244                 skb_queue_head_init(&ltxq->skbq);
  245                 sta->txq[tid] = &ltxq->txq;
  246         }
  247 
  248         /* Deflink information. */
  249         for (band = 0; band < NUM_NL80211_BANDS; band++) {
  250                 struct ieee80211_supported_band *supband;
  251 
  252                 supband = hw->wiphy->bands[band];
  253                 if (supband == NULL)
  254                         continue;
  255 
  256                 for (i = 0; i < supband->n_bitrates; i++) {
  257 
  258                         IMPROVE("Further supband->bitrates[i]* checks?");
  259                         /* or should we get them from the ni? */
  260                         sta->deflink.supp_rates[band] |= BIT(i);
  261                 }
  262         }
  263         IMPROVE("ht, vht, he, ... bandwidth, smps_mode, ..");
  264         /* bandwidth = IEEE80211_STA_RX_... */
  265 
  266         /* Deferred TX path. */
  267         mtx_init(&lsta->txq_mtx, "lsta_txq", NULL, MTX_DEF);
  268         TASK_INIT(&lsta->txq_task, 0, lkpi_80211_txq_task, lsta);
  269         mbufq_init(&lsta->txq, IFQ_MAXLEN);
  270 
  271         return (lsta);
  272 
  273 cleanup:
  274         for (; tid >= 0; tid--)
  275                 free(sta->txq[tid], M_LKPI80211);
  276         free(lsta, M_LKPI80211);
  277         return (NULL);
  278 }
  279 
  280 static enum nl80211_band
  281 lkpi_net80211_chan_to_nl80211_band(struct ieee80211_channel *c)
  282 {
  283 
  284         if (IEEE80211_IS_CHAN_2GHZ(c))
  285                 return (NL80211_BAND_2GHZ);
  286         else if (IEEE80211_IS_CHAN_5GHZ(c))
  287                 return (NL80211_BAND_5GHZ);
  288 #ifdef __notyet__
  289         else if ()
  290                 return (NL80211_BAND_6GHZ);
  291         else if ()
  292                 return (NL80211_BAND_60GHZ);
  293         else if (IEEE80211_IS_CHAN_GSM(c))
  294                 return (NL80211_BAND_XXX);
  295 #endif
  296         else
  297                 panic("%s: unsupported band. c %p flags %#x\n",
  298                     __func__, c, c->ic_flags);
  299 }
  300 
  301 static uint32_t
  302 lkpi_nl80211_band_to_net80211_band(enum nl80211_band band)
  303 {
  304 
  305         /* XXX-BZ this is just silly; net80211 is too convoluted. */
  306         /* IEEE80211_CHAN_A / _G / .. doesn't really work either. */
  307         switch (band) {
  308         case NL80211_BAND_2GHZ:
  309                 return (IEEE80211_CHAN_2GHZ);
  310                 break;
  311         case NL80211_BAND_5GHZ:
  312                 return (IEEE80211_CHAN_5GHZ);
  313                 break;
  314         case NL80211_BAND_60GHZ:
  315                 break;
  316         case NL80211_BAND_6GHZ:
  317                 break;
  318         default:
  319                 panic("%s: unsupported band %u\n", __func__, band);
  320                 break;
  321         }
  322 
  323         IMPROVE();
  324         return (0x00);
  325 }
  326 
  327 #if 0
  328 static enum ieee80211_ac_numbers
  329 lkpi_ac_net_to_l80211(int ac)
  330 {
  331 
  332         switch (ac) {
  333         case WME_AC_VO:
  334                 return (IEEE80211_AC_VO);
  335         case WME_AC_VI:
  336                 return (IEEE80211_AC_VI);
  337         case WME_AC_BE:
  338                 return (IEEE80211_AC_BE);
  339         case WME_AC_BK:
  340                 return (IEEE80211_AC_BK);
  341         default:
  342                 printf("%s: invalid WME_AC_* input: ac = %d\n", __func__, ac);
  343                 return (IEEE80211_AC_BE);
  344         }
  345 }
  346 #endif
  347 
  348 static enum nl80211_iftype
  349 lkpi_opmode_to_vif_type(enum ieee80211_opmode opmode)
  350 {
  351 
  352         switch (opmode) {
  353         case IEEE80211_M_IBSS:
  354                 return (NL80211_IFTYPE_ADHOC);
  355                 break;
  356         case IEEE80211_M_STA:
  357                 return (NL80211_IFTYPE_STATION);
  358                 break;
  359         case IEEE80211_M_WDS:
  360                 return (NL80211_IFTYPE_WDS);
  361                 break;
  362         case IEEE80211_M_HOSTAP:
  363                 return (NL80211_IFTYPE_AP);
  364                 break;
  365         case IEEE80211_M_MONITOR:
  366                 return (NL80211_IFTYPE_MONITOR);
  367                 break;
  368         case IEEE80211_M_MBSS:
  369                 return (NL80211_IFTYPE_MESH_POINT);
  370                 break;
  371         case IEEE80211_M_AHDEMO:
  372                 /* FALLTHROUGH */
  373         default:
  374                 printf("ERROR: %s: unsupported opmode %d\n", __func__, opmode);
  375                 /* FALLTHROUGH */
  376         }
  377         return (NL80211_IFTYPE_UNSPECIFIED);
  378 }
  379 
  380 #ifdef LKPI_80211_HW_CRYPTO
  381 static uint32_t
  382 lkpi_l80211_to_net80211_cyphers(uint32_t wlan_cipher_suite)
  383 {
  384 
  385         switch (wlan_cipher_suite) {
  386         case WLAN_CIPHER_SUITE_WEP40:
  387                 return (IEEE80211_CRYPTO_WEP);
  388         case WLAN_CIPHER_SUITE_TKIP:
  389                 return (IEEE80211_CRYPTO_TKIP);
  390         case WLAN_CIPHER_SUITE_CCMP:
  391                 return (IEEE80211_CIPHER_AES_CCM);
  392         case WLAN_CIPHER_SUITE_WEP104:
  393                 return (IEEE80211_CRYPTO_WEP);
  394         case WLAN_CIPHER_SUITE_AES_CMAC:
  395         case WLAN_CIPHER_SUITE_GCMP:
  396         case WLAN_CIPHER_SUITE_GCMP_256:
  397         case WLAN_CIPHER_SUITE_CCMP_256:
  398         case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  399         case WLAN_CIPHER_SUITE_BIP_GMAC_256:
  400         case WLAN_CIPHER_SUITE_BIP_CMAC_256:
  401                 printf("%s: unsupported WLAN Cipher Suite %#08x | %u\n", __func__,
  402                     wlan_cipher_suite >> 8, wlan_cipher_suite & 0xff);
  403                 break;
  404         default:
  405                 printf("%s: unknown WLAN Cipher Suite %#08x | %u\n", __func__,
  406                     wlan_cipher_suite >> 8, wlan_cipher_suite & 0xff);
  407         }
  408 
  409         return (0);
  410 }
  411 
  412 static uint32_t
  413 lkpi_net80211_to_l80211_cipher_suite(uint32_t cipher, uint8_t keylen)
  414 {
  415 
  416         switch (cipher) {
  417         case IEEE80211_CIPHER_TKIP:
  418                 return (WLAN_CIPHER_SUITE_TKIP);
  419         case IEEE80211_CIPHER_AES_CCM:
  420                 return (WLAN_CIPHER_SUITE_CCMP);
  421         case IEEE80211_CIPHER_WEP:
  422                 if (keylen < 8)
  423                         return (WLAN_CIPHER_SUITE_WEP40);
  424                 else
  425                         return (WLAN_CIPHER_SUITE_WEP104);
  426                 break;
  427         case IEEE80211_CIPHER_AES_OCB:
  428         case IEEE80211_CIPHER_TKIPMIC:
  429         case IEEE80211_CIPHER_CKIP:
  430         case IEEE80211_CIPHER_NONE:
  431                 printf("%s: unsupported cipher %#010x\n", __func__, cipher);
  432                 break;
  433         default:
  434                 printf("%s: unknown cipher %#010x\n", __func__, cipher);
  435         };
  436         return (0);
  437 }
  438 #endif
  439 
  440 #ifdef __notyet__
  441 static enum ieee80211_sta_state
  442 lkpi_net80211_state_to_sta_state(enum ieee80211_state state)
  443 {
  444 
  445         /*
  446          * XXX-BZ The net80211 states are "try to ..", the lkpi8011 states are
  447          * "done".  Also ASSOC/AUTHORIZED are both "RUN" then?
  448          */
  449         switch (state) {
  450         case IEEE80211_S_INIT:
  451                 return (IEEE80211_STA_NOTEXIST);
  452         case IEEE80211_S_SCAN:
  453                 return (IEEE80211_STA_NONE);
  454         case IEEE80211_S_AUTH:
  455                 return (IEEE80211_STA_AUTH);
  456         case IEEE80211_S_ASSOC:
  457                 return (IEEE80211_STA_ASSOC);
  458         case IEEE80211_S_RUN:
  459                 return (IEEE80211_STA_AUTHORIZED);
  460         case IEEE80211_S_CAC:
  461         case IEEE80211_S_CSA:
  462         case IEEE80211_S_SLEEP:
  463         default:
  464                 UNIMPLEMENTED;
  465         };
  466 
  467         return (IEEE80211_STA_NOTEXIST);
  468 }
  469 #endif
  470 
  471 static struct linuxkpi_ieee80211_channel *
  472 lkpi_find_lkpi80211_chan(struct lkpi_hw *lhw,
  473     struct ieee80211_channel *c)
  474 {
  475         struct ieee80211_hw *hw;
  476         struct linuxkpi_ieee80211_channel *channels;
  477         enum nl80211_band band;
  478         int i, nchans;
  479 
  480         hw = LHW_TO_HW(lhw);
  481         band = lkpi_net80211_chan_to_nl80211_band(c);
  482         if (hw->wiphy->bands[band] == NULL)
  483                 return (NULL);
  484 
  485         nchans = hw->wiphy->bands[band]->n_channels;
  486         if (nchans <= 0)
  487                 return (NULL);
  488 
  489         channels = hw->wiphy->bands[band]->channels;
  490         for (i = 0; i < nchans; i++) {
  491                 if (channels[i].hw_value == c->ic_ieee)
  492                         return (&channels[i]);
  493         }
  494 
  495         return (NULL);
  496 }
  497 
  498 static struct linuxkpi_ieee80211_channel *
  499 lkpi_get_lkpi80211_chan(struct ieee80211com *ic, struct ieee80211_node *ni)
  500 {
  501         struct linuxkpi_ieee80211_channel *chan;
  502         struct ieee80211_channel *c;
  503         struct lkpi_hw *lhw;
  504 
  505         chan = NULL;
  506         if (ni != NULL && ni->ni_chan != IEEE80211_CHAN_ANYC)
  507                 c = ni->ni_chan;
  508         else if (ic->ic_bsschan != IEEE80211_CHAN_ANYC)
  509                 c = ic->ic_bsschan;
  510         else if (ic->ic_curchan != IEEE80211_CHAN_ANYC)
  511                 c = ic->ic_curchan;
  512         else
  513                 c = NULL;
  514 
  515         if (c != NULL && c != IEEE80211_CHAN_ANYC) {
  516                 lhw = ic->ic_softc;
  517                 chan = lkpi_find_lkpi80211_chan(lhw, c);
  518         }
  519 
  520         return (chan);
  521 }
  522 
  523 struct linuxkpi_ieee80211_channel *
  524 linuxkpi_ieee80211_get_channel(struct wiphy *wiphy, uint32_t freq)
  525 {
  526         enum nl80211_band band;
  527 
  528         for (band = 0; band < NUM_NL80211_BANDS; band++) {
  529                 struct ieee80211_supported_band *supband;
  530                 struct linuxkpi_ieee80211_channel *channels;
  531                 int i;
  532 
  533                 supband = wiphy->bands[band];
  534                 if (supband == NULL || supband->n_channels == 0)
  535                         continue;
  536 
  537                 channels = supband->channels;
  538                 for (i = 0; i < supband->n_channels; i++) {
  539                         if (channels[i].center_freq == freq)
  540                                 return (&channels[i]);
  541                 }
  542         }
  543 
  544         return (NULL);
  545 }
  546 
  547 #ifdef LKPI_80211_HW_CRYPTO
  548 static int
  549 _lkpi_iv_key_set_delete(struct ieee80211vap *vap, const struct ieee80211_key *k,
  550     enum set_key_cmd cmd)
  551 {
  552         struct ieee80211com *ic;
  553         struct lkpi_hw *lhw;
  554         struct ieee80211_hw *hw;
  555         struct lkpi_vif *lvif;
  556         struct ieee80211_vif *vif;
  557         struct ieee80211_sta *sta;
  558         struct ieee80211_node *ni;
  559         struct ieee80211_key_conf *kc;
  560         int error;
  561 
  562         /* XXX TODO Check (k->wk_flags & IEEE80211_KEY_SWENCRYPT) and don't upload to driver/hw? */
  563 
  564         ic = vap->iv_ic;
  565         lhw = ic->ic_softc;
  566         hw = LHW_TO_HW(lhw);
  567         lvif = VAP_TO_LVIF(vap);
  568         vif = LVIF_TO_VIF(lvif);
  569 
  570         memset(&kc, 0, sizeof(kc));
  571         kc = malloc(sizeof(*kc) + k->wk_keylen, M_LKPI80211, M_WAITOK | M_ZERO);
  572         kc->cipher = lkpi_net80211_to_l80211_cipher_suite(
  573             k->wk_cipher->ic_cipher, k->wk_keylen);
  574         kc->keyidx = k->wk_keyix;
  575 #if 0
  576         kc->hw_key_idx = /* set by hw and needs to be passed for TX */;
  577 #endif
  578         atomic64_set(&kc->tx_pn, k->wk_keytsc);
  579         kc->keylen = k->wk_keylen;
  580         memcpy(kc->key, k->wk_key, k->wk_keylen);
  581 
  582         switch (kc->cipher) {
  583         case WLAN_CIPHER_SUITE_CCMP:
  584                 kc->iv_len = k->wk_cipher->ic_header;
  585                 kc->icv_len = k->wk_cipher->ic_trailer;
  586                 break;
  587         case WLAN_CIPHER_SUITE_TKIP:
  588         default:
  589                 IMPROVE();
  590                 return (0);
  591         };
  592 
  593         ni = vap->iv_bss;
  594         sta = ieee80211_find_sta(vif, ni->ni_bssid);
  595         if (sta != NULL) {
  596                 struct lkpi_sta *lsta;
  597 
  598                 lsta = STA_TO_LSTA(sta);
  599                 lsta->kc = kc;
  600         }
  601 
  602         error = lkpi_80211_mo_set_key(hw, cmd, vif, sta, kc);
  603         if (error != 0) {
  604                 /* XXX-BZ leaking kc currently */
  605                 ic_printf(ic, "%s: set_key failed: %d\n", __func__, error);
  606                 return (0);
  607         } else {
  608                 ic_printf(ic, "%s: set_key succeeded: keyidx %u hw_key_idx %u "
  609                     "flags %#10x\n", __func__,
  610                     kc->keyidx, kc->hw_key_idx, kc->flags);
  611                 return (1);
  612         }
  613 }
  614 
  615 static int
  616 lkpi_iv_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
  617 {
  618 
  619         /* XXX-BZ one day we should replace this iterating over VIFs, or node list? */
  620         return (_lkpi_iv_key_set_delete(vap, k, DISABLE_KEY));
  621 }
  622 static  int
  623 lkpi_iv_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
  624 {
  625 
  626         return (_lkpi_iv_key_set_delete(vap, k, SET_KEY));
  627 }
  628 #endif
  629 
  630 static u_int
  631 lkpi_ic_update_mcast_copy(void *arg, struct sockaddr_dl *sdl, u_int cnt)
  632 {
  633         struct netdev_hw_addr_list *mc_list;
  634         struct netdev_hw_addr *addr;
  635 
  636         KASSERT(arg != NULL && sdl != NULL, ("%s: arg %p sdl %p cnt %u\n",
  637             __func__, arg, sdl, cnt));
  638 
  639         mc_list = arg;
  640         /* If it is on the list already skip it. */
  641         netdev_hw_addr_list_for_each(addr, mc_list) {
  642                 if (!memcmp(addr->addr, LLADDR(sdl), sdl->sdl_alen))
  643                         return (0);
  644         }
  645 
  646         addr = malloc(sizeof(*addr), M_LKPI80211, M_NOWAIT | M_ZERO);
  647         if (addr == NULL)
  648                 return (0);
  649 
  650         INIT_LIST_HEAD(&addr->addr_list);
  651         memcpy(addr->addr, LLADDR(sdl), sdl->sdl_alen);
  652         /* XXX this should be a netdev function? */
  653         list_add(&addr->addr_list, &mc_list->addr_list);
  654         mc_list->count++;
  655 
  656 #ifdef LINUXKPI_DEBUG_80211
  657         if (linuxkpi_debug_80211 & D80211_TRACE)
  658                 printf("%s:%d: mc_list count %d: added %6D\n",
  659                     __func__, __LINE__, mc_list->count, addr->addr, ":");
  660 #endif
  661 
  662         return (1);
  663 }
  664 
  665 static void
  666 lkpi_update_mcast_filter(struct ieee80211com *ic, bool force)
  667 {
  668         struct lkpi_hw *lhw;
  669         struct ieee80211_hw *hw;
  670         struct netdev_hw_addr_list mc_list;
  671         struct list_head *le, *next;
  672         struct netdev_hw_addr *addr;
  673         struct ieee80211vap *vap;
  674         u64 mc;
  675         unsigned int changed_flags, total_flags;
  676 
  677         lhw = ic->ic_softc;
  678 
  679         if (lhw->ops->prepare_multicast == NULL ||
  680             lhw->ops->configure_filter == NULL)
  681                 return;
  682 
  683         if (!lhw->update_mc && !force)
  684                 return;
  685 
  686         changed_flags = total_flags = 0;
  687         mc_list.count = 0;
  688         INIT_LIST_HEAD(&mc_list.addr_list);
  689         if (ic->ic_allmulti == 0) {
  690                 TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
  691                         if_foreach_llmaddr(vap->iv_ifp,
  692                             lkpi_ic_update_mcast_copy, &mc_list);
  693         } else {
  694                 changed_flags |= FIF_ALLMULTI;
  695         }
  696 
  697         hw = LHW_TO_HW(lhw);
  698         mc = lkpi_80211_mo_prepare_multicast(hw, &mc_list);
  699         /*
  700          * XXX-BZ make sure to get this sorted what is a change,
  701          * what gets all set; what was already set?
  702          */
  703         total_flags = changed_flags;
  704         lkpi_80211_mo_configure_filter(hw, changed_flags, &total_flags, mc);
  705 
  706 #ifdef LINUXKPI_DEBUG_80211
  707         if (linuxkpi_debug_80211 & D80211_TRACE)
  708                 printf("%s: changed_flags %#06x count %d total_flags %#010x\n",
  709                     __func__, changed_flags, mc_list.count, total_flags);
  710 #endif
  711 
  712         if (mc_list.count != 0) {
  713                 list_for_each_safe(le, next, &mc_list.addr_list) {
  714                         addr = list_entry(le, struct netdev_hw_addr, addr_list);
  715                         free(addr, M_LKPI80211);
  716                         mc_list.count--;
  717                 }
  718         }
  719         KASSERT(mc_list.count == 0, ("%s: mc_list %p count %d != 0\n",
  720             __func__, &mc_list, mc_list.count));
  721 }
  722 
  723 static enum ieee80211_bss_changed
  724 lkpi_update_dtim_tsf(struct ieee80211_vif *vif, struct ieee80211_node *ni,
  725     struct ieee80211vap *vap, const char *_f, int _l)
  726 {
  727         enum ieee80211_bss_changed bss_changed;
  728 
  729         bss_changed = 0;
  730 
  731 #ifdef LINUXKPI_DEBUG_80211
  732         if (linuxkpi_debug_80211 & D80211_TRACE)
  733                 printf("%s:%d [%s:%d] assoc %d aid %d beacon_int %u "
  734                     "dtim_period %u sync_dtim_count %u sync_tsf %ju "
  735                     "sync_device_ts %u bss_changed %#08x\n",
  736                         __func__, __LINE__, _f, _l,
  737                         vif->bss_conf.assoc, vif->bss_conf.aid,
  738                         vif->bss_conf.beacon_int, vif->bss_conf.dtim_period,
  739                         vif->bss_conf.sync_dtim_count,
  740                         (uintmax_t)vif->bss_conf.sync_tsf,
  741                         vif->bss_conf.sync_device_ts,
  742                         bss_changed);
  743 #endif
  744 
  745         if (vif->bss_conf.beacon_int != ni->ni_intval) {
  746                 vif->bss_conf.beacon_int = ni->ni_intval;
  747                 /* iwlwifi FW bug workaround; iwl_mvm_mac_sta_state. */
  748                 if (vif->bss_conf.beacon_int < 16)
  749                         vif->bss_conf.beacon_int = 16;
  750                 bss_changed |= BSS_CHANGED_BEACON_INT;
  751         }
  752         if (vif->bss_conf.dtim_period != vap->iv_dtim_period &&
  753             vap->iv_dtim_period > 0) {
  754                 vif->bss_conf.dtim_period = vap->iv_dtim_period;
  755                 bss_changed |= BSS_CHANGED_BEACON_INFO;
  756         }
  757 
  758         vif->bss_conf.sync_dtim_count = vap->iv_dtim_count;
  759         vif->bss_conf.sync_tsf = le64toh(ni->ni_tstamp.tsf);
  760         /* vif->bss_conf.sync_device_ts = set in linuxkpi_ieee80211_rx. */
  761 
  762 #ifdef LINUXKPI_DEBUG_80211
  763         if (linuxkpi_debug_80211 & D80211_TRACE)
  764                 printf("%s:%d [%s:%d] assoc %d aid %d beacon_int %u "
  765                     "dtim_period %u sync_dtim_count %u sync_tsf %ju "
  766                     "sync_device_ts %u bss_changed %#08x\n",
  767                         __func__, __LINE__, _f, _l,
  768                         vif->bss_conf.assoc, vif->bss_conf.aid,
  769                         vif->bss_conf.beacon_int, vif->bss_conf.dtim_period,
  770                         vif->bss_conf.sync_dtim_count,
  771                         (uintmax_t)vif->bss_conf.sync_tsf,
  772                         vif->bss_conf.sync_device_ts,
  773                         bss_changed);
  774 #endif
  775 
  776         return (bss_changed);
  777 }
  778 
  779 static void
  780 lkpi_stop_hw_scan(struct lkpi_hw *lhw, struct ieee80211_vif *vif)
  781 {
  782         struct ieee80211_hw *hw;
  783         int error;
  784 
  785         if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) == 0)
  786                 return;
  787 
  788         hw = LHW_TO_HW(lhw);
  789 
  790         IEEE80211_UNLOCK(lhw->ic);
  791         LKPI_80211_LHW_LOCK(lhw);
  792         /* Need to cancel the scan. */
  793         lkpi_80211_mo_cancel_hw_scan(hw, vif);
  794 
  795         /* Need to make sure we see ieee80211_scan_completed. */
  796         error = msleep(lhw, &lhw->mtx, 0, "lhwscanstop", hz/2);
  797         LKPI_80211_LHW_UNLOCK(lhw);
  798         IEEE80211_LOCK(lhw->ic);
  799 
  800         if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0)
  801                 ic_printf(lhw->ic, "%s: failed to cancel scan: %d (%p, %p)\n",
  802                     __func__, error, lhw, vif);
  803 }
  804 
  805 static void
  806 lkpi_hw_conf_idle(struct ieee80211_hw *hw, bool new)
  807 {
  808         struct lkpi_hw *lhw;
  809         int error;
  810         bool old;
  811 
  812         old = hw->conf.flags & IEEE80211_CONF_IDLE;
  813         if (old == new)
  814                 return;
  815 
  816         hw->conf.flags ^= IEEE80211_CONF_IDLE;
  817         error = lkpi_80211_mo_config(hw, IEEE80211_CONF_CHANGE_IDLE);
  818         if (error != 0 && error != EOPNOTSUPP) {
  819                 lhw = HW_TO_LHW(hw);
  820                 ic_printf(lhw->ic, "ERROR: %s: config %#0x returned %d\n",
  821                     __func__, IEEE80211_CONF_CHANGE_IDLE, error);
  822         }
  823 }
  824 
  825 static void
  826 lkpi_disassoc(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
  827     struct lkpi_hw *lhw)
  828 {
  829         sta->aid = 0;
  830         if (vif->bss_conf.assoc) {
  831                 struct ieee80211_hw *hw;
  832                 enum ieee80211_bss_changed changed;
  833 
  834                 lhw->update_mc = true;
  835                 lkpi_update_mcast_filter(lhw->ic, true);
  836 
  837                 changed = 0;
  838                 vif->bss_conf.assoc = false;
  839                 vif->bss_conf.aid = 0;
  840                 changed |= BSS_CHANGED_ASSOC;
  841                 /*
  842                  * This will remove the sta from firmware for iwlwifi.
  843                  * So confusing that they use state and flags and ... ^%$%#%$^.
  844                  */
  845                 IMPROVE();
  846                 hw = LHW_TO_HW(lhw);
  847                 lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf,
  848                     changed);
  849 
  850                 lkpi_hw_conf_idle(hw, true);
  851         }
  852 }
  853 
  854 static void
  855 lkpi_wake_tx_queues(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
  856     bool dequeue_seen, bool no_emptyq)
  857 {
  858         struct lkpi_txq *ltxq;
  859         int tid;
  860 
  861         /* Wake up all queues to know they are allocated in the driver. */
  862         for (tid = 0; tid < nitems(sta->txq); tid++) {
  863 
  864                         if (tid == IEEE80211_NUM_TIDS) {
  865                                 IMPROVE("station specific?");
  866                                 if (!ieee80211_hw_check(hw, STA_MMPDU_TXQ))
  867                                         continue;
  868                         } else if (tid >= hw->queues)
  869                                 continue;
  870 
  871                         if (sta->txq[tid] == NULL)
  872                                 continue;
  873 
  874                         ltxq = TXQ_TO_LTXQ(sta->txq[tid]);
  875                         if (dequeue_seen && !ltxq->seen_dequeue)
  876                                 continue;
  877 
  878                         if (no_emptyq && skb_queue_empty(&ltxq->skbq))
  879                                 continue;
  880 
  881                         lkpi_80211_mo_wake_tx_queue(hw, sta->txq[tid]);
  882         }
  883 }
  884 
  885 /* -------------------------------------------------------------------------- */
  886 
  887 static int
  888 lkpi_sta_state_do_nada(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
  889 {
  890 
  891         return (0);
  892 }
  893 
  894 /* lkpi_iv_newstate() handles the stop scan case generally. */
  895 #define lkpi_sta_scan_to_init(_v, _n, _a)       lkpi_sta_state_do_nada(_v, _n, _a)
  896 
  897 static int
  898 lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
  899 {
  900         struct linuxkpi_ieee80211_channel *chan;
  901         struct ieee80211_chanctx_conf *conf;
  902         struct lkpi_hw *lhw;
  903         struct ieee80211_hw *hw;
  904         struct lkpi_vif *lvif;
  905         struct ieee80211_vif *vif;
  906         struct ieee80211_node *ni;
  907         struct lkpi_sta *lsta;
  908         enum ieee80211_bss_changed bss_changed;
  909         struct ieee80211_prep_tx_info prep_tx_info;
  910         uint32_t changed;
  911         int error;
  912 
  913         chan = lkpi_get_lkpi80211_chan(vap->iv_ic, vap->iv_bss);
  914         if (chan == NULL) {
  915                 ic_printf(vap->iv_ic, "%s: failed to get channel\n", __func__);
  916                 return (ESRCH);
  917         }
  918 
  919         lhw = vap->iv_ic->ic_softc;
  920         hw = LHW_TO_HW(lhw);
  921         lvif = VAP_TO_LVIF(vap);
  922         vif = LVIF_TO_VIF(lvif);
  923 
  924         ni = ieee80211_ref_node(vap->iv_bss);
  925 
  926         IEEE80211_UNLOCK(vap->iv_ic);
  927 
  928         /* Add chanctx (or if exists, change it). */
  929         if (vif->chanctx_conf != NULL) {
  930                 conf = vif->chanctx_conf;
  931                 IMPROVE("diff changes for changed, working on live copy, rcu");
  932         } else {
  933                 /* Keep separate alloc as in Linux this is rcu managed? */
  934                 conf = malloc(sizeof(*conf) + hw->chanctx_data_size,
  935                     M_LKPI80211, M_WAITOK | M_ZERO);
  936         }
  937 
  938         conf->rx_chains_dynamic = 1;
  939         conf->rx_chains_static = 1;
  940         conf->radar_enabled =
  941             (chan->flags & IEEE80211_CHAN_RADAR) ? true : false;
  942         conf->def.chan = chan;
  943         conf->def.width = NL80211_CHAN_WIDTH_20_NOHT;
  944         conf->def.center_freq1 = chan->center_freq;
  945         conf->def.center_freq2 = 0;
  946         /* Responder ... */
  947         conf->min_def.chan = chan;
  948         conf->min_def.width = NL80211_CHAN_WIDTH_20_NOHT;
  949         conf->min_def.center_freq1 = chan->center_freq;
  950         conf->min_def.center_freq2 = 0;
  951         IMPROVE("currently 20_NOHT only");
  952 
  953         error = 0;
  954         if (vif->chanctx_conf != NULL) {
  955                 changed = IEEE80211_CHANCTX_CHANGE_MIN_WIDTH;
  956                 changed |= IEEE80211_CHANCTX_CHANGE_RADAR;
  957                 changed |= IEEE80211_CHANCTX_CHANGE_RX_CHAINS;
  958                 changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
  959                 lkpi_80211_mo_change_chanctx(hw, conf, changed);
  960         } else {
  961                 error = lkpi_80211_mo_add_chanctx(hw, conf);
  962                 if (error == 0 || error == EOPNOTSUPP) {
  963                         vif->bss_conf.chandef.chan = conf->def.chan;
  964                         vif->bss_conf.chandef.width = conf->def.width;
  965                         vif->bss_conf.chandef.center_freq1 =
  966                             conf->def.center_freq1;
  967                         vif->bss_conf.chandef.center_freq2 =
  968                             conf->def.center_freq2;
  969                 } else {
  970                         goto out;
  971                 }
  972                 /* Assign vif chanctx. */
  973                 if (error == 0)
  974                         error = lkpi_80211_mo_assign_vif_chanctx(hw, vif, conf);
  975                 if (error == EOPNOTSUPP)
  976                         error = 0;
  977                 if (error != 0) {
  978                         lkpi_80211_mo_remove_chanctx(hw, conf);
  979                         free(conf, M_LKPI80211);
  980                         goto out;
  981                 }
  982         }
  983         IMPROVE("update radiotap chan fields too");
  984 
  985         /* Set bss info (bss_info_changed). */
  986         bss_changed = 0;
  987         vif->bss_conf.bssid = ni->ni_bssid;
  988         bss_changed |= BSS_CHANGED_BSSID;
  989         vif->bss_conf.txpower = ni->ni_txpower;
  990         bss_changed |= BSS_CHANGED_TXPOWER;
  991         vif->bss_conf.idle = false;
  992         bss_changed |= BSS_CHANGED_IDLE;
  993 
  994         /* Should almost assert it is this. */
  995         vif->bss_conf.assoc = false;
  996         vif->bss_conf.aid = 0;
  997 
  998         bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__);
  999 
 1000         /* RATES */
 1001         IMPROVE("bss info: not all needs to come now and rates are missing");
 1002         lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
 1003 
 1004         /*
 1005          * This is a bandaid for now.  If we went through (*iv_update_bss)()
 1006          * and then removed the lsta we end up here without a lsta and have
 1007          * to manually allocate and link it in as lkpi_ic_node_alloc()/init()
 1008          * would normally do.
 1009          * XXX-BZ I do not like this but currently we have no good way of
 1010          * intercepting the bss swap and state changes and packets going out
 1011          * workflow so live with this.  It is a compat layer after all.
 1012          */
 1013         if (ni->ni_drv_data == NULL) {
 1014                 lsta = lkpi_lsta_alloc(vap, ni->ni_macaddr, hw, ni);
 1015                 if (lsta == NULL) {
 1016                         error = ENOMEM;
 1017                         goto out;
 1018                 }
 1019                 lsta->ni = ieee80211_ref_node(ni);
 1020         } else {
 1021                 lsta = ni->ni_drv_data;
 1022         }
 1023 
 1024         /* Insert the [l]sta into the list of known stations. */
 1025         LKPI_80211_LVIF_LOCK(lvif);
 1026         TAILQ_INSERT_TAIL(&lvif->lsta_head, lsta, lsta_entry);
 1027         LKPI_80211_LVIF_UNLOCK(lvif);
 1028 
 1029         /* Add (or adjust) sta and change state (from NOTEXIST) to NONE. */
 1030         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1031         KASSERT(lsta->state == IEEE80211_STA_NOTEXIST, ("%s: lsta %p state not "
 1032             "NOTEXIST: %#x\n", __func__, lsta, lsta->state));
 1033         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_NONE);
 1034         if (error != 0) {
 1035                 IMPROVE("do we need to undo the chan ctx?");
 1036                 goto out;
 1037         }
 1038 #if 0
 1039         lsta->added_to_drv = true;      /* mo manages. */
 1040 #endif
 1041 
 1042         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1043 
 1044         /*
 1045          * Wakeup all queues now that sta is there so we have as much time to
 1046          * possibly prepare the queue in the driver to be ready for the 1st
 1047          * packet;  lkpi_80211_txq_tx_one() still has a workaround as there
 1048          * is no guarantee or way to check.
 1049          * XXX-BZ and by now we know that this does not work on all drivers
 1050          * for all queues.
 1051          */
 1052         lkpi_wake_tx_queues(hw, LSTA_TO_STA(lsta), false, false);
 1053 
 1054         /* Start mgd_prepare_tx. */
 1055         memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1056         prep_tx_info.duration = PREP_TX_INFO_DURATION;
 1057         lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info);
 1058         lsta->in_mgd = true;
 1059 
 1060         /*
 1061          * What is going to happen next:
 1062          * - <twiddle> .. we should end up in "auth_to_assoc"
 1063          * - event_callback
 1064          * - update sta_state (NONE to AUTH)
 1065          * - mgd_complete_tx
 1066          * (ideally we'd do that on a callback for something else ...)
 1067          */
 1068 
 1069 out:
 1070         IEEE80211_LOCK(vap->iv_ic);
 1071         if (ni != NULL)
 1072                 ieee80211_free_node(ni);
 1073         return (error);
 1074 }
 1075 
 1076 static int
 1077 lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1078 {
 1079         struct lkpi_hw *lhw;
 1080         struct ieee80211_hw *hw;
 1081         struct lkpi_vif *lvif;
 1082         struct ieee80211_vif *vif;
 1083         struct ieee80211_node *ni;
 1084         struct lkpi_sta *lsta;
 1085         struct ieee80211_sta *sta;
 1086         struct ieee80211_prep_tx_info prep_tx_info;
 1087         int error;
 1088 
 1089         lhw = vap->iv_ic->ic_softc;
 1090         hw = LHW_TO_HW(lhw);
 1091         lvif = VAP_TO_LVIF(vap);
 1092         vif = LVIF_TO_VIF(lvif);
 1093 
 1094         /* Keep ni around. */
 1095         ni = ieee80211_ref_node(vap->iv_bss);
 1096         lsta = ni->ni_drv_data;
 1097         sta = LSTA_TO_STA(lsta);
 1098 
 1099         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1100 
 1101         IEEE80211_UNLOCK(vap->iv_ic);
 1102 
 1103         /* flush, drop. */
 1104         lkpi_80211_mo_flush(hw, vif,  nitems(sta->txq), true);
 1105 
 1106         /* Wake tx queues to get packet(s) out. */
 1107         lkpi_wake_tx_queues(hw, sta, true, true);
 1108 
 1109         /* flush, no drop */
 1110         lkpi_80211_mo_flush(hw, vif,  nitems(sta->txq), false);
 1111 
 1112         /* End mgd_complete_tx. */
 1113         if (lsta->in_mgd) {
 1114                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1115                 prep_tx_info.success = false;
 1116                 lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info);
 1117                 lsta->in_mgd = false;
 1118         }
 1119 
 1120         /* sync_rx_queues */
 1121         lkpi_80211_mo_sync_rx_queues(hw);
 1122 
 1123         /* sta_pre_rcu_remove */
 1124         lkpi_80211_mo_sta_pre_rcu_remove(hw, vif, sta);
 1125 
 1126         /* Take the station down. */
 1127 
 1128         /* Adjust sta and change state (from NONE) to NOTEXIST. */
 1129         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1130         KASSERT(lsta->state == IEEE80211_STA_NONE, ("%s: lsta %p state not "
 1131             "NONE: %#x, nstate %d arg %d\n", __func__, lsta, lsta->state, nstate, arg));
 1132         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_NOTEXIST);
 1133         if (error != 0) {
 1134                 IMPROVE("do we need to undo the chan ctx?");
 1135                 goto out;
 1136         }
 1137 #if 0
 1138         lsta->added_to_drv = false;     /* mo manages. */
 1139 #endif
 1140 
 1141         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1142 
 1143         lkpi_lsta_remove(lsta, lvif);
 1144 
 1145         /* conf_tx */
 1146 
 1147         /* Take the chan ctx down. */
 1148         if (vif->chanctx_conf != NULL) {
 1149                 struct ieee80211_chanctx_conf *conf;
 1150 
 1151                 conf = vif->chanctx_conf;
 1152                 /* Remove vif context. */
 1153                 lkpi_80211_mo_unassign_vif_chanctx(hw, vif, &vif->chanctx_conf);
 1154                 /* NB: vif->chanctx_conf is NULL now. */
 1155 
 1156                 /* Remove chan ctx. */
 1157                 lkpi_80211_mo_remove_chanctx(hw, conf);
 1158                 free(conf, M_LKPI80211);
 1159         }
 1160 
 1161 out:
 1162         IEEE80211_LOCK(vap->iv_ic);
 1163         if (ni != NULL)
 1164                 ieee80211_free_node(ni);
 1165         return (error);
 1166 }
 1167 
 1168 static int
 1169 lkpi_sta_auth_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1170 {
 1171         int error;
 1172 
 1173         error = lkpi_sta_auth_to_scan(vap, nstate, arg);
 1174         if (error == 0)
 1175                 error = lkpi_sta_scan_to_init(vap, nstate, arg);
 1176         return (error);
 1177 }
 1178 
 1179 static int
 1180 lkpi_sta_auth_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1181 {
 1182         struct lkpi_hw *lhw;
 1183         struct ieee80211_hw *hw;
 1184         struct lkpi_vif *lvif;
 1185         struct ieee80211_vif *vif;
 1186         struct ieee80211_node *ni;
 1187         struct lkpi_sta *lsta;
 1188         struct ieee80211_prep_tx_info prep_tx_info;
 1189         int error;
 1190 
 1191         lhw = vap->iv_ic->ic_softc;
 1192         hw = LHW_TO_HW(lhw);
 1193         lvif = VAP_TO_LVIF(vap);
 1194         vif = LVIF_TO_VIF(lvif);
 1195 
 1196         IEEE80211_UNLOCK(vap->iv_ic);
 1197         ni = NULL;
 1198 
 1199         /* Finish auth. */
 1200         IMPROVE("event callback");
 1201 
 1202         /* Update sta_state (NONE to AUTH). */
 1203         ni = ieee80211_ref_node(vap->iv_bss);
 1204         lsta = ni->ni_drv_data;
 1205         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1206         KASSERT(lsta->state == IEEE80211_STA_NONE, ("%s: lsta %p state not "
 1207             "NONE: %#x\n", __func__, lsta, lsta->state));
 1208         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_AUTH);
 1209         if (error != 0)
 1210                 goto out;
 1211 
 1212         /* End mgd_complete_tx. */
 1213         if (lsta->in_mgd) {
 1214                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1215                 prep_tx_info.success = true;
 1216                 lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info);
 1217                 lsta->in_mgd = false;
 1218         }
 1219 
 1220         /* Now start assoc. */
 1221 
 1222         /* Start mgd_prepare_tx. */
 1223         if (!lsta->in_mgd) {
 1224                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1225                 prep_tx_info.duration = PREP_TX_INFO_DURATION;
 1226                 lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info);
 1227                 lsta->in_mgd = true;
 1228         }
 1229 
 1230         /* Wake tx queue to get packet out. */
 1231         lkpi_wake_tx_queues(hw, LSTA_TO_STA(lsta), true, true);
 1232 
 1233         /*
 1234          * <twiddle> .. we end up in "assoc_to_run"
 1235          * - update sta_state (AUTH to ASSOC)
 1236          * - conf_tx [all]
 1237          * - bss_info_changed (assoc, aid, ssid, ..)
 1238          * - change_chanctx (if needed)
 1239          * - event_callback
 1240          * - mgd_complete_tx
 1241          */
 1242 
 1243 out:
 1244         IEEE80211_LOCK(vap->iv_ic);
 1245         if (ni != NULL)
 1246                 ieee80211_free_node(ni);
 1247         return (error);
 1248 }
 1249 
 1250 /* auth_to_auth, assoc_to_assoc. */
 1251 static int
 1252 lkpi_sta_a_to_a(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1253 {
 1254         struct lkpi_hw *lhw;
 1255         struct ieee80211_hw *hw;
 1256         struct lkpi_vif *lvif;
 1257         struct ieee80211_vif *vif;
 1258         struct ieee80211_node *ni;
 1259         struct lkpi_sta *lsta;
 1260         struct ieee80211_prep_tx_info prep_tx_info;
 1261 
 1262         lhw = vap->iv_ic->ic_softc;
 1263         hw = LHW_TO_HW(lhw);
 1264         lvif = VAP_TO_LVIF(vap);
 1265         vif = LVIF_TO_VIF(lvif);
 1266 
 1267         ni = ieee80211_ref_node(vap->iv_bss);
 1268 
 1269         IEEE80211_UNLOCK(vap->iv_ic);
 1270         lsta = ni->ni_drv_data;
 1271 
 1272         IMPROVE("event callback?");
 1273 
 1274         /* End mgd_complete_tx. */
 1275         if (lsta->in_mgd) {
 1276                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1277                 prep_tx_info.success = false;
 1278                 lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info);
 1279                 lsta->in_mgd = false;
 1280         }
 1281 
 1282         /* Now start assoc. */
 1283 
 1284         /* Start mgd_prepare_tx. */
 1285         if (!lsta->in_mgd) {
 1286                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1287                 prep_tx_info.duration = PREP_TX_INFO_DURATION;
 1288                 lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info);
 1289                 lsta->in_mgd = true;
 1290         }
 1291 
 1292         IEEE80211_LOCK(vap->iv_ic);
 1293         if (ni != NULL)
 1294                 ieee80211_free_node(ni);
 1295 
 1296         return (0);
 1297 }
 1298 
 1299 static int
 1300 _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1301 {
 1302         struct lkpi_hw *lhw;
 1303         struct ieee80211_hw *hw;
 1304         struct lkpi_vif *lvif;
 1305         struct ieee80211_vif *vif;
 1306         struct ieee80211_node *ni;
 1307         struct lkpi_sta *lsta;
 1308         struct ieee80211_sta *sta;
 1309         struct ieee80211_prep_tx_info prep_tx_info;
 1310         enum ieee80211_bss_changed bss_changed;
 1311         int error;
 1312 
 1313         lhw = vap->iv_ic->ic_softc;
 1314         hw = LHW_TO_HW(lhw);
 1315         lvif = VAP_TO_LVIF(vap);
 1316         vif = LVIF_TO_VIF(lvif);
 1317 
 1318         /* Keep ni around. */
 1319         ni = ieee80211_ref_node(vap->iv_bss);
 1320         lsta = ni->ni_drv_data;
 1321         sta = LSTA_TO_STA(lsta);
 1322 
 1323         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1324 
 1325         IEEE80211_UNLOCK(vap->iv_ic);
 1326 
 1327         /* flush, drop. */
 1328         lkpi_80211_mo_flush(hw, vif,  nitems(sta->txq), true);
 1329 
 1330         IMPROVE("What are the proper conditions for DEAUTH_NEED_MGD_TX_PREP?");
 1331         if (ieee80211_hw_check(hw, DEAUTH_NEED_MGD_TX_PREP) &&
 1332             !lsta->in_mgd) {
 1333                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1334                 prep_tx_info.duration = PREP_TX_INFO_DURATION;
 1335                 lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info);
 1336                 lsta->in_mgd = true;
 1337         }
 1338 
 1339         IEEE80211_LOCK(vap->iv_ic);
 1340 
 1341         /* Call iv_newstate first so we get potential DISASSOC packet out. */
 1342         error = lvif->iv_newstate(vap, nstate, arg);
 1343         if (error != 0)
 1344                 goto outni;
 1345 
 1346         IEEE80211_UNLOCK(vap->iv_ic);
 1347 
 1348         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1349 
 1350         /* Wake tx queues to get packet(s) out. */
 1351         lkpi_wake_tx_queues(hw, sta, true, true);
 1352 
 1353         /* flush, no drop */
 1354         lkpi_80211_mo_flush(hw, vif,  nitems(sta->txq), false);
 1355 
 1356         /* End mgd_complete_tx. */
 1357         if (lsta->in_mgd) {
 1358                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1359                 prep_tx_info.success = false;
 1360                 lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info);
 1361                 lsta->in_mgd = false;
 1362         }
 1363 
 1364         /* sync_rx_queues */
 1365         lkpi_80211_mo_sync_rx_queues(hw);
 1366 
 1367         /* sta_pre_rcu_remove */
 1368         lkpi_80211_mo_sta_pre_rcu_remove(hw, vif, sta);
 1369 
 1370         /* Take the station down. */
 1371 
 1372         /* Update sta and change state (from AUTH) to NONE. */
 1373         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1374         KASSERT(lsta->state == IEEE80211_STA_AUTH, ("%s: lsta %p state not "
 1375             "AUTH: %#x\n", __func__, lsta, lsta->state));
 1376         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_NONE);
 1377         if (error != 0)
 1378                 goto out;
 1379 
 1380         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1381 
 1382         /* Adjust sta and change state (from NONE) to NOTEXIST. */
 1383         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1384         KASSERT(lsta->state == IEEE80211_STA_NONE, ("%s: lsta %p state not "
 1385             "NONE: %#x, nstate %d arg %d\n", __func__, lsta, lsta->state, nstate, arg));
 1386         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_NOTEXIST);
 1387         if (error != 0) {
 1388                 IMPROVE("do we need to undo the chan ctx?");
 1389                 goto out;
 1390         }
 1391 #if 0
 1392         lsta->added_to_drv = false;     /* mo manages. */
 1393 #endif
 1394 
 1395         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1396 
 1397         /* Update bss info (bss_info_changed) (assoc, aid, ..). */
 1398         /* We need to do this now, can only do after sta is IEEE80211_STA_NOTEXIST. */
 1399         lkpi_disassoc(sta, vif, lhw);
 1400 
 1401         IMPROVE("Any bss_info changes to announce?");
 1402         bss_changed = 0;
 1403         vif->bss_conf.qos = 0;
 1404         bss_changed |= BSS_CHANGED_QOS;
 1405         vif->bss_conf.ssid_len = 0;
 1406         memset(vif->bss_conf.ssid, '\0', sizeof(vif->bss_conf.ssid));
 1407         bss_changed |= BSS_CHANGED_BSSID;
 1408         lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
 1409 
 1410         lkpi_lsta_remove(lsta, lvif);
 1411 
 1412         /* conf_tx */
 1413 
 1414         /* Take the chan ctx down. */
 1415         if (vif->chanctx_conf != NULL) {
 1416                 struct ieee80211_chanctx_conf *conf;
 1417 
 1418                 conf = vif->chanctx_conf;
 1419                 /* Remove vif context. */
 1420                 lkpi_80211_mo_unassign_vif_chanctx(hw, vif, &vif->chanctx_conf);
 1421                 /* NB: vif->chanctx_conf is NULL now. */
 1422 
 1423                 /* Remove chan ctx. */
 1424                 lkpi_80211_mo_remove_chanctx(hw, conf);
 1425                 free(conf, M_LKPI80211);
 1426         }
 1427 
 1428         error = EALREADY;
 1429 out:
 1430         IEEE80211_LOCK(vap->iv_ic);
 1431 outni:
 1432         if (ni != NULL)
 1433                 ieee80211_free_node(ni);
 1434         return (error);
 1435 }
 1436 
 1437 static int
 1438 lkpi_sta_assoc_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1439 {
 1440         int error;
 1441 
 1442         error = _lkpi_sta_assoc_to_down(vap, nstate, arg);
 1443         if (error != 0 && error != EALREADY)
 1444                 return (error);
 1445 
 1446         /* At this point iv_bss is long a new node! */
 1447 
 1448         error |= lkpi_sta_scan_to_auth(vap, nstate, 0);
 1449         return (error);
 1450 }
 1451 
 1452 static int
 1453 lkpi_sta_assoc_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1454 {
 1455         int error;
 1456 
 1457         error = _lkpi_sta_assoc_to_down(vap, nstate, arg);
 1458         return (error);
 1459 }
 1460 
 1461 static int
 1462 lkpi_sta_assoc_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1463 {
 1464         int error;
 1465 
 1466         error = _lkpi_sta_assoc_to_down(vap, nstate, arg);
 1467         return (error);
 1468 }
 1469 
 1470 static int
 1471 lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1472 {
 1473         struct lkpi_hw *lhw;
 1474         struct ieee80211_hw *hw;
 1475         struct lkpi_vif *lvif;
 1476         struct ieee80211_vif *vif;
 1477         struct ieee80211_node *ni;
 1478         struct lkpi_sta *lsta;
 1479         struct ieee80211_sta *sta;
 1480         struct ieee80211_prep_tx_info prep_tx_info;
 1481         enum ieee80211_bss_changed bss_changed;
 1482         int error;
 1483 
 1484         lhw = vap->iv_ic->ic_softc;
 1485         hw = LHW_TO_HW(lhw);
 1486         lvif = VAP_TO_LVIF(vap);
 1487         vif = LVIF_TO_VIF(lvif);
 1488 
 1489         IEEE80211_UNLOCK(vap->iv_ic);
 1490         ni = NULL;
 1491 
 1492         IMPROVE("ponder some of this moved to ic_newassoc, scan_assoc_success, "
 1493             "and to lesser extend ieee80211_notify_node_join");
 1494 
 1495         /* Finish assoc. */
 1496         /* Update sta_state (AUTH to ASSOC) and set aid. */
 1497         ni = ieee80211_ref_node(vap->iv_bss);
 1498         lsta = ni->ni_drv_data;
 1499         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1500         KASSERT(lsta->state == IEEE80211_STA_AUTH, ("%s: lsta %p state not "
 1501             "AUTH: %#x\n", __func__, lsta, lsta->state));
 1502         sta = LSTA_TO_STA(lsta);
 1503         sta->aid = IEEE80211_NODE_AID(ni);
 1504 #ifdef LKPI_80211_WME
 1505         if (vap->iv_flags & IEEE80211_F_WME)
 1506                 sta->wme = true;
 1507 #endif
 1508         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_ASSOC);
 1509         if (error != 0)
 1510                 goto out;
 1511 
 1512         IMPROVE("wme / conf_tx [all]");
 1513 
 1514         /* Update bss info (bss_info_changed) (assoc, aid, ..). */
 1515         bss_changed = 0;
 1516 #ifdef LKPI_80211_WME
 1517         bss_changed |= lkpi_wme_update(lhw, vap, true);
 1518 #endif
 1519         if (!vif->bss_conf.assoc || vif->bss_conf.aid != IEEE80211_NODE_AID(ni)) {
 1520                 vif->bss_conf.assoc = true;
 1521                 vif->bss_conf.aid = IEEE80211_NODE_AID(ni);
 1522                 bss_changed |= BSS_CHANGED_ASSOC;
 1523         }
 1524         /* We set SSID but this is not BSSID! */
 1525         vif->bss_conf.ssid_len = ni->ni_esslen;
 1526         memcpy(vif->bss_conf.ssid, ni->ni_essid, ni->ni_esslen);
 1527         if ((vap->iv_flags & IEEE80211_F_SHPREAMBLE) !=
 1528             vif->bss_conf.use_short_preamble) {
 1529                 vif->bss_conf.use_short_preamble ^= 1;
 1530                 /* bss_changed |= BSS_CHANGED_??? */
 1531         }
 1532         if ((vap->iv_flags & IEEE80211_F_SHSLOT) !=
 1533             vif->bss_conf.use_short_slot) {
 1534                 vif->bss_conf.use_short_slot ^= 1;
 1535                 /* bss_changed |= BSS_CHANGED_??? */
 1536         }
 1537         if ((ni->ni_flags & IEEE80211_NODE_QOS) !=
 1538             vif->bss_conf.qos) {
 1539                 vif->bss_conf.qos ^= 1;
 1540                 bss_changed |= BSS_CHANGED_QOS;
 1541         }
 1542 
 1543         bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__);
 1544 
 1545         lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
 1546 
 1547         /* - change_chanctx (if needed)
 1548          * - event_callback
 1549          */
 1550 
 1551         /* End mgd_complete_tx. */
 1552         if (lsta->in_mgd) {
 1553                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1554                 prep_tx_info.success = true;
 1555                 lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info);
 1556                 lsta->in_mgd = false;
 1557         }
 1558 
 1559         lkpi_hw_conf_idle(hw, false);
 1560 
 1561         /*
 1562          * And then:
 1563          * - (more packets)?
 1564          * - set_key
 1565          * - set_default_unicast_key
 1566          * - set_key (?)
 1567          * - ipv6_addr_change (?)
 1568          */
 1569         /* Prepare_multicast && configure_filter. */
 1570         lhw->update_mc = true;
 1571         lkpi_update_mcast_filter(vap->iv_ic, true);
 1572 
 1573         if (!ieee80211_node_is_authorized(ni)) {
 1574                 IMPROVE("net80211 does not consider node authorized");
 1575         }
 1576 
 1577         /* Update sta_state (ASSOC to AUTHORIZED). */
 1578         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1579         KASSERT(lsta->state == IEEE80211_STA_ASSOC, ("%s: lsta %p state not "
 1580             "ASSOC: %#x\n", __func__, lsta, lsta->state));
 1581         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_AUTHORIZED);
 1582         if (error != 0) {
 1583                 IMPROVE("undo some changes?");
 1584                 goto out;
 1585         }
 1586 
 1587         /* - drv_config (?)
 1588          * - bss_info_changed
 1589          * - set_rekey_data (?)
 1590          *
 1591          * And now we should be passing packets.
 1592          */
 1593         IMPROVE("Need that bssid setting, and the keys");
 1594 
 1595         bss_changed = 0;
 1596         bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__);
 1597         lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
 1598 
 1599 out:
 1600         IEEE80211_LOCK(vap->iv_ic);
 1601         if (ni != NULL)
 1602                 ieee80211_free_node(ni);
 1603         return (error);
 1604 }
 1605 
 1606 static int
 1607 lkpi_sta_auth_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1608 {
 1609         int error;
 1610 
 1611         error = lkpi_sta_auth_to_assoc(vap, nstate, arg);
 1612         if (error == 0)
 1613                 error = lkpi_sta_assoc_to_run(vap, nstate, arg);
 1614         return (error);
 1615 }
 1616 
 1617 static int
 1618 lkpi_sta_run_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1619 {
 1620         struct lkpi_hw *lhw;
 1621         struct ieee80211_hw *hw;
 1622         struct lkpi_vif *lvif;
 1623         struct ieee80211_vif *vif;
 1624         struct ieee80211_node *ni;
 1625         struct lkpi_sta *lsta;
 1626         struct ieee80211_sta *sta;
 1627         struct ieee80211_prep_tx_info prep_tx_info;
 1628 #if 0
 1629         enum ieee80211_bss_changed bss_changed;
 1630 #endif
 1631         int error;
 1632 
 1633         lhw = vap->iv_ic->ic_softc;
 1634         hw = LHW_TO_HW(lhw);
 1635         lvif = VAP_TO_LVIF(vap);
 1636         vif = LVIF_TO_VIF(lvif);
 1637 
 1638         /* Keep ni around. */
 1639         ni = ieee80211_ref_node(vap->iv_bss);
 1640         lsta = ni->ni_drv_data;
 1641         sta = LSTA_TO_STA(lsta);
 1642 
 1643         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1644 
 1645         IEEE80211_UNLOCK(vap->iv_ic);
 1646 
 1647         /* flush, drop. */
 1648         lkpi_80211_mo_flush(hw, vif,  nitems(sta->txq), true);
 1649 
 1650         IMPROVE("What are the proper conditions for DEAUTH_NEED_MGD_TX_PREP?");
 1651         if (ieee80211_hw_check(hw, DEAUTH_NEED_MGD_TX_PREP) &&
 1652             !lsta->in_mgd) {
 1653                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1654                 prep_tx_info.duration = PREP_TX_INFO_DURATION;
 1655                 lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info);
 1656                 lsta->in_mgd = true;
 1657         }
 1658 
 1659         IEEE80211_LOCK(vap->iv_ic);
 1660 
 1661         /* Call iv_newstate first so we get potential DISASSOC packet out. */
 1662         error = lvif->iv_newstate(vap, nstate, arg);
 1663         if (error != 0)
 1664                 goto outni;
 1665 
 1666         IEEE80211_UNLOCK(vap->iv_ic);
 1667 
 1668         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1669 
 1670         /* Wake tx queues to get packet(s) out. */
 1671         lkpi_wake_tx_queues(hw, sta, true, true);
 1672 
 1673         /* flush, no drop */
 1674         lkpi_80211_mo_flush(hw, vif,  nitems(sta->txq), false);
 1675 
 1676         /* End mgd_complete_tx. */
 1677         if (lsta->in_mgd) {
 1678                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1679                 prep_tx_info.success = false;
 1680                 lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info);
 1681                 lsta->in_mgd = false;
 1682         }
 1683 
 1684 #if 0
 1685         /* sync_rx_queues */
 1686         lkpi_80211_mo_sync_rx_queues(hw);
 1687 
 1688         /* sta_pre_rcu_remove */
 1689         lkpi_80211_mo_sta_pre_rcu_remove(hw, vif, sta);
 1690 #endif
 1691 
 1692         /* Take the station down. */
 1693 
 1694         /* Adjust sta and change state (from AUTHORIZED) to ASSOC. */
 1695         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1696         KASSERT(lsta->state == IEEE80211_STA_AUTHORIZED, ("%s: lsta %p state not "
 1697             "AUTHORIZED: %#x\n", __func__, lsta, lsta->state));
 1698         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_ASSOC);
 1699         if (error != 0)
 1700                 goto out;
 1701 
 1702         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1703 
 1704         /* Update sta_state (ASSOC to AUTH). */
 1705         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1706         KASSERT(lsta->state == IEEE80211_STA_ASSOC, ("%s: lsta %p state not "
 1707             "ASSOC: %#x\n", __func__, lsta, lsta->state));
 1708         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_AUTH);
 1709         if (error != 0)
 1710                 goto out;
 1711 
 1712         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1713 
 1714 #if 0
 1715         /* Update bss info (bss_info_changed) (assoc, aid, ..). */
 1716         lkpi_disassoc(sta, vif, lhw);
 1717 #endif
 1718 
 1719         error = EALREADY;
 1720 out:
 1721         IEEE80211_LOCK(vap->iv_ic);
 1722 outni:
 1723         if (ni != NULL)
 1724                 ieee80211_free_node(ni);
 1725         return (error);
 1726 }
 1727 
 1728 static int
 1729 lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1730 {
 1731         struct lkpi_hw *lhw;
 1732         struct ieee80211_hw *hw;
 1733         struct lkpi_vif *lvif;
 1734         struct ieee80211_vif *vif;
 1735         struct ieee80211_node *ni;
 1736         struct lkpi_sta *lsta;
 1737         struct ieee80211_sta *sta;
 1738         struct ieee80211_prep_tx_info prep_tx_info;
 1739         enum ieee80211_bss_changed bss_changed;
 1740         int error;
 1741 
 1742         lhw = vap->iv_ic->ic_softc;
 1743         hw = LHW_TO_HW(lhw);
 1744         lvif = VAP_TO_LVIF(vap);
 1745         vif = LVIF_TO_VIF(lvif);
 1746 
 1747         /* Keep ni around. */
 1748         ni = ieee80211_ref_node(vap->iv_bss);
 1749         lsta = ni->ni_drv_data;
 1750         sta = LSTA_TO_STA(lsta);
 1751 
 1752         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1753 
 1754         IEEE80211_UNLOCK(vap->iv_ic);
 1755 
 1756         /* flush, drop. */
 1757         lkpi_80211_mo_flush(hw, vif,  nitems(sta->txq), true);
 1758 
 1759         IMPROVE("What are the proper conditions for DEAUTH_NEED_MGD_TX_PREP?");
 1760         if (ieee80211_hw_check(hw, DEAUTH_NEED_MGD_TX_PREP) &&
 1761             !lsta->in_mgd) {
 1762                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1763                 prep_tx_info.duration = PREP_TX_INFO_DURATION;
 1764                 lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info);
 1765                 lsta->in_mgd = true;
 1766         }
 1767 
 1768         IEEE80211_LOCK(vap->iv_ic);
 1769 
 1770         /* Call iv_newstate first so we get potential DISASSOC packet out. */
 1771         error = lvif->iv_newstate(vap, nstate, arg);
 1772         if (error != 0)
 1773                 goto outni;
 1774 
 1775         IEEE80211_UNLOCK(vap->iv_ic);
 1776 
 1777         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1778 
 1779         /* Wake tx queues to get packet(s) out. */
 1780         lkpi_wake_tx_queues(hw, sta, true, true);
 1781 
 1782         /* flush, no drop */
 1783         lkpi_80211_mo_flush(hw, vif,  nitems(sta->txq), false);
 1784 
 1785         /* End mgd_complete_tx. */
 1786         if (lsta->in_mgd) {
 1787                 memset(&prep_tx_info, 0, sizeof(prep_tx_info));
 1788                 prep_tx_info.success = false;
 1789                 lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info);
 1790                 lsta->in_mgd = false;
 1791         }
 1792 
 1793         /* sync_rx_queues */
 1794         lkpi_80211_mo_sync_rx_queues(hw);
 1795 
 1796         /* sta_pre_rcu_remove */
 1797         lkpi_80211_mo_sta_pre_rcu_remove(hw, vif, sta);
 1798 
 1799         /* Take the station down. */
 1800 
 1801         /* Adjust sta and change state (from AUTHORIZED) to ASSOC. */
 1802         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1803         KASSERT(lsta->state == IEEE80211_STA_AUTHORIZED, ("%s: lsta %p state not "
 1804             "AUTHORIZED: %#x\n", __func__, lsta, lsta->state));
 1805         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_ASSOC);
 1806         if (error != 0)
 1807                 goto out;
 1808 
 1809         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1810 
 1811         /* Update sta_state (ASSOC to AUTH). */
 1812         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1813         KASSERT(lsta->state == IEEE80211_STA_ASSOC, ("%s: lsta %p state not "
 1814             "ASSOC: %#x\n", __func__, lsta, lsta->state));
 1815         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_AUTH);
 1816         if (error != 0)
 1817                 goto out;
 1818 
 1819         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1820 
 1821         /* Update sta and change state (from AUTH) to NONE. */
 1822         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1823         KASSERT(lsta->state == IEEE80211_STA_AUTH, ("%s: lsta %p state not "
 1824             "AUTH: %#x\n", __func__, lsta, lsta->state));
 1825         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_NONE);
 1826         if (error != 0)
 1827                 goto out;
 1828 
 1829         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1830 
 1831         /* Adjust sta and change state (from NONE) to NOTEXIST. */
 1832         KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
 1833         KASSERT(lsta->state == IEEE80211_STA_NONE, ("%s: lsta %p state not "
 1834             "NONE: %#x, nstate %d arg %d\n", __func__, lsta, lsta->state, nstate, arg));
 1835         error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_NOTEXIST);
 1836         if (error != 0) {
 1837                 IMPROVE("do we need to undo the chan ctx?");
 1838                 goto out;
 1839         }
 1840 #if 0
 1841         lsta->added_to_drv = false;     /* mo manages. */
 1842 #endif
 1843 
 1844         lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
 1845 
 1846         /* Update bss info (bss_info_changed) (assoc, aid, ..). */
 1847         /*
 1848          * One would expect this to happen when going off AUTHORIZED.
 1849          * See comment there; removes the sta from fw.
 1850          */
 1851         lkpi_disassoc(sta, vif, lhw);
 1852 
 1853         IMPROVE("Any bss_info changes to announce?");
 1854         bss_changed = 0;
 1855         vif->bss_conf.qos = 0;
 1856         bss_changed |= BSS_CHANGED_QOS;
 1857         vif->bss_conf.ssid_len = 0;
 1858         memset(vif->bss_conf.ssid, '\0', sizeof(vif->bss_conf.ssid));
 1859         bss_changed |= BSS_CHANGED_BSSID;
 1860         lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
 1861 
 1862         lkpi_lsta_remove(lsta, lvif);
 1863 
 1864         /* conf_tx */
 1865 
 1866         /* Take the chan ctx down. */
 1867         if (vif->chanctx_conf != NULL) {
 1868                 struct ieee80211_chanctx_conf *conf;
 1869 
 1870                 conf = vif->chanctx_conf;
 1871                 /* Remove vif context. */
 1872                 lkpi_80211_mo_unassign_vif_chanctx(hw, vif, &vif->chanctx_conf);
 1873                 /* NB: vif->chanctx_conf is NULL now. */
 1874 
 1875                 /* Remove chan ctx. */
 1876                 lkpi_80211_mo_remove_chanctx(hw, conf);
 1877                 free(conf, M_LKPI80211);
 1878         }
 1879 
 1880         error = EALREADY;
 1881 out:
 1882         IEEE80211_LOCK(vap->iv_ic);
 1883 outni:
 1884         if (ni != NULL)
 1885                 ieee80211_free_node(ni);
 1886         return (error);
 1887 }
 1888 
 1889 static int
 1890 lkpi_sta_run_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1891 {
 1892 
 1893         return (lkpi_sta_run_to_init(vap, nstate, arg));
 1894 }
 1895 
 1896 static int
 1897 lkpi_sta_run_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1898 {
 1899         int error;
 1900 
 1901         error = lkpi_sta_run_to_init(vap, nstate, arg);
 1902         if (error != 0 && error != EALREADY)
 1903                 return (error);
 1904 
 1905         /* At this point iv_bss is long a new node! */
 1906 
 1907         error |= lkpi_sta_scan_to_auth(vap, nstate, 0);
 1908         return (error);
 1909 }
 1910 
 1911 /* -------------------------------------------------------------------------- */
 1912 
 1913 /*
 1914  * The matches the documented state changes in net80211::sta_newstate().
 1915  * XXX (1) without CSA and SLEEP yet, * XXX (2) not all unhandled cases
 1916  * there are "invalid" (so there is a room for failure here).
 1917  */
 1918 struct fsm_state {
 1919         /* INIT, SCAN, AUTH, ASSOC, CAC, RUN, CSA, SLEEP */
 1920         enum ieee80211_state ostate;
 1921         enum ieee80211_state nstate;
 1922         int (*handler)(struct ieee80211vap *, enum ieee80211_state, int);
 1923 } sta_state_fsm[] = {
 1924         { IEEE80211_S_INIT,     IEEE80211_S_INIT, lkpi_sta_state_do_nada },
 1925         { IEEE80211_S_SCAN,     IEEE80211_S_INIT, lkpi_sta_state_do_nada },     /* scan_to_init */
 1926         { IEEE80211_S_AUTH,     IEEE80211_S_INIT, lkpi_sta_auth_to_init },      /* not explicitly in sta_newstate() */
 1927         { IEEE80211_S_ASSOC,    IEEE80211_S_INIT, lkpi_sta_assoc_to_init },     /* Send DEAUTH. */
 1928         { IEEE80211_S_RUN,      IEEE80211_S_INIT, lkpi_sta_run_to_init },       /* Send DISASSOC. */
 1929 
 1930         { IEEE80211_S_INIT,     IEEE80211_S_SCAN, lkpi_sta_state_do_nada },
 1931         { IEEE80211_S_SCAN,     IEEE80211_S_SCAN, lkpi_sta_state_do_nada },
 1932         { IEEE80211_S_AUTH,     IEEE80211_S_SCAN, lkpi_sta_auth_to_scan },
 1933         { IEEE80211_S_ASSOC,    IEEE80211_S_SCAN, lkpi_sta_assoc_to_scan },
 1934         { IEEE80211_S_RUN,      IEEE80211_S_SCAN, lkpi_sta_run_to_scan },       /* Beacon miss. */
 1935 
 1936         { IEEE80211_S_INIT,     IEEE80211_S_AUTH, lkpi_sta_scan_to_auth },      /* Send AUTH. */
 1937         { IEEE80211_S_SCAN,     IEEE80211_S_AUTH, lkpi_sta_scan_to_auth },      /* Send AUTH. */
 1938         { IEEE80211_S_AUTH,     IEEE80211_S_AUTH, lkpi_sta_a_to_a },            /* Send ?AUTH. */
 1939         { IEEE80211_S_ASSOC,    IEEE80211_S_AUTH, lkpi_sta_assoc_to_auth },     /* Send ?AUTH. */
 1940         { IEEE80211_S_RUN,      IEEE80211_S_AUTH, lkpi_sta_run_to_auth },       /* Send ?AUTH. */
 1941 
 1942         { IEEE80211_S_AUTH,     IEEE80211_S_ASSOC, lkpi_sta_auth_to_assoc },    /* Send ASSOCREQ. */
 1943         { IEEE80211_S_ASSOC,    IEEE80211_S_ASSOC, lkpi_sta_a_to_a },           /* Send ASSOCREQ. */
 1944         { IEEE80211_S_RUN,      IEEE80211_S_ASSOC, lkpi_sta_run_to_assoc },     /* Send ASSOCREQ/REASSOCREQ. */
 1945 
 1946         { IEEE80211_S_AUTH,     IEEE80211_S_RUN, lkpi_sta_auth_to_run },
 1947         { IEEE80211_S_ASSOC,    IEEE80211_S_RUN, lkpi_sta_assoc_to_run },
 1948         { IEEE80211_S_RUN,      IEEE80211_S_RUN, lkpi_sta_state_do_nada },
 1949 
 1950         /* Dummy at the end without handler. */
 1951         { IEEE80211_S_INIT,     IEEE80211_S_INIT, NULL },
 1952 };
 1953 
 1954 static int
 1955 lkpi_iv_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 1956 {
 1957         struct ieee80211com *ic;
 1958         struct lkpi_hw *lhw;
 1959         struct lkpi_vif *lvif;
 1960         struct ieee80211_vif *vif;
 1961         struct fsm_state *s;
 1962         enum ieee80211_state ostate;
 1963         int error;
 1964 
 1965         ic = vap->iv_ic;
 1966         IEEE80211_LOCK_ASSERT(ic);
 1967         ostate = vap->iv_state;
 1968 
 1969 #ifdef LINUXKPI_DEBUG_80211
 1970         if (linuxkpi_debug_80211 & D80211_TRACE)
 1971                 ic_printf(vap->iv_ic, "%s:%d: vap %p nstate %#x arg %#x\n",
 1972                     __func__, __LINE__, vap, nstate, arg);
 1973 #endif
 1974 
 1975         if (vap->iv_opmode == IEEE80211_M_STA) {
 1976 
 1977                 lhw = ic->ic_softc;
 1978                 lvif = VAP_TO_LVIF(vap);
 1979                 vif = LVIF_TO_VIF(lvif);
 1980 
 1981                 /* No need to replicate this in most state handlers. */
 1982                 if (ostate == IEEE80211_S_SCAN && nstate != IEEE80211_S_SCAN)
 1983                         lkpi_stop_hw_scan(lhw, vif);
 1984 
 1985                 s = sta_state_fsm;
 1986 
 1987         } else {
 1988                 ic_printf(vap->iv_ic, "%s: only station mode currently supported: "
 1989                     "cap %p iv_opmode %d\n", __func__, vap, vap->iv_opmode);
 1990                 return (ENOSYS);
 1991         }
 1992 
 1993         error = 0;
 1994         for (; s->handler != NULL; s++) {
 1995                 if (ostate == s->ostate && nstate == s->nstate) {
 1996 #ifdef LINUXKPI_DEBUG_80211
 1997                         if (linuxkpi_debug_80211 & D80211_TRACE)
 1998                                 ic_printf(vap->iv_ic, "%s: new state %d (%s) ->"
 1999                                     " %d (%s): arg %d.\n", __func__,
 2000                                     ostate, ieee80211_state_name[ostate],
 2001                                     nstate, ieee80211_state_name[nstate], arg);
 2002 #endif
 2003                         error = s->handler(vap, nstate, arg);
 2004                         break;
 2005                 }
 2006         }
 2007         IEEE80211_LOCK_ASSERT(vap->iv_ic);
 2008 
 2009         if (s->handler == NULL) {
 2010                 IMPROVE("turn this into a KASSERT\n");
 2011                 ic_printf(vap->iv_ic, "%s: unsupported state transition "
 2012                     "%d (%s) -> %d (%s)\n", __func__,
 2013                     ostate, ieee80211_state_name[ostate],
 2014                     nstate, ieee80211_state_name[nstate]);
 2015                 return (ENOSYS);
 2016         }
 2017 
 2018         if (error == EALREADY) {
 2019 #ifdef LINUXKPI_DEBUG_80211
 2020                 if (linuxkpi_debug_80211 & D80211_TRACE)
 2021                         ic_printf(vap->iv_ic, "%s: state transition %d (%s) -> "
 2022                             "%d (%s): iv_newstate already handled: %d.\n",
 2023                             __func__, ostate, ieee80211_state_name[ostate],
 2024                             nstate, ieee80211_state_name[nstate], error);
 2025 #endif
 2026                 return (0);
 2027         }
 2028 
 2029         if (error != 0) {
 2030                 /* XXX-BZ currently expected so ignore. */
 2031                 ic_printf(vap->iv_ic, "%s: error %d during state transition "
 2032                     "%d (%s) -> %d (%s)\n", __func__, error,
 2033                     ostate, ieee80211_state_name[ostate],
 2034                     nstate, ieee80211_state_name[nstate]);
 2035                 /* return (error); */
 2036         }
 2037 
 2038 #ifdef LINUXKPI_DEBUG_80211
 2039         if (linuxkpi_debug_80211 & D80211_TRACE)
 2040                 ic_printf(vap->iv_ic, "%s:%d: vap %p nstate %#x arg %#x "
 2041                     "calling net80211 parent\n",
 2042                     __func__, __LINE__, vap, nstate, arg);
 2043 #endif
 2044 
 2045         return (lvif->iv_newstate(vap, nstate, arg));
 2046 }
 2047 
 2048 /* -------------------------------------------------------------------------- */
 2049 
 2050 /*
 2051  * We overload (*iv_update_bss) as otherwise we have cases in, e.g.,
 2052  * net80211::ieee80211_sta_join1() where vap->iv_bss gets replaced by a
 2053  * new node without us knowing and thus our ni/lsta are out of sync.
 2054  */
 2055 static struct ieee80211_node *
 2056 lkpi_iv_update_bss(struct ieee80211vap *vap, struct ieee80211_node *ni)
 2057 {
 2058         struct lkpi_vif *lvif;
 2059         struct ieee80211_node *obss;
 2060         struct lkpi_sta *lsta;
 2061         struct ieee80211_sta *sta;
 2062 
 2063         obss = vap->iv_bss;
 2064 
 2065 #ifdef LINUXKPI_DEBUG_80211
 2066         if (linuxkpi_debug_80211 & D80211_TRACE)
 2067                 ic_printf(vap->iv_ic, "%s: obss %p ni_drv_data %p "
 2068                     "ni %p ni_drv_data %p\n", __func__,
 2069                     obss, (obss != NULL) ? obss->ni_drv_data : NULL,
 2070                     ni, (ni != NULL) ? ni->ni_drv_data : NULL);
 2071 #endif
 2072 
 2073         /* Nothing to copy from.  Just return. */
 2074         if (obss == NULL || obss->ni_drv_data == NULL)
 2075                 goto out;
 2076 
 2077         /* Nothing to copy to.  Just return. */
 2078         IMPROVE("clearing the obss might still be needed?");
 2079         if (ni == NULL)
 2080                 goto out;
 2081 
 2082         /* Nothing changed? panic? */
 2083         if (obss == ni)
 2084                 goto out;
 2085 
 2086         lsta = obss->ni_drv_data;
 2087         obss->ni_drv_data = ni->ni_drv_data;
 2088         ni->ni_drv_data = lsta;
 2089         if (lsta != NULL) {
 2090                 lsta->ni = ni;
 2091                 sta = LSTA_TO_STA(lsta);
 2092                 IEEE80211_ADDR_COPY(sta->addr, lsta->ni->ni_macaddr);
 2093         }
 2094         lsta = obss->ni_drv_data;
 2095         if (lsta != NULL) {
 2096                 lsta->ni = obss;
 2097                 sta = LSTA_TO_STA(lsta);
 2098                 IEEE80211_ADDR_COPY(sta->addr, lsta->ni->ni_macaddr);
 2099         }
 2100 
 2101 out:
 2102         lvif = VAP_TO_LVIF(vap);
 2103         return (lvif->iv_update_bss(vap, ni));
 2104 }
 2105 
 2106 #ifdef LKPI_80211_WME
 2107 static int
 2108 lkpi_wme_update(struct lkpi_hw *lhw, struct ieee80211vap *vap, bool planned)
 2109 {
 2110         struct ieee80211com *ic;
 2111         struct ieee80211_hw *hw;
 2112         struct lkpi_vif *lvif;
 2113         struct ieee80211_vif *vif;
 2114         struct chanAccParams chp;
 2115         struct wmeParams wmeparr[WME_NUM_AC];
 2116         struct ieee80211_tx_queue_params txqp;
 2117         enum ieee80211_bss_changed changed;
 2118         int error;
 2119         uint16_t ac;
 2120 
 2121         IMPROVE();
 2122         KASSERT(WME_NUM_AC == IEEE80211_NUM_ACS, ("%s: WME_NUM_AC %d != "
 2123             "IEEE80211_NUM_ACS %d\n", __func__, WME_NUM_AC, IEEE80211_NUM_ACS));
 2124 
 2125         if (vap == NULL)
 2126                 return (0);
 2127 
 2128         if ((vap->iv_flags & IEEE80211_F_WME) == 0)
 2129                 return (0);
 2130 
 2131         if (lhw->ops->conf_tx == NULL)
 2132                 return (0);
 2133 
 2134         if (!planned && (vap->iv_state != IEEE80211_S_RUN)) {
 2135                 lhw->update_wme = true;
 2136                 return (0);
 2137         }
 2138         lhw->update_wme = false;
 2139 
 2140         ic = lhw->ic;
 2141         ieee80211_wme_ic_getparams(ic, &chp);
 2142         IEEE80211_LOCK(ic);
 2143         for (ac = 0; ac < WME_NUM_AC; ac++)
 2144                 wmeparr[ac] = chp.cap_wmeParams[ac];
 2145         IEEE80211_UNLOCK(ic);
 2146 
 2147         hw = LHW_TO_HW(lhw);
 2148         lvif = VAP_TO_LVIF(vap);
 2149         vif = LVIF_TO_VIF(lvif);
 2150 
 2151         /* Configure tx queues (conf_tx) & send BSS_CHANGED_QOS. */
 2152         LKPI_80211_LHW_LOCK(lhw);
 2153         for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
 2154                 struct wmeParams *wmep;
 2155 
 2156                 wmep = &wmeparr[ac];
 2157                 bzero(&txqp, sizeof(txqp));
 2158                 txqp.cw_min = wmep->wmep_logcwmin;
 2159                 txqp.cw_max = wmep->wmep_logcwmax;
 2160                 txqp.txop = wmep->wmep_txopLimit;
 2161                 txqp.aifs = wmep->wmep_aifsn;
 2162                 error = lkpi_80211_mo_conf_tx(hw, vif, ac, &txqp);
 2163                 if (error != 0)
 2164                         printf("%s: conf_tx ac %u failed %d\n",
 2165                             __func__, ac, error);
 2166         }
 2167         LKPI_80211_LHW_UNLOCK(lhw);
 2168         changed = BSS_CHANGED_QOS;
 2169         if (!planned)
 2170                 lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, changed);
 2171 
 2172         return (changed);
 2173 }
 2174 #endif
 2175 
 2176 static int
 2177 lkpi_ic_wme_update(struct ieee80211com *ic)
 2178 {
 2179 #ifdef LKPI_80211_WME
 2180         struct ieee80211vap *vap;
 2181         struct lkpi_hw *lhw;
 2182 
 2183         IMPROVE("Use the per-VAP callback in net80211.");
 2184         vap = TAILQ_FIRST(&ic->ic_vaps);
 2185         if (vap == NULL)
 2186                 return (0);
 2187 
 2188         lhw = ic->ic_softc;
 2189 
 2190         lkpi_wme_update(lhw, vap, false);
 2191 #endif
 2192         return (0);     /* unused */
 2193 }
 2194 
 2195 static struct ieee80211vap *
 2196 lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
 2197     int unit, enum ieee80211_opmode opmode, int flags,
 2198     const uint8_t bssid[IEEE80211_ADDR_LEN],
 2199     const uint8_t mac[IEEE80211_ADDR_LEN])
 2200 {
 2201         struct lkpi_hw *lhw;
 2202         struct ieee80211_hw *hw;
 2203         struct lkpi_vif *lvif;
 2204         struct ieee80211vap *vap;
 2205         struct ieee80211_vif *vif;
 2206         enum ieee80211_bss_changed changed;
 2207         size_t len;
 2208         int error, i;
 2209 
 2210         if (!TAILQ_EMPTY(&ic->ic_vaps)) /* 1 so far. Add <n> once this works. */
 2211                 return (NULL);
 2212 
 2213         lhw = ic->ic_softc;
 2214         hw = LHW_TO_HW(lhw);
 2215 
 2216         len = sizeof(*lvif);
 2217         len += hw->vif_data_size;       /* vif->drv_priv */
 2218 
 2219         lvif = malloc(len, M_80211_VAP, M_WAITOK | M_ZERO);
 2220         mtx_init(&lvif->mtx, "lvif", NULL, MTX_DEF);
 2221         TAILQ_INIT(&lvif->lsta_head);
 2222         vap = LVIF_TO_VAP(lvif);
 2223 
 2224         vif = LVIF_TO_VIF(lvif);
 2225         memcpy(vif->addr, mac, IEEE80211_ADDR_LEN);
 2226         vif->p2p = false;
 2227         vif->probe_req_reg = false;
 2228         vif->type = lkpi_opmode_to_vif_type(opmode);
 2229         lvif->wdev.iftype = vif->type;
 2230         /* Need to fill in other fields as well. */
 2231         IMPROVE();
 2232 
 2233         /* XXX-BZ hardcoded for now! */
 2234 #if 1
 2235         vif->chanctx_conf = NULL;
 2236         vif->bss_conf.idle = true;
 2237         vif->bss_conf.ps = false;
 2238         vif->bss_conf.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
 2239         vif->bss_conf.use_short_preamble = false;       /* vap->iv_flags IEEE80211_F_SHPREAMBLE */
 2240         vif->bss_conf.use_short_slot = false;           /* vap->iv_flags IEEE80211_F_SHSLOT */
 2241         vif->bss_conf.qos = false;
 2242         vif->bss_conf.use_cts_prot = false;             /* vap->iv_protmode */
 2243         vif->bss_conf.ht_operation_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
 2244         vif->bss_conf.assoc = false;
 2245         vif->bss_conf.aid = 0;
 2246         /*
 2247          * We need to initialize it to something as the bss_info_changed call
 2248          * will try to copy from it in iwlwifi and NULL is a panic.
 2249          * We will set the proper one in scan_to_auth() before being assoc.
 2250          * NB: the logic there with using an array as bssid_override and checking
 2251          * for non-NULL later is flawed but in their workflow does not seem to
 2252          * matter.
 2253          */
 2254         vif->bss_conf.bssid = zerobssid;
 2255 #endif
 2256 #if 0
 2257         vif->bss_conf.dtim_period = 0; /* IEEE80211_DTIM_DEFAULT ; must stay 0. */
 2258         IEEE80211_ADDR_COPY(vif->bss_conf.bssid, bssid);
 2259         vif->bss_conf.beacon_int = ic->ic_bintval;
 2260         /* iwlwifi bug. */
 2261         if (vif->bss_conf.beacon_int < 16)
 2262                 vif->bss_conf.beacon_int = 16;
 2263 #endif
 2264 
 2265         /* Setup queue defaults; driver may override in (*add_interface). */
 2266         for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 2267                 if (ieee80211_hw_check(hw, QUEUE_CONTROL))
 2268                         vif->hw_queue[i] = IEEE80211_INVAL_HW_QUEUE;
 2269                 else if (hw->queues >= IEEE80211_NUM_ACS)
 2270                         vif->hw_queue[i] = i;
 2271                 else
 2272                         vif->hw_queue[i] = 0;
 2273         }
 2274         vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
 2275 
 2276         IMPROVE();
 2277 
 2278         error = lkpi_80211_mo_start(hw);
 2279         if (error != 0) {
 2280                 printf("%s: failed to start hw: %d\n", __func__, error);
 2281                 mtx_destroy(&lvif->mtx);
 2282                 free(lvif, M_80211_VAP);
 2283                 return (NULL);
 2284         }
 2285 
 2286         error = lkpi_80211_mo_add_interface(hw, vif);
 2287         if (error != 0) {
 2288                 IMPROVE();      /* XXX-BZ mo_stop()? */
 2289                 printf("%s: failed to add interface: %d\n", __func__, error);
 2290                 mtx_destroy(&lvif->mtx);
 2291                 free(lvif, M_80211_VAP);
 2292                 return (NULL);
 2293         }
 2294 
 2295         LKPI_80211_LHW_LVIF_LOCK(lhw);
 2296         TAILQ_INSERT_TAIL(&lhw->lvif_head, lvif, lvif_entry);
 2297         LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 2298 
 2299         /* Set bss_info. */
 2300         changed = 0;
 2301         lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, changed);
 2302 
 2303         /* conf_tx setup; default WME? */
 2304 
 2305         /* Force MC init. */
 2306         lkpi_update_mcast_filter(ic, true);
 2307 
 2308         IMPROVE();
 2309 
 2310         ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
 2311 
 2312         /* Override with LinuxKPI method so we can drive mac80211/cfg80211. */
 2313         lvif->iv_newstate = vap->iv_newstate;
 2314         vap->iv_newstate = lkpi_iv_newstate;
 2315         lvif->iv_update_bss = vap->iv_update_bss;
 2316         vap->iv_update_bss = lkpi_iv_update_bss;
 2317 
 2318         /* Key management. */
 2319         if (lhw->ops->set_key != NULL) {
 2320 #ifdef LKPI_80211_HW_CRYPTO
 2321                 vap->iv_key_set = lkpi_iv_key_set;
 2322                 vap->iv_key_delete = lkpi_iv_key_delete;
 2323 #endif
 2324         }
 2325 
 2326         ieee80211_ratectl_init(vap);
 2327 
 2328         /* Complete setup. */
 2329         ieee80211_vap_attach(vap, ieee80211_media_change,
 2330             ieee80211_media_status, mac);
 2331 
 2332         if (hw->max_listen_interval == 0)
 2333                 hw->max_listen_interval = 7 * (ic->ic_lintval / ic->ic_bintval);
 2334         hw->conf.listen_interval = hw->max_listen_interval;
 2335         ic->ic_set_channel(ic);
 2336 
 2337         /* XXX-BZ do we need to be able to update these? */
 2338         hw->wiphy->frag_threshold =  vap->iv_fragthreshold;
 2339         lkpi_80211_mo_set_frag_threshold(hw, vap->iv_fragthreshold);
 2340         hw->wiphy->rts_threshold =  vap->iv_rtsthreshold;
 2341         lkpi_80211_mo_set_rts_threshold(hw, vap->iv_rtsthreshold);
 2342         /* any others? */
 2343         IMPROVE();
 2344 
 2345         return (vap);
 2346 }
 2347 
 2348 void
 2349 linuxkpi_ieee80211_unregister_hw(struct ieee80211_hw *hw)
 2350 {
 2351 
 2352         wiphy_unregister(hw->wiphy);
 2353         linuxkpi_ieee80211_ifdetach(hw);
 2354 
 2355         IMPROVE();
 2356 }
 2357 
 2358 void
 2359 linuxkpi_ieee80211_restart_hw(struct ieee80211_hw *hw)
 2360 {
 2361 
 2362         TODO();
 2363 }
 2364 
 2365 static void
 2366 lkpi_ic_vap_delete(struct ieee80211vap *vap)
 2367 {
 2368         struct ieee80211com *ic;
 2369         struct lkpi_hw *lhw;
 2370         struct ieee80211_hw *hw;
 2371         struct lkpi_vif *lvif;
 2372         struct ieee80211_vif *vif;
 2373 
 2374         lvif = VAP_TO_LVIF(vap);
 2375         vif = LVIF_TO_VIF(lvif);
 2376         ic = vap->iv_ic;
 2377         lhw = ic->ic_softc;
 2378         hw = LHW_TO_HW(lhw);
 2379 
 2380         LKPI_80211_LHW_LVIF_LOCK(lhw);
 2381         TAILQ_REMOVE(&lhw->lvif_head, lvif, lvif_entry);
 2382         LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 2383         lkpi_80211_mo_remove_interface(hw, vif);
 2384 
 2385         ieee80211_ratectl_deinit(vap);
 2386         ieee80211_vap_detach(vap);
 2387         mtx_destroy(&lvif->mtx);
 2388         free(lvif, M_80211_VAP);
 2389 }
 2390 
 2391 static void
 2392 lkpi_ic_update_mcast(struct ieee80211com *ic)
 2393 {
 2394 
 2395         lkpi_update_mcast_filter(ic, false);
 2396         TRACEOK();
 2397 }
 2398 
 2399 static void
 2400 lkpi_ic_update_promisc(struct ieee80211com *ic)
 2401 {
 2402 
 2403         UNIMPLEMENTED;
 2404 }
 2405 
 2406 static void
 2407 lkpi_ic_update_chw(struct ieee80211com *ic)
 2408 {
 2409 
 2410         UNIMPLEMENTED;
 2411 }
 2412 
 2413 /* Start / stop device. */
 2414 static void
 2415 lkpi_ic_parent(struct ieee80211com *ic)
 2416 {
 2417         struct lkpi_hw *lhw;
 2418         struct ieee80211_hw *hw;
 2419         int error;
 2420         bool start_all;
 2421 
 2422         IMPROVE();
 2423 
 2424         lhw = ic->ic_softc;
 2425         hw = LHW_TO_HW(lhw);
 2426         start_all = false;
 2427 
 2428         if (ic->ic_nrunning > 0) {
 2429                 error = lkpi_80211_mo_start(hw);
 2430                 if (error == 0)
 2431                         start_all = true;
 2432         } else {
 2433                 lkpi_80211_mo_stop(hw);
 2434         }
 2435 
 2436         if (start_all)
 2437                 ieee80211_start_all(ic);
 2438 }
 2439 
 2440 bool
 2441 linuxkpi_ieee80211_is_ie_id_in_ie_buf(const u8 ie, const u8 *ie_ids,
 2442     size_t ie_ids_len)
 2443 {
 2444         int i;
 2445 
 2446         for (i = 0; i < ie_ids_len; i++) {
 2447                 if (ie == *ie_ids)
 2448                         return (true);
 2449         }
 2450 
 2451         return (false);
 2452 }
 2453 
 2454 /* Return true if skipped; false if error. */
 2455 bool
 2456 linuxkpi_ieee80211_ie_advance(size_t *xp, const u8 *ies, size_t ies_len)
 2457 {
 2458         size_t x;
 2459         uint8_t l;
 2460 
 2461         x = *xp;
 2462 
 2463         KASSERT(x < ies_len, ("%s: x %zu ies_len %zu ies %p\n",
 2464             __func__, x, ies_len, ies));
 2465         l = ies[x + 1];
 2466         x += 2 + l;
 2467 
 2468         if (x > ies_len)
 2469                 return (false);
 2470 
 2471         *xp = x;
 2472         return (true);
 2473 }
 2474 
 2475 static uint8_t *
 2476 lkpi_scan_ies_add(uint8_t *p, struct ieee80211_scan_ies *scan_ies,
 2477     uint32_t band_mask, struct ieee80211vap *vap, struct ieee80211_hw *hw)
 2478 {
 2479         struct ieee80211_supported_band *supband;
 2480         struct linuxkpi_ieee80211_channel *channels;
 2481         const struct ieee80211_channel *chan;
 2482         const struct ieee80211_rateset *rs;
 2483         uint8_t *pb;
 2484         int band, i;
 2485 
 2486         for (band = 0; band < NUM_NL80211_BANDS; band++) {
 2487                 if ((band_mask & (1 << band)) == 0)
 2488                         continue;
 2489 
 2490                 supband = hw->wiphy->bands[band];
 2491                 /*
 2492                  * This should not happen;
 2493                  * band_mask is a bitmask of valid bands to scan on.
 2494                  */
 2495                 if (supband == NULL || supband->n_channels == 0)
 2496                         continue;
 2497 
 2498                 /* Find a first channel to get the mode and rates from. */
 2499                 channels = supband->channels;
 2500                 chan = NULL;
 2501                 for (i = 0; i < supband->n_channels; i++) {
 2502 
 2503                         if (channels[i].flags & IEEE80211_CHAN_DISABLED)
 2504                                 continue;
 2505 
 2506                         chan = ieee80211_find_channel(vap->iv_ic,
 2507                             channels[i].center_freq, 0);
 2508                         if (chan != NULL)
 2509                                 break;
 2510                 }
 2511 
 2512                 /* This really should not happen. */
 2513                 if (chan == NULL)
 2514                         continue;
 2515 
 2516                 pb = p;
 2517                 rs = ieee80211_get_suprates(vap->iv_ic, chan);  /* calls chan2mode */
 2518                 p = ieee80211_add_rates(p, rs);
 2519                 p = ieee80211_add_xrates(p, rs);
 2520 
 2521                 scan_ies->ies[band] = pb;
 2522                 scan_ies->len[band] = p - pb;
 2523         }
 2524 
 2525         /* Add common_ies */
 2526         pb = p;
 2527         if ((vap->iv_flags & IEEE80211_F_WPA1) != 0 &&
 2528             vap->iv_wpa_ie != NULL) {
 2529                 memcpy(p, vap->iv_wpa_ie, 2 + vap->iv_wpa_ie[1]);
 2530                 p += 2 + vap->iv_wpa_ie[1];
 2531         }
 2532         if (vap->iv_appie_probereq != NULL) {
 2533                 memcpy(p, vap->iv_appie_probereq->ie_data,
 2534                     vap->iv_appie_probereq->ie_len);
 2535                 p += vap->iv_appie_probereq->ie_len;
 2536         }
 2537         scan_ies->common_ies = pb;
 2538         scan_ies->common_ie_len = p - pb;
 2539 
 2540         return (p);
 2541 }
 2542 
 2543 static void
 2544 lkpi_ic_scan_start(struct ieee80211com *ic)
 2545 {
 2546         struct lkpi_hw *lhw;
 2547         struct ieee80211_hw *hw;
 2548         struct lkpi_vif *lvif;
 2549         struct ieee80211_vif *vif;
 2550         struct ieee80211_scan_state *ss;
 2551         struct ieee80211vap *vap;
 2552         int error;
 2553 
 2554         lhw = ic->ic_softc;
 2555         if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0) {
 2556                 /* A scan is still running. */
 2557                 return;
 2558         }
 2559 
 2560         ss = ic->ic_scan;
 2561         vap = ss->ss_vap;
 2562         if (vap->iv_state != IEEE80211_S_SCAN) {
 2563                 IMPROVE("We need to be able to scan if not in S_SCAN");
 2564                 return;
 2565         }
 2566 
 2567         hw = LHW_TO_HW(lhw);
 2568         if ((lhw->scan_flags & LKPI_LHW_SCAN_HW) == 0) {
 2569                 /* If hw_scan is cleared clear FEXT_SCAN_OFFLOAD too. */
 2570                 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_OFFLOAD;
 2571 sw_scan:
 2572                 lvif = VAP_TO_LVIF(vap);
 2573                 vif = LVIF_TO_VIF(lvif);
 2574 
 2575                 if (vap->iv_state == IEEE80211_S_SCAN)
 2576                         lkpi_hw_conf_idle(hw, false);
 2577 
 2578                 lkpi_80211_mo_sw_scan_start(hw, vif, vif->addr);
 2579                 /* net80211::scan_start() handled PS for us. */
 2580                 IMPROVE();
 2581                 /* XXX Also means it is too late to flush queues?
 2582                  * need to check iv_sta_ps or overload? */
 2583                 /* XXX want to adjust ss end time/ maxdwell? */
 2584 
 2585         } else {
 2586                 struct ieee80211_channel *c;
 2587                 struct ieee80211_scan_request *hw_req;
 2588                 struct linuxkpi_ieee80211_channel *lc, **cpp;
 2589                 struct cfg80211_ssid *ssids;
 2590                 struct cfg80211_scan_6ghz_params *s6gp;
 2591                 size_t chan_len, nchan, ssids_len, s6ghzlen;
 2592                 int band, i, ssid_count, common_ie_len;
 2593                 uint32_t band_mask;
 2594                 uint8_t *ie, *ieend;
 2595 
 2596                 if (!ieee80211_hw_check(hw, SINGLE_SCAN_ON_ALL_BANDS)) {
 2597                         IMPROVE("individual band scans not yet supported");
 2598                         /* In theory net80211 would have to drive this. */
 2599                         return;
 2600                 }
 2601 
 2602                 ssid_count = min(ss->ss_nssid, hw->wiphy->max_scan_ssids);
 2603                 ssids_len = ssid_count * sizeof(*ssids);
 2604                 s6ghzlen = 0 * (sizeof(*s6gp));                 /* XXX-BZ */
 2605 
 2606                 band_mask = 0;
 2607                 nchan = 0;
 2608                 for (i = ss->ss_next; i < ss->ss_last; i++) {
 2609                         nchan++;
 2610                         band = lkpi_net80211_chan_to_nl80211_band(
 2611                             ss->ss_chans[ss->ss_next + i]);
 2612                         band_mask |= (1 << band);
 2613                 }
 2614                 chan_len = nchan * (sizeof(lc) + sizeof(*lc));
 2615 
 2616                 common_ie_len = 0;
 2617                 if ((vap->iv_flags & IEEE80211_F_WPA1) != 0 &&
 2618                     vap->iv_wpa_ie != NULL)
 2619                         common_ie_len += vap->iv_wpa_ie[1];
 2620                 if (vap->iv_appie_probereq != NULL)
 2621                         common_ie_len += vap->iv_appie_probereq->ie_len;
 2622 
 2623                 /* We would love to check this at an earlier stage... */
 2624                 if (common_ie_len >  hw->wiphy->max_scan_ie_len) {
 2625                         ic_printf(ic, "WARNING: %s: common_ie_len %d > "
 2626                             "wiphy->max_scan_ie_len %d\n", __func__,
 2627                             common_ie_len, hw->wiphy->max_scan_ie_len);
 2628                 }
 2629 
 2630                 KASSERT(lhw->hw_req == NULL, ("%s: ic %p lhw %p hw_req %p "
 2631                     "!= NULL\n", __func__, ic, lhw, lhw->hw_req));
 2632 
 2633                 lhw->hw_req = hw_req = malloc(sizeof(*hw_req) + ssids_len +
 2634                     s6ghzlen + chan_len + lhw->supbands * lhw->scan_ie_len +
 2635                     common_ie_len, M_LKPI80211, M_WAITOK | M_ZERO);
 2636 
 2637                 hw_req->req.flags = 0;                  /* XXX ??? */
 2638                 /* hw_req->req.wdev */
 2639                 hw_req->req.wiphy = hw->wiphy;
 2640                 hw_req->req.no_cck = false;             /* XXX */
 2641 #if 0
 2642                 /* This seems to pessimise default scanning behaviour. */
 2643                 hw_req->req.duration_mandatory = TICKS_2_USEC(ss->ss_mindwell);
 2644                 hw_req->req.duration = TICKS_2_USEC(ss->ss_maxdwell);
 2645 #endif
 2646 #ifdef __notyet__
 2647                 hw_req->req.flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
 2648                 memcpy(hw_req->req.mac_addr, xxx, IEEE80211_ADDR_LEN);
 2649                 memset(hw_req->req.mac_addr_mask, 0xxx, IEEE80211_ADDR_LEN);
 2650 #endif
 2651 
 2652                 hw_req->req.n_channels = nchan;
 2653                 cpp = (struct linuxkpi_ieee80211_channel **)(hw_req + 1);
 2654                 lc = (struct linuxkpi_ieee80211_channel *)(cpp + nchan);
 2655                 for (i = 0; i < nchan; i++) {
 2656                         *(cpp + i) =
 2657                             (struct linuxkpi_ieee80211_channel *)(lc + i);
 2658                 }
 2659                 for (i = 0; i < nchan; i++) {
 2660                         c = ss->ss_chans[ss->ss_next + i];
 2661 
 2662                         lc->hw_value = c->ic_ieee;
 2663                         lc->center_freq = c->ic_freq;
 2664                         /* lc->flags */
 2665                         lc->band = lkpi_net80211_chan_to_nl80211_band(c);
 2666                         lc->max_power = c->ic_maxpower;
 2667                         /* lc-> ... */
 2668                         lc++;
 2669                 }
 2670 
 2671                 hw_req->req.n_ssids = ssid_count;
 2672                 if (hw_req->req.n_ssids > 0) {
 2673                         ssids = (struct cfg80211_ssid *)lc;
 2674                         hw_req->req.ssids = ssids;
 2675                         for (i = 0; i < ssid_count; i++) {
 2676                                 ssids->ssid_len = ss->ss_ssid[i].len;
 2677                                 memcpy(ssids->ssid, ss->ss_ssid[i].ssid,
 2678                                     ss->ss_ssid[i].len);
 2679                                 ssids++;
 2680                         }
 2681                         s6gp = (struct cfg80211_scan_6ghz_params *)ssids;
 2682                 } else {
 2683                         s6gp = (struct cfg80211_scan_6ghz_params *)lc;
 2684                 }
 2685 
 2686                 /* 6GHz one day. */
 2687                 hw_req->req.n_6ghz_params = 0;
 2688                 hw_req->req.scan_6ghz_params = NULL;
 2689                 hw_req->req.scan_6ghz = false;  /* Weird boolean; not what you think. */
 2690                 /* s6gp->... */
 2691 
 2692                 ie = ieend = (uint8_t *)s6gp;
 2693                 /* Copy per-band IEs, copy common IEs */
 2694                 ieend = lkpi_scan_ies_add(ie, &hw_req->ies, band_mask, vap, hw);
 2695                 hw_req->req.ie = ie;
 2696                 hw_req->req.ie_len = ieend - ie;
 2697 
 2698                 lvif = VAP_TO_LVIF(vap);
 2699                 vif = LVIF_TO_VIF(lvif);
 2700                 error = lkpi_80211_mo_hw_scan(hw, vif, hw_req);
 2701                 if (error != 0) {
 2702                         ieee80211_cancel_scan(vap);
 2703 
 2704                         free(hw_req, M_LKPI80211);
 2705                         lhw->hw_req = NULL;
 2706 
 2707                         /*
 2708                          * XXX-SIGH magic number.
 2709                          * rtw88 has a magic "return 1" if offloading scan is
 2710                          * not possible.  Fall back to sw scan in that case.
 2711                          */
 2712                         if (error == 1) {
 2713                                 lhw->scan_flags &= ~LKPI_LHW_SCAN_HW;
 2714                                 ieee80211_start_scan(vap,
 2715                                     IEEE80211_SCAN_ACTIVE |
 2716                                     IEEE80211_SCAN_NOPICK |
 2717                                     IEEE80211_SCAN_ONCE,
 2718                                     IEEE80211_SCAN_FOREVER,
 2719                                     ss->ss_mindwell ? ss->ss_mindwell : msecs_to_ticks(20),
 2720                                     ss->ss_maxdwell ? ss->ss_maxdwell : msecs_to_ticks(200),
 2721                                     vap->iv_des_nssid, vap->iv_des_ssid);
 2722                                 goto sw_scan;
 2723                         }
 2724 
 2725                         ic_printf(ic, "ERROR: %s: hw_scan returned %d\n",
 2726                             __func__, error);
 2727                 }
 2728         }
 2729 }
 2730 
 2731 static void
 2732 lkpi_ic_scan_end(struct ieee80211com *ic)
 2733 {
 2734         struct lkpi_hw *lhw;
 2735 
 2736         lhw = ic->ic_softc;
 2737         if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) == 0) {
 2738                 return;
 2739         }
 2740 
 2741         if ((lhw->scan_flags & LKPI_LHW_SCAN_HW) == 0) {
 2742                 struct ieee80211_scan_state *ss;
 2743                 struct ieee80211vap *vap;
 2744                 struct ieee80211_hw *hw;
 2745                 struct lkpi_vif *lvif;
 2746                 struct ieee80211_vif *vif;
 2747 
 2748                 ss = ic->ic_scan;
 2749                 vap = ss->ss_vap;
 2750                 hw = LHW_TO_HW(lhw);
 2751                 lvif = VAP_TO_LVIF(vap);
 2752                 vif = LVIF_TO_VIF(lvif);
 2753 
 2754                 lkpi_80211_mo_sw_scan_complete(hw, vif);
 2755 
 2756                 /* Send PS to stop buffering if n80211 does not for us? */
 2757 
 2758                 if (vap->iv_state == IEEE80211_S_SCAN)
 2759                         lkpi_hw_conf_idle(hw, true);
 2760         }
 2761 }
 2762 
 2763 static void
 2764 lkpi_ic_scan_curchan(struct ieee80211_scan_state *ss,
 2765     unsigned long maxdwell)
 2766 {
 2767         struct lkpi_hw *lhw;
 2768 
 2769         lhw = ss->ss_ic->ic_softc;
 2770         if ((lhw->scan_flags & LKPI_LHW_SCAN_HW) == 0)
 2771                 lhw->ic_scan_curchan(ss, maxdwell);
 2772 }
 2773 
 2774 static void
 2775 lkpi_ic_scan_mindwell(struct ieee80211_scan_state *ss)
 2776 {
 2777         struct lkpi_hw *lhw;
 2778 
 2779         lhw = ss->ss_ic->ic_softc;
 2780         if ((lhw->scan_flags & LKPI_LHW_SCAN_HW) == 0)
 2781                 lhw->ic_scan_mindwell(ss);
 2782 }
 2783 
 2784 static void
 2785 lkpi_ic_set_channel(struct ieee80211com *ic)
 2786 {
 2787         struct lkpi_hw *lhw;
 2788         struct ieee80211_hw *hw;
 2789         struct ieee80211_channel *c;
 2790         struct linuxkpi_ieee80211_channel *chan;
 2791         int error;
 2792 
 2793         lhw = ic->ic_softc;
 2794 
 2795         /* If we do not support (*config)() save us the work. */
 2796         if (lhw->ops->config == NULL)
 2797                 return;
 2798 
 2799         /* If we have a hw_scan running do not switch channels. */
 2800         if ((lhw->scan_flags & (LKPI_LHW_SCAN_RUNNING|LKPI_LHW_SCAN_HW)) ==
 2801             (LKPI_LHW_SCAN_RUNNING|LKPI_LHW_SCAN_HW))
 2802                 return;
 2803 
 2804         c = ic->ic_curchan;
 2805         if (c == NULL || c == IEEE80211_CHAN_ANYC) {
 2806                 ic_printf(ic, "%s: c %p ops->config %p\n", __func__,
 2807                     c, lhw->ops->config);
 2808                 return;
 2809         }
 2810 
 2811         chan = lkpi_find_lkpi80211_chan(lhw, c);
 2812         if (chan == NULL) {
 2813                 ic_printf(ic, "%s: c %p chan %p\n", __func__,
 2814                     c, chan);
 2815                 return;
 2816         }
 2817 
 2818         /* XXX max power for scanning? */
 2819         IMPROVE();
 2820 
 2821         hw = LHW_TO_HW(lhw);
 2822         cfg80211_chandef_create(&hw->conf.chandef, chan,
 2823             NL80211_CHAN_NO_HT);
 2824 
 2825         error = lkpi_80211_mo_config(hw, IEEE80211_CONF_CHANGE_CHANNEL);
 2826         if (error != 0 && error != EOPNOTSUPP) {
 2827                 ic_printf(ic, "ERROR: %s: config %#0x returned %d\n",
 2828                     __func__, IEEE80211_CONF_CHANGE_CHANNEL, error);
 2829                 /* XXX should we unroll to the previous chandef? */
 2830                 IMPROVE();
 2831         } else {
 2832                 /* Update radiotap channels as well. */
 2833                 lhw->rtap_tx.wt_chan_freq = htole16(c->ic_freq);
 2834                 lhw->rtap_tx.wt_chan_flags = htole16(c->ic_flags);
 2835                 lhw->rtap_rx.wr_chan_freq = htole16(c->ic_freq);
 2836                 lhw->rtap_rx.wr_chan_flags = htole16(c->ic_flags);
 2837         }
 2838 
 2839         /* Currently PS is hard coded off! Not sure it belongs here. */
 2840         IMPROVE();
 2841         if (ieee80211_hw_check(hw, SUPPORTS_PS) &&
 2842             (hw->conf.flags & IEEE80211_CONF_PS) != 0) {
 2843                 hw->conf.flags &= ~IEEE80211_CONF_PS;
 2844                 error = lkpi_80211_mo_config(hw, IEEE80211_CONF_CHANGE_PS);
 2845                 if (error != 0 && error != EOPNOTSUPP)
 2846                         ic_printf(ic, "ERROR: %s: config %#0x returned "
 2847                             "%d\n", __func__, IEEE80211_CONF_CHANGE_PS,
 2848                             error);
 2849         }
 2850 }
 2851 
 2852 static struct ieee80211_node *
 2853 lkpi_ic_node_alloc(struct ieee80211vap *vap,
 2854     const uint8_t mac[IEEE80211_ADDR_LEN])
 2855 {
 2856         struct ieee80211com *ic;
 2857         struct lkpi_hw *lhw;
 2858         struct ieee80211_node *ni;
 2859         struct ieee80211_hw *hw;
 2860         struct lkpi_sta *lsta;
 2861 
 2862         ic = vap->iv_ic;
 2863         lhw = ic->ic_softc;
 2864 
 2865         /* We keep allocations de-coupled so we can deal with the two worlds. */
 2866         if (lhw->ic_node_alloc == NULL)
 2867                 return (NULL);
 2868 
 2869         ni = lhw->ic_node_alloc(vap, mac);
 2870         if (ni == NULL)
 2871                 return (NULL);
 2872 
 2873         hw = LHW_TO_HW(lhw);
 2874         lsta = lkpi_lsta_alloc(vap, mac, hw, ni);
 2875         if (lsta == NULL) {
 2876                 if (lhw->ic_node_free != NULL)
 2877                         lhw->ic_node_free(ni);
 2878                 return (NULL);
 2879         }
 2880 
 2881         return (ni);
 2882 }
 2883 
 2884 static int
 2885 lkpi_ic_node_init(struct ieee80211_node *ni)
 2886 {
 2887         struct ieee80211com *ic;
 2888         struct lkpi_hw *lhw;
 2889         struct lkpi_sta *lsta;
 2890         int error;
 2891 
 2892         ic = ni->ni_ic;
 2893         lhw = ic->ic_softc;
 2894 
 2895         if (lhw->ic_node_init != NULL) {
 2896                 error = lhw->ic_node_init(ni);
 2897                 if (error != 0)
 2898                         return (error);
 2899         }
 2900 
 2901         lsta = ni->ni_drv_data;
 2902 
 2903         /* Now take the reference before linking it to the table. */
 2904         lsta->ni = ieee80211_ref_node(ni);
 2905 
 2906         /* XXX-BZ Sync other state over. */
 2907         IMPROVE();
 2908 
 2909         return (0);
 2910 }
 2911 
 2912 static void
 2913 lkpi_ic_node_cleanup(struct ieee80211_node *ni)
 2914 {
 2915         struct ieee80211com *ic;
 2916         struct lkpi_hw *lhw;
 2917 
 2918         ic = ni->ni_ic;
 2919         lhw = ic->ic_softc;
 2920 
 2921         /* XXX-BZ remove from driver, ... */
 2922         IMPROVE();
 2923 
 2924         if (lhw->ic_node_cleanup != NULL)
 2925                 lhw->ic_node_cleanup(ni);
 2926 }
 2927 
 2928 static void
 2929 lkpi_ic_node_free(struct ieee80211_node *ni)
 2930 {
 2931         struct ieee80211com *ic;
 2932         struct lkpi_hw *lhw;
 2933         struct lkpi_sta *lsta;
 2934 
 2935         ic = ni->ni_ic;
 2936         lhw = ic->ic_softc;
 2937         lsta = ni->ni_drv_data;
 2938         if (lsta == NULL)
 2939                 goto out;
 2940 
 2941         /* XXX-BZ free resources, ... */
 2942         IMPROVE();
 2943 
 2944         /* Flush mbufq (make sure to release ni refs!). */
 2945 #ifdef __notyet__
 2946         KASSERT(mbufq_len(&lsta->txq) == 0, ("%s: lsta %p has txq len %d != 0\n",
 2947             __func__, lsta, mbufq_len(&lsta->txq)));
 2948 #endif
 2949         /* Drain taskq. */
 2950 
 2951         /* Drain sta->txq[] */
 2952         mtx_destroy(&lsta->txq_mtx);
 2953 
 2954         /* Remove lsta if added_to_drv. */
 2955 
 2956         /* Remove lsta from vif */
 2957         /* Remove ref from lsta node... */
 2958         /* Free lsta. */
 2959         lkpi_lsta_remove(lsta, VAP_TO_LVIF(ni->ni_vap));
 2960 
 2961 out:
 2962         if (lhw->ic_node_free != NULL)
 2963                 lhw->ic_node_free(ni);
 2964 }
 2965 
 2966 static int
 2967 lkpi_ic_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
 2968         const struct ieee80211_bpf_params *params __unused)
 2969 {
 2970         struct lkpi_sta *lsta;
 2971 
 2972         lsta = ni->ni_drv_data;
 2973 
 2974         /* Queue the packet and enqueue the task to handle it. */
 2975         LKPI_80211_LSTA_LOCK(lsta);
 2976         mbufq_enqueue(&lsta->txq, m);
 2977         LKPI_80211_LSTA_UNLOCK(lsta);
 2978 
 2979 #ifdef LINUXKPI_DEBUG_80211
 2980         if (linuxkpi_debug_80211 & D80211_TRACE_TX)
 2981                 printf("%s:%d lsta %p ni %p %6D mbuf_qlen %d\n",
 2982                     __func__, __LINE__, lsta, ni, ni->ni_macaddr, ":",
 2983                     mbufq_len(&lsta->txq));
 2984 #endif
 2985 
 2986         taskqueue_enqueue(taskqueue_thread, &lsta->txq_task);
 2987         return (0);
 2988 }
 2989 
 2990 static void
 2991 lkpi_80211_txq_tx_one(struct lkpi_sta *lsta, struct mbuf *m)
 2992 {
 2993         struct ieee80211_node *ni;
 2994 #ifndef LKPI_80211_HW_CRYPTO
 2995         struct ieee80211_frame *wh;
 2996 #endif
 2997         struct ieee80211_key *k;
 2998         struct sk_buff *skb;
 2999         struct ieee80211com *ic;
 3000         struct lkpi_hw *lhw;
 3001         struct ieee80211_hw *hw;
 3002         struct lkpi_vif *lvif;
 3003         struct ieee80211_vif *vif;
 3004         struct ieee80211_channel *c;
 3005         struct ieee80211_tx_control control;
 3006         struct ieee80211_tx_info *info;
 3007         struct ieee80211_sta *sta;
 3008         struct ieee80211_hdr *hdr;
 3009         void *buf;
 3010         uint8_t ac, tid;
 3011 
 3012         M_ASSERTPKTHDR(m);
 3013 #ifdef LINUXKPI_DEBUG_80211
 3014         if (linuxkpi_debug_80211 & D80211_TRACE_TX_DUMP)
 3015                 hexdump(mtod(m, const void *), m->m_len, "RAW TX (plain) ", 0);
 3016 #endif
 3017 
 3018         ni = lsta->ni;
 3019         k = NULL;
 3020 #ifndef LKPI_80211_HW_CRYPTO
 3021         /* Encrypt the frame if need be; XXX-BZ info->control.hw_key. */
 3022         wh = mtod(m, struct ieee80211_frame *);
 3023         if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
 3024                 /* Retrieve key for TX && do software encryption. */
 3025                 k = ieee80211_crypto_encap(ni, m);
 3026                 if (k == NULL) {
 3027                         ieee80211_free_node(ni);
 3028                         m_freem(m);
 3029                         return;
 3030                 }
 3031         }
 3032 #endif
 3033 
 3034         ic = ni->ni_ic;
 3035         lhw = ic->ic_softc;
 3036         hw = LHW_TO_HW(lhw);
 3037         c = ni->ni_chan;
 3038 
 3039         if (ieee80211_radiotap_active_vap(ni->ni_vap)) {
 3040                 struct lkpi_radiotap_tx_hdr *rtap;
 3041 
 3042                 rtap = &lhw->rtap_tx;
 3043                 rtap->wt_flags = 0;
 3044                 if (k != NULL)
 3045                         rtap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
 3046                 if (m->m_flags & M_FRAG)
 3047                         rtap->wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
 3048                 IMPROVE();
 3049                 rtap->wt_rate = 0;
 3050                 if (c != NULL && c != IEEE80211_CHAN_ANYC) {
 3051                         rtap->wt_chan_freq = htole16(c->ic_freq);
 3052                         rtap->wt_chan_flags = htole16(c->ic_flags);
 3053                 }
 3054 
 3055                 ieee80211_radiotap_tx(ni->ni_vap, m);
 3056         }
 3057 
 3058         /*
 3059          * net80211 should handle hw->extra_tx_headroom.
 3060          * Though for as long as we are copying we don't mind.
 3061          * XXX-BZ rtw88 asks for too much headroom for ipv6+tcp:
 3062          * https://lists.freebsd.org/archives/freebsd-transport/2022-February/000012.html
 3063          */
 3064         skb = dev_alloc_skb(hw->extra_tx_headroom + m->m_pkthdr.len);
 3065         if (skb == NULL) {
 3066                 printf("XXX ERROR %s: skb alloc failed\n", __func__);
 3067                 ieee80211_free_node(ni);
 3068                 m_freem(m);
 3069                 return;
 3070         }
 3071         skb_reserve(skb, hw->extra_tx_headroom);
 3072 
 3073         /* XXX-BZ we need a SKB version understanding mbuf. */
 3074         /* Save the mbuf for ieee80211_tx_complete(). */
 3075         skb->m_free_func = lkpi_ieee80211_free_skb_mbuf;
 3076         skb->m = m;
 3077 #if 0
 3078         skb_put_data(skb, m->m_data, m->m_pkthdr.len);
 3079 #else
 3080         buf = skb_put(skb, m->m_pkthdr.len);
 3081         m_copydata(m, 0, m->m_pkthdr.len, buf);
 3082 #endif
 3083         /* Save the ni. */
 3084         m->m_pkthdr.PH_loc.ptr = ni;
 3085 
 3086         lvif = VAP_TO_LVIF(ni->ni_vap);
 3087         vif = LVIF_TO_VIF(lvif);
 3088 
 3089         hdr = (void *)skb->data;
 3090         tid = linuxkpi_ieee80211_get_tid(hdr, true);
 3091         if (tid == IEEE80211_NONQOS_TID) { /* == IEEE80211_NUM_TIDS */
 3092                 skb->priority = 0;
 3093                 ac = IEEE80211_AC_BE;
 3094         } else {
 3095                 skb->priority = tid & IEEE80211_QOS_CTL_TID_MASK;
 3096                 ac = tid_to_mac80211_ac[tid & 7];
 3097         }
 3098         skb_set_queue_mapping(skb, ac);
 3099 
 3100         info = IEEE80211_SKB_CB(skb);
 3101         info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
 3102         /* Slight delay; probably only happens on scanning so fine? */
 3103         if (c == NULL || c == IEEE80211_CHAN_ANYC)
 3104                 c = ic->ic_curchan;
 3105         info->band = lkpi_net80211_chan_to_nl80211_band(c);
 3106         info->hw_queue = vif->hw_queue[ac];
 3107         if (m->m_flags & M_EAPOL)
 3108                 info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
 3109         info->control.vif = vif;
 3110         /* XXX-BZ info->control.rates */
 3111 
 3112         lsta = lkpi_find_lsta_by_ni(lvif, ni);
 3113         if (lsta != NULL) {
 3114                 sta = LSTA_TO_STA(lsta);
 3115 #ifdef LKPI_80211_HW_CRYPTO
 3116                 info->control.hw_key = lsta->kc;
 3117 #endif
 3118         } else {
 3119                 sta = NULL;
 3120         }
 3121 
 3122         IMPROVE();
 3123 
 3124         if (sta != NULL) {
 3125                 struct lkpi_txq *ltxq;
 3126 
 3127                 ltxq = NULL;
 3128                 if (!ieee80211_is_data_present(hdr->frame_control)) {
 3129                         if (vif->type == NL80211_IFTYPE_STATION &&
 3130                             lsta->added_to_drv &&
 3131                             sta->txq[IEEE80211_NUM_TIDS] != NULL)
 3132                                 ltxq = TXQ_TO_LTXQ(sta->txq[IEEE80211_NUM_TIDS]);
 3133                 } else if (lsta->added_to_drv &&
 3134                     sta->txq[skb->priority] != NULL) {
 3135                         ltxq = TXQ_TO_LTXQ(sta->txq[skb->priority]);
 3136                 }
 3137                 if (ltxq == NULL)
 3138                         goto ops_tx;
 3139 
 3140                 KASSERT(ltxq != NULL, ("%s: lsta %p sta %p m %p skb %p "
 3141                     "ltxq %p != NULL\n", __func__, lsta, sta, m, skb, ltxq));
 3142 
 3143                 skb_queue_tail(&ltxq->skbq, skb);
 3144 #ifdef LINUXKPI_DEBUG_80211
 3145                 if (linuxkpi_debug_80211 & D80211_TRACE_TX)
 3146                         printf("%s:%d mo_wake_tx_queue :: %d %u lsta %p sta %p "
 3147                             "ni %p %6D skb %p lxtq %p { qlen %u, ac %d tid %u } "
 3148                             "WAKE_TX_Q ac %d prio %u qmap %u\n",
 3149                             __func__, __LINE__,
 3150                             curthread->td_tid, (unsigned int)ticks,
 3151                             lsta, sta, ni, ni->ni_macaddr, ":", skb, ltxq,
 3152                             skb_queue_len(&ltxq->skbq), ltxq->txq.ac,
 3153                             ltxq->txq.tid, ac, skb->priority, skb->qmap);
 3154 #endif
 3155                 lkpi_80211_mo_wake_tx_queue(hw, &ltxq->txq);
 3156                 return;
 3157         }
 3158 
 3159 ops_tx:
 3160 #ifdef LINUXKPI_DEBUG_80211
 3161         if (linuxkpi_debug_80211 & D80211_TRACE_TX)
 3162                 printf("%s:%d mo_tx :: lsta %p sta %p ni %p %6D skb %p "
 3163                     "TX ac %d prio %u qmap %u\n",
 3164                     __func__, __LINE__, lsta, sta, ni, ni->ni_macaddr, ":",
 3165                     skb, ac, skb->priority, skb->qmap);
 3166 #endif
 3167         memset(&control, 0, sizeof(control));
 3168         control.sta = sta;
 3169 
 3170         lkpi_80211_mo_tx(hw, &control, skb);
 3171         return;
 3172 }
 3173 
 3174 static void
 3175 lkpi_80211_txq_task(void *ctx, int pending)
 3176 {
 3177         struct lkpi_sta *lsta;
 3178         struct mbufq mq;
 3179         struct mbuf *m;
 3180 
 3181         lsta = ctx;
 3182 
 3183 #ifdef LINUXKPI_DEBUG_80211
 3184         if (linuxkpi_debug_80211 & D80211_TRACE_TX)
 3185                 printf("%s:%d lsta %p ni %p %6D pending %d mbuf_qlen %d\n",
 3186                     __func__, __LINE__, lsta, lsta->ni, lsta->ni->ni_macaddr, ":",
 3187                     pending, mbufq_len(&lsta->txq));
 3188 #endif
 3189 
 3190         mbufq_init(&mq, IFQ_MAXLEN);
 3191 
 3192         LKPI_80211_LSTA_LOCK(lsta);
 3193         mbufq_concat(&mq, &lsta->txq);
 3194         LKPI_80211_LSTA_UNLOCK(lsta);
 3195 
 3196         m = mbufq_dequeue(&mq);
 3197         while (m != NULL) {
 3198                 lkpi_80211_txq_tx_one(lsta, m);
 3199                 m = mbufq_dequeue(&mq);
 3200         }
 3201 }
 3202 
 3203 static int
 3204 lkpi_ic_transmit(struct ieee80211com *ic, struct mbuf *m)
 3205 {
 3206 
 3207         /* XXX TODO */
 3208         IMPROVE();
 3209 
 3210         /* Quick and dirty cheating hack. */
 3211         struct ieee80211_node *ni;
 3212 
 3213         ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
 3214         return (lkpi_ic_raw_xmit(ni, m, NULL));
 3215 }
 3216 
 3217 static void
 3218 lkpi_ic_getradiocaps(struct ieee80211com *ic, int maxchan,
 3219     int *n, struct ieee80211_channel *c)
 3220 {
 3221         struct lkpi_hw *lhw;
 3222         struct ieee80211_hw *hw;
 3223         struct linuxkpi_ieee80211_channel *channels;
 3224         uint8_t bands[IEEE80211_MODE_BYTES];
 3225         int chan_flags, error, i, nchans;
 3226 
 3227         /* Channels */
 3228         lhw = ic->ic_softc;
 3229         hw = LHW_TO_HW(lhw);
 3230 
 3231         /* NL80211_BAND_2GHZ */
 3232         nchans = 0;
 3233         if (hw->wiphy->bands[NL80211_BAND_2GHZ] != NULL)
 3234                 nchans = hw->wiphy->bands[NL80211_BAND_2GHZ]->n_channels;
 3235         if (nchans > 0) {
 3236                 memset(bands, 0, sizeof(bands));
 3237                 chan_flags = 0;
 3238                 setbit(bands, IEEE80211_MODE_11B);
 3239                 /* XXX-BZ unclear how to check for 11g. */
 3240                 setbit(bands, IEEE80211_MODE_11G);
 3241 #ifdef __notyet__
 3242                 if (hw->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.ht_supported) {
 3243                         setbit(bands, IEEE80211_MODE_11NG);
 3244                         chan_flags |= NET80211_CBW_FLAG_HT40;
 3245                 }
 3246 #endif
 3247 
 3248                 channels = hw->wiphy->bands[NL80211_BAND_2GHZ]->channels;
 3249                 for (i = 0; i < nchans && *n < maxchan; i++) {
 3250                         uint32_t nflags = 0;
 3251                         int cflags = chan_flags;
 3252 
 3253                         if (channels[i].flags & IEEE80211_CHAN_DISABLED) {
 3254                                 printf("%s: %s: Skipping disabled chan "
 3255                                     "[%u/%u/%#x]\n", ic->ic_name, __func__,
 3256                                     channels[i].hw_value,
 3257                                     channels[i].center_freq, channels[i].flags);
 3258                                 continue;
 3259                         }
 3260                         if (channels[i].flags & IEEE80211_CHAN_NO_IR)
 3261                                 nflags |= (IEEE80211_CHAN_NOADHOC|IEEE80211_CHAN_PASSIVE);
 3262                         if (channels[i].flags & IEEE80211_CHAN_RADAR)
 3263                                 nflags |= IEEE80211_CHAN_DFS;
 3264                         if (channels[i].flags & IEEE80211_CHAN_NO_160MHZ)
 3265                                 cflags &= ~(NET80211_CBW_FLAG_VHT160|NET80211_CBW_FLAG_VHT80P80);
 3266                         if (channels[i].flags & IEEE80211_CHAN_NO_80MHZ)
 3267                                 cflags &= ~NET80211_CBW_FLAG_VHT80;
 3268                         /* XXX how to map the remaining enum ieee80211_channel_flags? */
 3269                         if (channels[i].flags & IEEE80211_CHAN_NO_HT40)
 3270                                 cflags &= ~NET80211_CBW_FLAG_HT40;
 3271 
 3272                         error = ieee80211_add_channel_cbw(c, maxchan, n,
 3273                             channels[i].hw_value, channels[i].center_freq,
 3274                             channels[i].max_power,
 3275                             nflags, bands, chan_flags);
 3276                         /* net80211::ENOBUFS: *n >= maxchans */
 3277                         if (error != 0 && error != ENOBUFS)
 3278                                 printf("%s: %s: Adding chan %u/%u/%#x/%#x/%#x/%#x "
 3279                                     "returned error %d\n", ic->ic_name,
 3280                                     __func__, channels[i].hw_value,
 3281                                     channels[i].center_freq, channels[i].flags,
 3282                                     nflags, chan_flags, cflags, error);
 3283                         if (error != 0)
 3284                                 break;
 3285                 }
 3286         }
 3287 
 3288         /* NL80211_BAND_5GHZ */
 3289         nchans = 0;
 3290         if (hw->wiphy->bands[NL80211_BAND_5GHZ] != NULL)
 3291                 nchans = hw->wiphy->bands[NL80211_BAND_5GHZ]->n_channels;
 3292         if (nchans > 0) {
 3293                 memset(bands, 0, sizeof(bands));
 3294                 chan_flags = 0;
 3295                 setbit(bands, IEEE80211_MODE_11A);
 3296 #ifdef __not_yet__
 3297                 if (hw->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.ht_supported) {
 3298                         setbit(bands, IEEE80211_MODE_11NA);
 3299                         chan_flags |= NET80211_CBW_FLAG_HT40;
 3300                 }
 3301                 if (hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.vht_supported){
 3302 
 3303                         ic->ic_flags_ext |= IEEE80211_FEXT_VHT;
 3304                         ic->ic_vhtcaps =
 3305                             hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap;
 3306 
 3307                         setbit(bands, IEEE80211_MODE_VHT_5GHZ);
 3308                         chan_flags |= NET80211_CBW_FLAG_VHT80;
 3309                         if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(
 3310                             ic->ic_vhtcaps))
 3311                                 chan_flags |= NET80211_CBW_FLAG_VHT160;
 3312                         if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(
 3313                             ic->ic_vhtcaps))
 3314                                 chan_flags |= NET80211_CBW_FLAG_VHT80P80;
 3315                 }
 3316 #endif
 3317 
 3318                 channels = hw->wiphy->bands[NL80211_BAND_5GHZ]->channels;
 3319                 for (i = 0; i < nchans && *n < maxchan; i++) {
 3320                         uint32_t nflags = 0;
 3321                         int cflags = chan_flags;
 3322 
 3323                         if (channels[i].flags & IEEE80211_CHAN_DISABLED) {
 3324                                 printf("%s: %s: Skipping disabled chan "
 3325                                     "[%u/%u/%#x]\n", ic->ic_name, __func__,
 3326                                     channels[i].hw_value,
 3327                                     channels[i].center_freq, channels[i].flags);
 3328                                 continue;
 3329                         }
 3330                         if (channels[i].flags & IEEE80211_CHAN_NO_IR)
 3331                                 nflags |= (IEEE80211_CHAN_NOADHOC|IEEE80211_CHAN_PASSIVE);
 3332                         if (channels[i].flags & IEEE80211_CHAN_RADAR)
 3333                                 nflags |= IEEE80211_CHAN_DFS;
 3334                         if (channels[i].flags & IEEE80211_CHAN_NO_160MHZ)
 3335                                 cflags &= ~(NET80211_CBW_FLAG_VHT160|NET80211_CBW_FLAG_VHT80P80);
 3336                         if (channels[i].flags & IEEE80211_CHAN_NO_80MHZ)
 3337                                 cflags &= ~NET80211_CBW_FLAG_VHT80;
 3338                         /* XXX hwo to map the remaining enum ieee80211_channel_flags? */
 3339                         if (channels[i].flags & IEEE80211_CHAN_NO_HT40)
 3340                                 cflags &= ~NET80211_CBW_FLAG_HT40;
 3341 
 3342                         error = ieee80211_add_channel_cbw(c, maxchan, n,
 3343                             channels[i].hw_value, channels[i].center_freq,
 3344                             channels[i].max_power,
 3345                             nflags, bands, chan_flags);
 3346                         /* net80211::ENOBUFS: *n >= maxchans */
 3347                         if (error != 0 && error != ENOBUFS)
 3348                                 printf("%s: %s: Adding chan %u/%u/%#x/%#x/%#x/%#x "
 3349                                     "returned error %d\n", ic->ic_name,
 3350                                     __func__, channels[i].hw_value,
 3351                                     channels[i].center_freq, channels[i].flags,
 3352                                     nflags, chan_flags, cflags, error);
 3353                         if (error != 0)
 3354                                 break;
 3355                 }
 3356         }
 3357 }
 3358 
 3359 static void *
 3360 lkpi_ieee80211_ifalloc(void)
 3361 {
 3362         struct ieee80211com *ic;
 3363 
 3364         ic = malloc(sizeof(*ic), M_LKPI80211, M_WAITOK | M_ZERO);
 3365         if (ic == NULL)
 3366                 return (NULL);
 3367 
 3368         /* Setting these happens later when we have device information. */
 3369         ic->ic_softc = NULL;
 3370         ic->ic_name = "linuxkpi";
 3371 
 3372         return (ic);
 3373 }
 3374 
 3375 struct ieee80211_hw *
 3376 linuxkpi_ieee80211_alloc_hw(size_t priv_len, const struct ieee80211_ops *ops)
 3377 {
 3378         struct ieee80211_hw *hw;
 3379         struct lkpi_hw *lhw;
 3380         struct wiphy *wiphy;
 3381 
 3382         /* Get us and the driver data also allocated. */
 3383         wiphy = wiphy_new(&linuxkpi_mac80211cfgops, sizeof(*lhw) + priv_len);
 3384         if (wiphy == NULL)
 3385                 return (NULL);
 3386 
 3387         lhw = wiphy_priv(wiphy);
 3388         lhw->ops = ops;
 3389 
 3390         mtx_init(&lhw->mtx, "lhw", NULL, MTX_DEF | MTX_RECURSE);
 3391         sx_init_flags(&lhw->lvif_sx, "lhw-lvif", SX_RECURSE | SX_DUPOK);
 3392         TAILQ_INIT(&lhw->lvif_head);
 3393 
 3394         /*
 3395          * XXX-BZ TODO make sure there is a "_null" function to all ops
 3396          * not initialized.
 3397          */
 3398         hw = LHW_TO_HW(lhw);
 3399         hw->wiphy = wiphy;
 3400         hw->conf.flags |= IEEE80211_CONF_IDLE;
 3401         hw->priv = (void *)(lhw + 1);
 3402 
 3403         /* BSD Specific. */
 3404         lhw->ic = lkpi_ieee80211_ifalloc();
 3405         if (lhw->ic == NULL) {
 3406                 ieee80211_free_hw(hw);
 3407                 return (NULL);
 3408         }
 3409 
 3410         IMPROVE();
 3411 
 3412         return (hw);
 3413 }
 3414 
 3415 void
 3416 linuxkpi_ieee80211_iffree(struct ieee80211_hw *hw)
 3417 {
 3418         struct lkpi_hw *lhw;
 3419 
 3420         lhw = HW_TO_LHW(hw);
 3421         free(lhw->ic, M_LKPI80211);
 3422         lhw->ic = NULL;
 3423 
 3424         /* Cleanup more of lhw here or in wiphy_free()? */
 3425         sx_destroy(&lhw->lvif_sx);
 3426         mtx_destroy(&lhw->mtx);
 3427         IMPROVE();
 3428 }
 3429 
 3430 void
 3431 linuxkpi_set_ieee80211_dev(struct ieee80211_hw *hw, char *name)
 3432 {
 3433         struct lkpi_hw *lhw;
 3434         struct ieee80211com *ic;
 3435 
 3436         lhw = HW_TO_LHW(hw);
 3437         ic = lhw->ic;
 3438 
 3439         /* Now set a proper name before ieee80211_ifattach(). */
 3440         ic->ic_softc = lhw;
 3441         ic->ic_name = name;
 3442 
 3443         /* XXX-BZ do we also need to set wiphy name? */
 3444 }
 3445 
 3446 struct ieee80211_hw *
 3447 linuxkpi_wiphy_to_ieee80211_hw(struct wiphy *wiphy)
 3448 {
 3449         struct lkpi_hw *lhw;
 3450 
 3451         lhw = wiphy_priv(wiphy);
 3452         return (LHW_TO_HW(lhw));
 3453 }
 3454 
 3455 static void
 3456 lkpi_radiotap_attach(struct lkpi_hw *lhw)
 3457 {
 3458         struct ieee80211com *ic;
 3459 
 3460         ic = lhw->ic;
 3461         ieee80211_radiotap_attach(ic,
 3462             &lhw->rtap_tx.wt_ihdr, sizeof(lhw->rtap_tx),
 3463             LKPI_RTAP_TX_FLAGS_PRESENT,
 3464             &lhw->rtap_rx.wr_ihdr, sizeof(lhw->rtap_rx),
 3465             LKPI_RTAP_RX_FLAGS_PRESENT);
 3466 }
 3467 
 3468 int
 3469 linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw)
 3470 {
 3471         struct ieee80211com *ic;
 3472         struct lkpi_hw *lhw;
 3473         int band, i;
 3474 
 3475         lhw = HW_TO_LHW(hw);
 3476         ic = lhw->ic;
 3477 
 3478         /* We do it this late as wiphy->dev should be set for the name. */
 3479         lhw->workq = alloc_ordered_workqueue(wiphy_name(hw->wiphy), 0);
 3480         if (lhw->workq == NULL)
 3481                 return (-EAGAIN);
 3482 
 3483         /* XXX-BZ figure this out how they count his... */
 3484         if (!is_zero_ether_addr(hw->wiphy->perm_addr)) {
 3485                 IEEE80211_ADDR_COPY(ic->ic_macaddr,
 3486                     hw->wiphy->perm_addr);
 3487         } else if (hw->wiphy->n_addresses > 0) {
 3488                 /* We take the first one. */
 3489                 IEEE80211_ADDR_COPY(ic->ic_macaddr,
 3490                     hw->wiphy->addresses[0].addr);
 3491         } else {
 3492                 ic_printf(ic, "%s: warning, no hardware address!\n", __func__);
 3493         }
 3494 
 3495 #ifdef __not_yet__
 3496         /* See comment in lkpi_80211_txq_tx_one(). */
 3497         ic->ic_headroom = hw->extra_tx_headroom;
 3498 #endif
 3499 
 3500         ic->ic_phytype = IEEE80211_T_OFDM;      /* not only, but not used */
 3501         ic->ic_opmode = IEEE80211_M_STA;
 3502 
 3503         /* Set device capabilities. */
 3504         /* XXX-BZ we need to get these from linux80211/drivers and convert. */
 3505         ic->ic_caps =
 3506             IEEE80211_C_STA |
 3507             IEEE80211_C_MONITOR |
 3508             IEEE80211_C_WPA |           /* WPA/RSN */
 3509 #ifdef LKPI_80211_WME
 3510             IEEE80211_C_WME |
 3511 #endif
 3512 #if 0
 3513             IEEE80211_C_PMGT |
 3514 #endif
 3515             IEEE80211_C_SHSLOT |        /* short slot time supported */
 3516             IEEE80211_C_SHPREAMBLE      /* short preamble supported */
 3517             ;
 3518 #if 0
 3519         /* Scanning is a different kind of beast to re-work. */
 3520         ic->ic_caps |= IEEE80211_C_BGSCAN;
 3521 #endif
 3522         if (lhw->ops->hw_scan) {
 3523                 /*
 3524                  * Advertise full-offload scanning.
 3525                  *
 3526                  * Not limiting to SINGLE_SCAN_ON_ALL_BANDS here as otherwise
 3527                  * we essentially disable hw_scan for all drivers not setting
 3528                  * the flag.
 3529                  */
 3530                 ic->ic_flags_ext |= IEEE80211_FEXT_SCAN_OFFLOAD;
 3531                 lhw->scan_flags |= LKPI_LHW_SCAN_HW;
 3532         }
 3533 
 3534 #ifdef __notyet__
 3535         ic->ic_htcaps = IEEE80211_HTC_HT        /* HT operation */
 3536                     | IEEE80211_HTC_AMPDU       /* A-MPDU tx/rx */
 3537                     | IEEE80211_HTC_AMSDU       /* A-MSDU tx/rx */
 3538                     | IEEE80211_HTCAP_MAXAMSDU_3839
 3539                                                 /* max A-MSDU length */
 3540                     | IEEE80211_HTCAP_SMPS_OFF; /* SM power save off */
 3541         ic->ic_htcaps |= IEEE80211_HTCAP_SHORTGI20;
 3542         ic->ic_htcaps |= IEEE80211_HTCAP_CHWIDTH40 | IEEE80211_HTCAP_SHORTGI40;
 3543         ic->ic_htcaps |= IEEE80211_HTCAP_TXSTBC;
 3544 #endif
 3545 
 3546         /*
 3547          * The wiphy variables report bitmasks of avail antennas.
 3548          * (*get_antenna) get the current bitmask sets which can be
 3549          * altered by (*set_antenna) for some drivers.
 3550          * XXX-BZ will the count alone do us much good long-term in net80211?
 3551          */
 3552         if (hw->wiphy->available_antennas_rx ||
 3553             hw->wiphy->available_antennas_tx) {
 3554                 uint32_t rxs, txs;
 3555 
 3556                 if (lkpi_80211_mo_get_antenna(hw, &txs, &rxs) == 0) {
 3557                         ic->ic_rxstream = bitcount32(rxs);
 3558                         ic->ic_txstream = bitcount32(txs);
 3559                 }
 3560         }
 3561 
 3562         ic->ic_cryptocaps = 0;
 3563 #ifdef LKPI_80211_HW_CRYPTO
 3564         if (hw->wiphy->n_cipher_suites > 0) {
 3565                 for (i = 0; i < hw->wiphy->n_cipher_suites; i++)
 3566                         ic->ic_cryptocaps |= lkpi_l80211_to_net80211_cyphers(
 3567                             hw->wiphy->cipher_suites[i]);
 3568         }
 3569 #endif
 3570 
 3571         lkpi_ic_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans,
 3572             ic->ic_channels);
 3573 
 3574         ieee80211_ifattach(ic);
 3575 
 3576         ic->ic_update_mcast = lkpi_ic_update_mcast;
 3577         ic->ic_update_promisc = lkpi_ic_update_promisc;
 3578         ic->ic_update_chw = lkpi_ic_update_chw;
 3579         ic->ic_parent = lkpi_ic_parent;
 3580         ic->ic_scan_start = lkpi_ic_scan_start;
 3581         ic->ic_scan_end = lkpi_ic_scan_end;
 3582         ic->ic_set_channel = lkpi_ic_set_channel;
 3583         ic->ic_transmit = lkpi_ic_transmit;
 3584         ic->ic_raw_xmit = lkpi_ic_raw_xmit;
 3585         ic->ic_vap_create = lkpi_ic_vap_create;
 3586         ic->ic_vap_delete = lkpi_ic_vap_delete;
 3587         ic->ic_getradiocaps = lkpi_ic_getradiocaps;
 3588         ic->ic_wme.wme_update = lkpi_ic_wme_update;
 3589 
 3590         lhw->ic_scan_curchan = ic->ic_scan_curchan;
 3591         ic->ic_scan_curchan = lkpi_ic_scan_curchan;
 3592         lhw->ic_scan_mindwell = ic->ic_scan_mindwell;
 3593         ic->ic_scan_mindwell = lkpi_ic_scan_mindwell;
 3594 
 3595         lhw->ic_node_alloc = ic->ic_node_alloc;
 3596         ic->ic_node_alloc = lkpi_ic_node_alloc;
 3597         lhw->ic_node_init = ic->ic_node_init;
 3598         ic->ic_node_init = lkpi_ic_node_init;
 3599         lhw->ic_node_cleanup = ic->ic_node_cleanup;
 3600         ic->ic_node_cleanup = lkpi_ic_node_cleanup;
 3601         lhw->ic_node_free = ic->ic_node_free;
 3602         ic->ic_node_free = lkpi_ic_node_free;
 3603 
 3604         lkpi_radiotap_attach(lhw);
 3605 
 3606         /*
 3607          * Assign the first possible channel for now;  seems Realtek drivers
 3608          * expect one.
 3609          * Also remember the amount of bands we support and the most rates
 3610          * in any band so we can scale [(ext) sup rates] IE(s) accordingly.
 3611          */
 3612         lhw->supbands = lhw->max_rates = 0;
 3613         for (band = 0; band < NUM_NL80211_BANDS &&
 3614             hw->conf.chandef.chan == NULL; band++) {
 3615                 struct ieee80211_supported_band *supband;
 3616                 struct linuxkpi_ieee80211_channel *channels;
 3617 
 3618                 supband = hw->wiphy->bands[band];
 3619                 if (supband == NULL || supband->n_channels == 0)
 3620                         continue;
 3621 
 3622                 lhw->supbands++;
 3623                 lhw->max_rates = max(lhw->max_rates, supband->n_bitrates);
 3624 
 3625                 channels = supband->channels;
 3626                 for (i = 0; i < supband->n_channels; i++) {
 3627 
 3628                         if (channels[i].flags & IEEE80211_CHAN_DISABLED)
 3629                                 continue;
 3630 
 3631                         cfg80211_chandef_create(&hw->conf.chandef, &channels[i],
 3632                             NL80211_CHAN_NO_HT);
 3633                         break;
 3634                 }
 3635         }
 3636 
 3637         IMPROVE("see net80211::ieee80211_chan_init vs. wiphy->bands[].bitrates possibly in lkpi_ic_getradiocaps?");
 3638 
 3639         /* Make sure we do not support more than net80211 is willing to take. */
 3640         if (lhw->max_rates > IEEE80211_RATE_MAXSIZE) {
 3641                 ic_printf(ic, "%s: limiting max_rates %d to %d!\n", __func__,
 3642                     lhw->max_rates, IEEE80211_RATE_MAXSIZE);
 3643                 lhw->max_rates = IEEE80211_RATE_MAXSIZE;
 3644         }
 3645 
 3646         /*
 3647          * The maximum supported bitrates on any band + size for
 3648          * DSSS Parameter Set give our per-band IE size.
 3649          * XXX-BZ FIXME add HT VHT ... later
 3650          * SSID is the responsibility of the driver and goes on the side.
 3651          * The user specified bits coming from the vap go into the
 3652          * "common ies" fields.
 3653          */
 3654         lhw->scan_ie_len = 2 + IEEE80211_RATE_SIZE;
 3655         if (lhw->max_rates > IEEE80211_RATE_SIZE)
 3656                 lhw->scan_ie_len += 2 + (lhw->max_rates - IEEE80211_RATE_SIZE);
 3657         /*
 3658          * net80211 does not seem to support the DSSS Parameter Set but some of
 3659          * the drivers insert it so calculate the extra fixed space in.
 3660          */
 3661         lhw->scan_ie_len += 2 + 1;
 3662 
 3663         /* Reduce the max_scan_ie_len "left" by the amount we consume already. */
 3664         if (hw->wiphy->max_scan_ie_len > 0)
 3665                 hw->wiphy->max_scan_ie_len -= lhw->scan_ie_len;
 3666 
 3667         if (bootverbose)
 3668                 ieee80211_announce(ic);
 3669 
 3670         return (0);
 3671 }
 3672 
 3673 void
 3674 linuxkpi_ieee80211_ifdetach(struct ieee80211_hw *hw)
 3675 {
 3676         struct lkpi_hw *lhw;
 3677         struct ieee80211com *ic;
 3678 
 3679         lhw = HW_TO_LHW(hw);
 3680         ic = lhw->ic;
 3681         ieee80211_ifdetach(ic);
 3682 }
 3683 
 3684 void
 3685 linuxkpi_ieee80211_iterate_interfaces(struct ieee80211_hw *hw,
 3686     enum ieee80211_iface_iter flags,
 3687     void(*iterfunc)(void *, uint8_t *, struct ieee80211_vif *),
 3688     void *arg)
 3689 {
 3690         struct lkpi_hw *lhw;
 3691         struct lkpi_vif *lvif;
 3692         struct ieee80211_vif *vif;
 3693         bool active, atomic, nin_drv;
 3694 
 3695         lhw = HW_TO_LHW(hw);
 3696 
 3697         if (flags & ~(IEEE80211_IFACE_ITER_NORMAL|
 3698             IEEE80211_IFACE_ITER_RESUME_ALL|
 3699             IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER|
 3700             IEEE80211_IFACE_ITER__ACTIVE|IEEE80211_IFACE_ITER__ATOMIC)) {
 3701                 ic_printf(lhw->ic, "XXX TODO %s flags(%#x) not yet supported.\n",
 3702                     __func__, flags);
 3703         }
 3704 
 3705         active = (flags & IEEE80211_IFACE_ITER__ACTIVE) != 0;
 3706         atomic = (flags & IEEE80211_IFACE_ITER__ATOMIC) != 0;
 3707         nin_drv = (flags & IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER) != 0;
 3708 
 3709         if (atomic)
 3710                 LKPI_80211_LHW_LVIF_LOCK(lhw);
 3711         TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
 3712                 struct ieee80211vap *vap;
 3713 
 3714                 vif = LVIF_TO_VIF(lvif);
 3715 
 3716                 /*
 3717                  * If we want "active" interfaces, we need to distinguish on
 3718                  * whether the driver knows about them or not to be able to
 3719                  * handle the "resume" case correctly.  Skip the ones the
 3720                  * driver does not know about.
 3721                  */
 3722                 if (active && !lvif->added_to_drv &&
 3723                     (flags & IEEE80211_IFACE_ITER_RESUME_ALL) != 0)
 3724                         continue;
 3725 
 3726                 /*
 3727                  * If we shall skip interfaces not added to the driver do so
 3728                  * if we haven't yet.
 3729                  */
 3730                 if (nin_drv && !lvif->added_to_drv)
 3731                         continue;
 3732 
 3733                 /*
 3734                  * Run the iterator function if we are either not asking
 3735                  * asking for active only or if the VAP is "running".
 3736                  */
 3737                 /* XXX-BZ probably should have state in the lvif as well. */
 3738                 vap = LVIF_TO_VAP(lvif);
 3739                 if (!active || (vap->iv_state != IEEE80211_S_INIT))
 3740                         iterfunc(arg, vif->addr, vif);
 3741         }
 3742         if (atomic)
 3743                 LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 3744 }
 3745 
 3746 void
 3747 linuxkpi_ieee80211_iterate_keys(struct ieee80211_hw *hw,
 3748     struct ieee80211_vif *vif,
 3749     void(*iterfunc)(struct ieee80211_hw *, struct ieee80211_vif *,
 3750         struct ieee80211_sta *, struct ieee80211_key_conf *, void *),
 3751     void *arg)
 3752 {
 3753 
 3754         UNIMPLEMENTED;
 3755 }
 3756 
 3757 void
 3758 linuxkpi_ieee80211_iterate_chan_contexts(struct ieee80211_hw *hw,
 3759     void(*iterfunc)(struct ieee80211_hw *, struct ieee80211_chanctx_conf *,
 3760         void *),
 3761     void *arg)
 3762 {
 3763 
 3764         UNIMPLEMENTED;
 3765 }
 3766 
 3767 void
 3768 linuxkpi_ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
 3769    void (*iterfunc)(void *, struct ieee80211_sta *), void *arg)
 3770 {
 3771         struct lkpi_hw *lhw;
 3772         struct lkpi_vif *lvif;
 3773         struct lkpi_sta *lsta;
 3774         struct ieee80211_sta *sta;
 3775 
 3776         KASSERT(hw != NULL && iterfunc != NULL,
 3777             ("%s: hw %p iterfunc %p arg %p\n", __func__, hw, iterfunc, arg));
 3778 
 3779         lhw = HW_TO_LHW(hw);
 3780 
 3781         LKPI_80211_LHW_LVIF_LOCK(lhw);
 3782         TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
 3783 
 3784                 LKPI_80211_LVIF_LOCK(lvif);
 3785                 TAILQ_FOREACH(lsta, &lvif->lsta_head, lsta_entry) {
 3786                         if (!lsta->added_to_drv)
 3787                                 continue;
 3788                         sta = LSTA_TO_STA(lsta);
 3789                         iterfunc(arg, sta);
 3790                 }
 3791                 LKPI_80211_LVIF_UNLOCK(lvif);
 3792         }
 3793         LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 3794 }
 3795 
 3796 int
 3797 linuxkpi_regulatory_set_wiphy_regd_sync(struct wiphy *wiphy,
 3798     struct linuxkpi_ieee80211_regdomain *regd)
 3799 {
 3800         struct lkpi_hw *lhw;
 3801         struct ieee80211com *ic;
 3802         struct ieee80211_regdomain *rd;
 3803 
 3804         lhw = wiphy_priv(wiphy);
 3805         ic = lhw->ic;
 3806 
 3807         rd = &ic->ic_regdomain;
 3808         if (rd->isocc[0] == '\0') {
 3809                 rd->isocc[0] = regd->alpha2[0];
 3810                 rd->isocc[1] = regd->alpha2[1];
 3811         }
 3812 
 3813         TODO();
 3814         /* XXX-BZ finish the rest. */
 3815 
 3816         return (0);
 3817 }
 3818 
 3819 void
 3820 linuxkpi_ieee80211_scan_completed(struct ieee80211_hw *hw,
 3821     struct cfg80211_scan_info *info)
 3822 {
 3823         struct lkpi_hw *lhw;
 3824         struct ieee80211com *ic;
 3825         struct ieee80211_scan_state *ss;
 3826 
 3827         lhw = wiphy_priv(hw->wiphy);
 3828         ic = lhw->ic;
 3829         ss = ic->ic_scan;
 3830 
 3831         ieee80211_scan_done(ss->ss_vap);
 3832 
 3833         LKPI_80211_LHW_LOCK(lhw);
 3834         free(lhw->hw_req, M_LKPI80211);
 3835         lhw->hw_req = NULL;
 3836         lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING;
 3837         wakeup(lhw);
 3838         LKPI_80211_LHW_UNLOCK(lhw);
 3839 
 3840         return;
 3841 }
 3842 
 3843 void
 3844 linuxkpi_ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
 3845     struct ieee80211_sta *sta, struct napi_struct *napi __unused)
 3846 {
 3847         struct epoch_tracker et;
 3848         struct lkpi_hw *lhw;
 3849         struct ieee80211com *ic;
 3850         struct mbuf *m;
 3851         struct skb_shared_info *shinfo;
 3852         struct ieee80211_rx_status *rx_status;
 3853         struct ieee80211_rx_stats rx_stats;
 3854         struct ieee80211_node *ni;
 3855         struct ieee80211vap *vap;
 3856         struct ieee80211_hdr *hdr;
 3857         struct lkpi_sta *lsta;
 3858         int i, offset, ok;
 3859         int8_t rssi;
 3860         bool is_beacon;
 3861 
 3862         if (skb->len < 2) {
 3863                 /* Need 80211 stats here. */
 3864                 IMPROVE();
 3865                 goto err;
 3866         }
 3867 
 3868         /*
 3869          * For now do the data copy; we can later improve things. Might even
 3870          * have an mbuf backing the skb data then?
 3871          */
 3872         m = m_get2(skb->len, M_NOWAIT, MT_DATA, M_PKTHDR);
 3873         if (m == NULL)
 3874                 goto err;
 3875         m_copyback(m, 0, skb->tail - skb->data, skb->data);
 3876 
 3877         shinfo = skb_shinfo(skb);
 3878         offset = m->m_len;
 3879         for (i = 0; i < shinfo->nr_frags; i++) {
 3880                 m_copyback(m, offset, shinfo->frags[i].size,
 3881                     (uint8_t *)linux_page_address(shinfo->frags[i].page) +
 3882                     shinfo->frags[i].offset);
 3883                 offset += shinfo->frags[i].size;
 3884         }
 3885 
 3886         rx_status = IEEE80211_SKB_RXCB(skb);
 3887 
 3888         hdr = (void *)skb->data;
 3889         is_beacon = ieee80211_is_beacon(hdr->frame_control);
 3890 
 3891 #ifdef LINUXKPI_DEBUG_80211
 3892         if (is_beacon && (linuxkpi_debug_80211 & D80211_TRACE_RX_BEACONS) == 0)
 3893                 goto no_trace_beacons;
 3894 
 3895         if (linuxkpi_debug_80211 & D80211_TRACE_RX)
 3896                 printf("TRACE-RX: %s: skb %p a/l/d/t-len (%u/%u/%u/%u) "
 3897                     "h %p d %p t %p e %p sh %p (%u) m %p plen %u len %u%s\n",
 3898                     __func__, skb, skb->_alloc_len, skb->len, skb->data_len,
 3899                     skb->truesize, skb->head, skb->data, skb->tail, skb->end,
 3900                     shinfo, shinfo->nr_frags,
 3901                     m, m->m_pkthdr.len, m->m_len, is_beacon ? " beacon" : "");
 3902 
 3903         if (linuxkpi_debug_80211 & D80211_TRACE_RX_DUMP)
 3904                 hexdump(mtod(m, const void *), m->m_len, "RX (raw) ", 0);
 3905 
 3906         /* Implement a dump_rxcb() !!! */
 3907         if (linuxkpi_debug_80211 & D80211_TRACE_RX)
 3908                 printf("TRACE %s: RXCB: %ju %ju %u, %#0x, %u, %#0x, %#0x, "
 3909                     "%u band %u, %u { %d %d %d %d }, %d, %#x %#x %#x %#x %u %u %u\n",
 3910                         __func__,
 3911                         (uintmax_t)rx_status->boottime_ns,
 3912                         (uintmax_t)rx_status->mactime,
 3913                         rx_status->device_timestamp,
 3914                         rx_status->flag,
 3915                         rx_status->freq,
 3916                         rx_status->bw,
 3917                         rx_status->encoding,
 3918                         rx_status->ampdu_reference,
 3919                         rx_status->band,
 3920                         rx_status->chains,
 3921                         rx_status->chain_signal[0],
 3922                         rx_status->chain_signal[1],
 3923                         rx_status->chain_signal[2],
 3924                         rx_status->chain_signal[3],
 3925                         rx_status->signal,
 3926                         rx_status->enc_flags,
 3927                         rx_status->he_dcm,
 3928                         rx_status->he_gi,
 3929                         rx_status->he_ru,
 3930                         rx_status->zero_length_psdu_type,
 3931                         rx_status->nss,
 3932                         rx_status->rate_idx);
 3933 no_trace_beacons:
 3934 #endif
 3935 
 3936         memset(&rx_stats, 0, sizeof(rx_stats));
 3937         rx_stats.r_flags = IEEE80211_R_NF | IEEE80211_R_RSSI;
 3938         /* XXX-BZ correct hardcoded rssi and noise floor, how? survey? */
 3939         rx_stats.c_nf = -96;
 3940         if (ieee80211_hw_check(hw, SIGNAL_DBM) &&
 3941             !(rx_status->flag & RX_FLAG_NO_SIGNAL_VAL))
 3942                 rssi = rx_status->signal;
 3943         else
 3944                 rssi = rx_stats.c_nf;
 3945         /*
 3946          * net80211 signal strength data are in .5 dBm units relative to
 3947          * the current noise floor (see comment in ieee80211_node.h).
 3948          */
 3949         rssi -= rx_stats.c_nf;
 3950         rx_stats.c_rssi = rssi * 2;
 3951         rx_stats.r_flags |= IEEE80211_R_BAND;
 3952         rx_stats.c_band =
 3953             lkpi_nl80211_band_to_net80211_band(rx_status->band);
 3954         rx_stats.r_flags |= IEEE80211_R_FREQ | IEEE80211_R_IEEE;
 3955         rx_stats.c_freq = rx_status->freq;
 3956         rx_stats.c_ieee = ieee80211_mhz2ieee(rx_stats.c_freq, rx_stats.c_band);
 3957 
 3958         /* XXX (*sta_statistics)() to get to some of that? */
 3959         /* XXX-BZ dump the FreeBSD version of rx_stats as well! */
 3960 
 3961         lhw = HW_TO_LHW(hw);
 3962         ic = lhw->ic;
 3963 
 3964         ok = ieee80211_add_rx_params(m, &rx_stats);
 3965         if (ok == 0) {
 3966                 m_freem(m);
 3967                 counter_u64_add(ic->ic_ierrors, 1);
 3968                 goto err;
 3969         }
 3970 
 3971         if (sta != NULL) {
 3972                 lsta = STA_TO_LSTA(sta);
 3973                 ni = ieee80211_ref_node(lsta->ni);
 3974         } else {
 3975                 struct ieee80211_frame_min *wh;
 3976 
 3977                 wh = mtod(m, struct ieee80211_frame_min *);
 3978                 ni = ieee80211_find_rxnode(ic, wh);
 3979                 if (ni != NULL)
 3980                         lsta = ni->ni_drv_data;
 3981         }
 3982 
 3983         if (ni != NULL)
 3984                 vap = ni->ni_vap;
 3985         else
 3986                 /*
 3987                  * XXX-BZ can we improve this by looking at the frame hdr
 3988                  * or other meta-data passed up?
 3989                  */
 3990                 vap = TAILQ_FIRST(&ic->ic_vaps);
 3991 
 3992 #ifdef LINUXKPI_DEBUG_80211
 3993         if (linuxkpi_debug_80211 & D80211_TRACE_RX)
 3994                 printf("TRACE %s: sta %p lsta %p state %d ni %p vap %p%s\n",
 3995                     __func__, sta, lsta, (lsta != NULL) ? lsta->state : -1,
 3996                     ni, vap, is_beacon ? " beacon" : "");
 3997 #endif
 3998 
 3999         if (ni != NULL && vap != NULL && is_beacon &&
 4000             rx_status->device_timestamp > 0 &&
 4001             m->m_pkthdr.len >= sizeof(struct ieee80211_frame)) {
 4002                 struct lkpi_vif *lvif;
 4003                 struct ieee80211_vif *vif;
 4004                 struct ieee80211_frame *wh;
 4005 
 4006                 wh = mtod(m, struct ieee80211_frame *);
 4007                 if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid))
 4008                         goto skip_device_ts;
 4009 
 4010                 lvif = VAP_TO_LVIF(vap);
 4011                 vif = LVIF_TO_VIF(lvif);
 4012 
 4013                 IMPROVE("TIMING_BEACON_ONLY?");
 4014                 /* mac80211 specific (not net80211) so keep it here. */
 4015                 vif->bss_conf.sync_device_ts = rx_status->device_timestamp;
 4016                 /*
 4017                  * net80211 should take care of the other information (sync_tsf,
 4018                  * sync_dtim_count) as otherwise we need to parse the beacon.
 4019                  */
 4020         }
 4021 skip_device_ts:
 4022 
 4023         if (vap != NULL && vap->iv_state > IEEE80211_S_INIT &&
 4024             ieee80211_radiotap_active_vap(vap)) {
 4025                 struct lkpi_radiotap_rx_hdr *rtap;
 4026 
 4027                 rtap = &lhw->rtap_rx;
 4028                 rtap->wr_tsft = rx_status->device_timestamp;
 4029                 rtap->wr_flags = 0;
 4030                 if (rx_status->enc_flags & RX_ENC_FLAG_SHORTPRE)
 4031                         rtap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
 4032                 if (rx_status->enc_flags & RX_ENC_FLAG_SHORT_GI)
 4033                         rtap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
 4034 #if 0   /* .. or it does not given we strip it below. */
 4035                 if (ieee80211_hw_check(hw, RX_INCLUDES_FCS))
 4036                         rtap->wr_flags |= IEEE80211_RADIOTAP_F_FCS;
 4037 #endif
 4038                 if (rx_status->flag & RX_FLAG_FAILED_FCS_CRC)
 4039                         rtap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
 4040                 rtap->wr_rate = 0;
 4041                 IMPROVE();
 4042                 /* XXX TODO status->encoding / rate_index / bw */
 4043                 rtap->wr_chan_freq = htole16(rx_stats.c_freq);
 4044                 if (ic->ic_curchan->ic_ieee == rx_stats.c_ieee)
 4045                         rtap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
 4046                 rtap->wr_dbm_antsignal = rssi;
 4047                 rtap->wr_dbm_antnoise = rx_stats.c_nf;
 4048         }
 4049 
 4050         if (ieee80211_hw_check(hw, RX_INCLUDES_FCS))
 4051                 m_adj(m, -IEEE80211_CRC_LEN);
 4052 
 4053         NET_EPOCH_ENTER(et);
 4054         if (ni != NULL) {
 4055                 ok = ieee80211_input_mimo(ni, m);
 4056                 ieee80211_free_node(ni);
 4057                 if (ok < 0)
 4058                         m_freem(m);
 4059         } else {
 4060                 ok = ieee80211_input_mimo_all(ic, m);
 4061                 /* mbuf got consumed. */
 4062         }
 4063         NET_EPOCH_EXIT(et);
 4064 
 4065 #ifdef LINUXKPI_DEBUG_80211
 4066         if (linuxkpi_debug_80211 & D80211_TRACE_RX)
 4067                 printf("TRACE %s: handled frame type %#0x\n", __func__, ok);
 4068 #endif
 4069 
 4070         IMPROVE();
 4071 
 4072 err:
 4073         /* The skb is ours so we can free it :-) */
 4074         kfree_skb(skb);
 4075 }
 4076 
 4077 uint8_t
 4078 linuxkpi_ieee80211_get_tid(struct ieee80211_hdr *hdr, bool nonqos_ok)
 4079 {
 4080         const struct ieee80211_frame *wh;
 4081         uint8_t tid;
 4082 
 4083         /* Linux seems to assume this is a QOS-Data-Frame */
 4084         KASSERT(nonqos_ok || ieee80211_is_data_qos(hdr->frame_control),
 4085            ("%s: hdr %p fc %#06x not qos_data\n", __func__, hdr,
 4086            hdr->frame_control));
 4087 
 4088         wh = (const struct ieee80211_frame *)hdr;
 4089         tid = ieee80211_gettid(wh);
 4090         KASSERT(nonqos_ok || tid == (tid & IEEE80211_QOS_TID), ("%s: tid %u "
 4091            "not expected (%u?)\n", __func__, tid, IEEE80211_NONQOS_TID));
 4092 
 4093         return (tid);
 4094 }
 4095 
 4096 struct wiphy *
 4097 linuxkpi_wiphy_new(const struct cfg80211_ops *ops, size_t priv_len)
 4098 {
 4099         struct lkpi_wiphy *lwiphy;
 4100 
 4101         lwiphy = kzalloc(sizeof(*lwiphy) + priv_len, GFP_KERNEL);
 4102         if (lwiphy == NULL)
 4103                 return (NULL);
 4104         lwiphy->ops = ops;
 4105 
 4106         /* XXX TODO */
 4107         return (LWIPHY_TO_WIPHY(lwiphy));
 4108 }
 4109 
 4110 void
 4111 linuxkpi_wiphy_free(struct wiphy *wiphy)
 4112 {
 4113         struct lkpi_wiphy *lwiphy;
 4114 
 4115         if (wiphy == NULL)
 4116                 return;
 4117 
 4118         lwiphy = WIPHY_TO_LWIPHY(wiphy);
 4119         kfree(lwiphy);
 4120 }
 4121 
 4122 uint32_t
 4123 linuxkpi_ieee80211_channel_to_frequency(uint32_t channel,
 4124     enum nl80211_band band)
 4125 {
 4126 
 4127         switch (band) {
 4128         case NL80211_BAND_2GHZ:
 4129                 return (ieee80211_ieee2mhz(channel, IEEE80211_CHAN_2GHZ));
 4130                 break;
 4131         case NL80211_BAND_5GHZ:
 4132                 return (ieee80211_ieee2mhz(channel, IEEE80211_CHAN_5GHZ));
 4133                 break;
 4134         default:
 4135                 /* XXX abort, retry, error, panic? */
 4136                 break;
 4137         }
 4138 
 4139         return (0);
 4140 }
 4141 
 4142 uint32_t
 4143 linuxkpi_ieee80211_frequency_to_channel(uint32_t freq, uint32_t flags __unused)
 4144 {
 4145 
 4146         return (ieee80211_mhz2ieee(freq, 0));
 4147 }
 4148 
 4149 static struct lkpi_sta *
 4150 lkpi_find_lsta_by_ni(struct lkpi_vif *lvif, struct ieee80211_node *ni)
 4151 {
 4152         struct lkpi_sta *lsta, *temp;
 4153 
 4154         LKPI_80211_LVIF_LOCK(lvif);
 4155         TAILQ_FOREACH_SAFE(lsta, &lvif->lsta_head, lsta_entry, temp) {
 4156                 if (lsta->ni == ni) {
 4157                         LKPI_80211_LVIF_UNLOCK(lvif);
 4158                         return (lsta);
 4159                 }
 4160         }
 4161         LKPI_80211_LVIF_UNLOCK(lvif);
 4162 
 4163         return (NULL);
 4164 }
 4165 
 4166 struct ieee80211_sta *
 4167 linuxkpi_ieee80211_find_sta(struct ieee80211_vif *vif, const u8 *peer)
 4168 {
 4169         struct lkpi_vif *lvif;
 4170         struct lkpi_sta *lsta, *temp;
 4171         struct ieee80211_sta *sta;
 4172 
 4173         lvif = VIF_TO_LVIF(vif);
 4174 
 4175         LKPI_80211_LVIF_LOCK(lvif);
 4176         TAILQ_FOREACH_SAFE(lsta, &lvif->lsta_head, lsta_entry, temp) {
 4177                 sta = LSTA_TO_STA(lsta);
 4178                 if (IEEE80211_ADDR_EQ(sta->addr, peer)) {
 4179                         LKPI_80211_LVIF_UNLOCK(lvif);
 4180                         return (sta);
 4181                 }
 4182         }
 4183         LKPI_80211_LVIF_UNLOCK(lvif);
 4184         return (NULL);
 4185 }
 4186 
 4187 struct ieee80211_sta *
 4188 linuxkpi_ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
 4189     const uint8_t *addr, const uint8_t *ourvifaddr)
 4190 {
 4191         struct lkpi_hw *lhw;
 4192         struct lkpi_vif *lvif;
 4193         struct lkpi_sta *lsta;
 4194         struct ieee80211_vif *vif;
 4195         struct ieee80211_sta *sta;
 4196 
 4197         lhw = wiphy_priv(hw->wiphy);
 4198         sta = NULL;
 4199 
 4200         LKPI_80211_LHW_LVIF_LOCK(lhw);
 4201         TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
 4202 
 4203                 /* XXX-BZ check our address from the vif. */
 4204 
 4205                 vif = LVIF_TO_VIF(lvif);
 4206                 if (ourvifaddr != NULL &&
 4207                     !IEEE80211_ADDR_EQ(vif->addr, ourvifaddr))
 4208                         continue;
 4209                 sta = linuxkpi_ieee80211_find_sta(vif, addr);
 4210                 if (sta != NULL)
 4211                         break;
 4212         }
 4213         LKPI_80211_LHW_LVIF_UNLOCK(lhw);
 4214 
 4215         if (sta != NULL) {
 4216                 lsta = STA_TO_LSTA(sta);
 4217                 if (!lsta->added_to_drv)
 4218                         return (NULL);
 4219         }
 4220 
 4221         return (sta);
 4222 }
 4223 
 4224 struct sk_buff *
 4225 linuxkpi_ieee80211_tx_dequeue(struct ieee80211_hw *hw,
 4226     struct ieee80211_txq *txq)
 4227 {
 4228         struct lkpi_txq *ltxq;
 4229         struct sk_buff *skb;
 4230 
 4231         ltxq = TXQ_TO_LTXQ(txq);
 4232         ltxq->seen_dequeue = true;
 4233 
 4234         skb = skb_dequeue(&ltxq->skbq);
 4235 
 4236         return (skb);
 4237 }
 4238 
 4239 void
 4240 linuxkpi_ieee80211_txq_get_depth(struct ieee80211_txq *txq,
 4241     unsigned long *frame_cnt, unsigned long *byte_cnt)
 4242 {
 4243         struct lkpi_txq *ltxq;
 4244         struct sk_buff *skb;
 4245         unsigned long fc, bc;
 4246 
 4247         ltxq = TXQ_TO_LTXQ(txq);
 4248 
 4249         fc = bc = 0;
 4250         skb_queue_walk(&ltxq->skbq, skb) {
 4251                 fc++;
 4252                 bc += skb->len;
 4253         }
 4254         if (frame_cnt)
 4255                 *frame_cnt = fc;
 4256         if (byte_cnt)
 4257                 *byte_cnt = bc;
 4258 
 4259         /* Validate that this is doing the correct thing. */
 4260         /* Should we keep track on en/dequeue? */
 4261         IMPROVE();
 4262 }
 4263 
 4264 /*
 4265  * We are called from ieee80211_free_txskb() or ieee80211_tx_status().
 4266  * The latter tries to derive the success status from the info flags
 4267  * passed back from the driver.  rawx_mit() saves the ni on the m and the
 4268  * m on the skb for us to be able to give feedback to net80211.
 4269  */
 4270 void
 4271 linuxkpi_ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb,
 4272     int status)
 4273 {
 4274         struct ieee80211_node *ni;
 4275         struct mbuf *m;
 4276 
 4277         m = skb->m;
 4278         skb->m = NULL;
 4279 
 4280         if (m != NULL) {
 4281                 ni = m->m_pkthdr.PH_loc.ptr;
 4282                 /* Status: 0 is ok, != 0 is error. */
 4283                 ieee80211_tx_complete(ni, m, status);
 4284                 /* ni & mbuf were consumed. */
 4285         }
 4286 
 4287         kfree_skb(skb);
 4288 }
 4289 
 4290 void
 4291 linuxkpi_ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 4292 {
 4293         struct ieee80211_tx_info *info;
 4294         struct ieee80211_ratectl_tx_status txs;
 4295         struct ieee80211_node *ni;
 4296         int status;
 4297 
 4298         info = IEEE80211_SKB_CB(skb);
 4299 
 4300         if (skb->m != NULL) {
 4301                 struct mbuf *m;
 4302 
 4303                 m = skb->m;
 4304                 ni = m->m_pkthdr.PH_loc.ptr;
 4305                 memset(&txs, 0, sizeof(txs));
 4306         } else {
 4307                 ni = NULL;
 4308         }
 4309 
 4310         if (info->flags & IEEE80211_TX_STAT_ACK) {
 4311                 status = 0;     /* No error. */
 4312                 txs.status = IEEE80211_RATECTL_TX_SUCCESS;
 4313         } else {
 4314                 status = 1;
 4315                 txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED;
 4316         }
 4317 
 4318         if (ni != NULL) {
 4319                 int ridx __unused;
 4320 #ifdef LINUXKPI_DEBUG_80211
 4321                 int old_rate;
 4322 
 4323                 old_rate = ni->ni_vap->iv_bss->ni_txrate;
 4324 #endif
 4325                 txs.pktlen = skb->len;
 4326                 txs.flags |= IEEE80211_RATECTL_STATUS_PKTLEN;
 4327                 if (info->status.rates[0].count > 1) {
 4328                         txs.long_retries = info->status.rates[0].count - 1;     /* 1 + retries in drivers. */
 4329                         txs.flags |= IEEE80211_RATECTL_STATUS_LONG_RETRY;
 4330                 }
 4331 #if 0           /* Unused in net80211 currently. */
 4332                 /* XXX-BZ conver;t check .flags for MCS/VHT/.. */
 4333                 txs.final_rate = info->status.rates[0].idx;
 4334                 txs.flags |= IEEE80211_RATECTL_STATUS_FINAL_RATE;
 4335 #endif
 4336                 if (info->status.is_valid_ack_signal) {
 4337                         txs.rssi = info->status.ack_signal;             /* XXX-BZ CONVERT? */
 4338                         txs.flags |= IEEE80211_RATECTL_STATUS_RSSI;
 4339                 }
 4340 
 4341                 IMPROVE("only update of rate matches but that requires us to get a proper rate");
 4342                 ieee80211_ratectl_tx_complete(ni, &txs);
 4343                 ridx = ieee80211_ratectl_rate(ni->ni_vap->iv_bss, NULL, 0);
 4344 
 4345 #ifdef LINUXKPI_DEBUG_80211
 4346                 if (linuxkpi_debug_80211 & D80211_TRACE_TX) {
 4347                         printf("TX-RATE: %s: old %d new %d ridx %d, "
 4348                             "long_retries %d\n", __func__,
 4349                             old_rate, ni->ni_vap->iv_bss->ni_txrate,
 4350                             ridx, txs.long_retries);
 4351                 }
 4352 #endif
 4353         }
 4354 
 4355 #ifdef LINUXKPI_DEBUG_80211
 4356         if (linuxkpi_debug_80211 & D80211_TRACE_TX)
 4357                 printf("TX-STATUS: %s: hw %p skb %p status %d : flags %#x "
 4358                     "band %u hw_queue %u tx_time_est %d : "
 4359                     "rates [ %u %u %#x, %u %u %#x, %u %u %#x, %u %u %#x ] "
 4360                     "ack_signal %u ampdu_ack_len %u ampdu_len %u antenna %u "
 4361                     "tx_time %u is_valid_ack_signal %u "
 4362                     "status_driver_data [ %p %p ]\n",
 4363                     __func__, hw, skb, status, info->flags,
 4364                     info->band, info->hw_queue, info->tx_time_est,
 4365                     info->status.rates[0].idx, info->status.rates[0].count,
 4366                     info->status.rates[0].flags,
 4367                     info->status.rates[1].idx, info->status.rates[1].count,
 4368                     info->status.rates[1].flags,
 4369                     info->status.rates[2].idx, info->status.rates[2].count,
 4370                     info->status.rates[2].flags,
 4371                     info->status.rates[3].idx, info->status.rates[3].count,
 4372                     info->status.rates[3].flags,
 4373                     info->status.ack_signal, info->status.ampdu_ack_len,
 4374                     info->status.ampdu_len, info->status.antenna,
 4375                     info->status.tx_time, info->status.is_valid_ack_signal,
 4376                     info->status.status_driver_data[0],
 4377                     info->status.status_driver_data[1]);
 4378 #endif
 4379 
 4380         linuxkpi_ieee80211_free_txskb(hw, skb, status);
 4381 }
 4382 
 4383 /*
 4384  * This is an internal bandaid for the moment for the way we glue
 4385  * skbs and mbufs together for TX.  Once we have skbs backed by
 4386  * mbufs this should go away.
 4387  * This is a public function but kept on the private KPI (lkpi_)
 4388  * and is not exposed by a header file.
 4389  */
 4390 static void
 4391 lkpi_ieee80211_free_skb_mbuf(void *p)
 4392 {
 4393         struct ieee80211_node *ni;
 4394         struct mbuf *m;
 4395 
 4396         if (p == NULL)
 4397                 return;
 4398 
 4399         m = (struct mbuf *)p;
 4400         M_ASSERTPKTHDR(m);
 4401 
 4402         ni = m->m_pkthdr.PH_loc.ptr;
 4403         m->m_pkthdr.PH_loc.ptr = NULL;
 4404         if (ni != NULL)
 4405                 ieee80211_free_node(ni);
 4406         m_freem(m);
 4407 }
 4408 
 4409 void
 4410 linuxkpi_ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
 4411     struct delayed_work *w, int delay)
 4412 {
 4413         struct lkpi_hw *lhw;
 4414 
 4415         /* Need to make sure hw is in a stable (non-suspended) state. */
 4416         IMPROVE();
 4417 
 4418         lhw = HW_TO_LHW(hw);
 4419         queue_delayed_work(lhw->workq, w, delay);
 4420 }
 4421 
 4422 void
 4423 linuxkpi_ieee80211_queue_work(struct ieee80211_hw *hw,
 4424     struct work_struct *w)
 4425 {
 4426         struct lkpi_hw *lhw;
 4427 
 4428         /* Need to make sure hw is in a stable (non-suspended) state. */
 4429         IMPROVE();
 4430 
 4431         lhw = HW_TO_LHW(hw);
 4432         queue_work(lhw->workq, w);
 4433 }
 4434 
 4435 struct sk_buff *
 4436 linuxkpi_ieee80211_probereq_get(struct ieee80211_hw *hw, uint8_t *addr,
 4437     uint8_t *ssid, size_t ssid_len, size_t tailroom)
 4438 {
 4439         struct sk_buff *skb;
 4440         struct ieee80211_frame *wh;
 4441         uint8_t *p;
 4442         size_t len;
 4443 
 4444         len = sizeof(*wh);
 4445         len += 2 + ssid_len;
 4446 
 4447         skb = dev_alloc_skb(hw->extra_tx_headroom + len + tailroom);
 4448         if (skb == NULL)
 4449                 return (NULL);
 4450 
 4451         skb_reserve(skb, hw->extra_tx_headroom);
 4452 
 4453         wh = skb_put_zero(skb, sizeof(*wh));
 4454         wh->i_fc[0] = IEEE80211_FC0_VERSION_0;
 4455         wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_PROBE_REQ | IEEE80211_FC0_TYPE_MGT;
 4456         IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
 4457         IEEE80211_ADDR_COPY(wh->i_addr2, addr);
 4458         IEEE80211_ADDR_COPY(wh->i_addr3, ieee80211broadcastaddr);
 4459 
 4460         p = skb_put(skb, 2 + ssid_len);
 4461         *p++ = IEEE80211_ELEMID_SSID;
 4462         *p++ = ssid_len;
 4463         if (ssid_len > 0)
 4464                 memcpy(p, ssid, ssid_len);
 4465 
 4466         return (skb);
 4467 }
 4468 
 4469 struct sk_buff *
 4470 linuxkpi_ieee80211_pspoll_get(struct ieee80211_hw *hw,
 4471     struct ieee80211_vif *vif)
 4472 {
 4473         struct lkpi_vif *lvif;
 4474         struct ieee80211vap *vap;
 4475         struct sk_buff *skb;
 4476         struct ieee80211_frame_pspoll *psp;
 4477         uint16_t v;
 4478 
 4479         skb = dev_alloc_skb(hw->extra_tx_headroom + sizeof(*psp));
 4480         if (skb == NULL)
 4481                 return (NULL);
 4482 
 4483         skb_reserve(skb, hw->extra_tx_headroom);
 4484 
 4485         lvif = VIF_TO_LVIF(vif);
 4486         vap = LVIF_TO_VAP(lvif);
 4487 
 4488         psp = skb_put_zero(skb, sizeof(*psp));
 4489         psp->i_fc[0] = IEEE80211_FC0_VERSION_0;
 4490         psp->i_fc[0] |= IEEE80211_FC0_SUBTYPE_PS_POLL | IEEE80211_FC0_TYPE_CTL;
 4491         v = htole16(vif->bss_conf.aid | 1<<15 | 1<<16);
 4492         memcpy(&psp->i_aid, &v, sizeof(v));
 4493         IEEE80211_ADDR_COPY(psp->i_bssid, vap->iv_bss->ni_macaddr);
 4494         IEEE80211_ADDR_COPY(psp->i_ta, vif->addr);
 4495 
 4496         return (skb);
 4497 }
 4498 
 4499 struct sk_buff *
 4500 linuxkpi_ieee80211_nullfunc_get(struct ieee80211_hw *hw,
 4501     struct ieee80211_vif *vif, bool qos)
 4502 {
 4503         struct lkpi_vif *lvif;
 4504         struct ieee80211vap *vap;
 4505         struct sk_buff *skb;
 4506         struct ieee80211_frame *nullf;
 4507 
 4508         skb = dev_alloc_skb(hw->extra_tx_headroom + sizeof(*nullf));
 4509         if (skb == NULL)
 4510                 return (NULL);
 4511 
 4512         skb_reserve(skb, hw->extra_tx_headroom);
 4513 
 4514         lvif = VIF_TO_LVIF(vif);
 4515         vap = LVIF_TO_VAP(lvif);
 4516 
 4517         nullf = skb_put_zero(skb, sizeof(*nullf));
 4518         nullf->i_fc[0] = IEEE80211_FC0_VERSION_0;
 4519         nullf->i_fc[0] |= IEEE80211_FC0_SUBTYPE_NODATA | IEEE80211_FC0_TYPE_DATA;
 4520         nullf->i_fc[1] = IEEE80211_FC1_DIR_TODS;
 4521 
 4522         IEEE80211_ADDR_COPY(nullf->i_addr1, vap->iv_bss->ni_bssid);
 4523         IEEE80211_ADDR_COPY(nullf->i_addr2, vif->addr);
 4524         IEEE80211_ADDR_COPY(nullf->i_addr3, vap->iv_bss->ni_macaddr);
 4525 
 4526         return (skb);
 4527 }
 4528 
 4529 struct wireless_dev *
 4530 linuxkpi_ieee80211_vif_to_wdev(struct ieee80211_vif *vif)
 4531 {
 4532         struct lkpi_vif *lvif;
 4533 
 4534         lvif = VIF_TO_LVIF(vif);
 4535         return (&lvif->wdev);
 4536 }
 4537 
 4538 void
 4539 linuxkpi_ieee80211_connection_loss(struct ieee80211_vif *vif)
 4540 {
 4541         struct lkpi_vif *lvif;
 4542         struct ieee80211vap *vap;
 4543         enum ieee80211_state nstate;
 4544         int arg;
 4545 
 4546         lvif = VIF_TO_LVIF(vif);
 4547         vap = LVIF_TO_VAP(lvif);
 4548 
 4549         /*
 4550          * Go to init; otherwise we need to elaborately check state and
 4551          * handle accordingly, e.g., if in RUN we could call iv_bmiss.
 4552          * Let the statemachine handle all neccessary changes.
 4553          */
 4554         nstate = IEEE80211_S_INIT;
 4555         arg = 0;        /* Not a valid reason. */
 4556 
 4557 #ifdef LINUXKPI_DEBUG_80211
 4558         if (linuxkpi_debug_80211 & D80211_TRACE)
 4559                 ic_printf(vap->iv_ic, "%s: vif %p\n", __func__, vif);
 4560 #endif
 4561         ieee80211_new_state(vap, nstate, arg);
 4562 }
 4563 
 4564 void
 4565 linuxkpi_ieee80211_beacon_loss(struct ieee80211_vif *vif)
 4566 {
 4567         struct lkpi_vif *lvif;
 4568         struct ieee80211vap *vap;
 4569 
 4570         lvif = VIF_TO_LVIF(vif);
 4571         vap = LVIF_TO_VAP(lvif);
 4572 
 4573 #ifdef LINUXKPI_DEBUG_80211
 4574         if (linuxkpi_debug_80211 & D80211_TRACE || vap->iv_state != IEEE80211_S_RUN)
 4575                 ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s\n", __func__,
 4576                     vif, vap, ieee80211_state_name[vap->iv_state]);
 4577 #endif
 4578         ieee80211_beacon_miss(vap->iv_ic);
 4579 }
 4580 
 4581 /* -------------------------------------------------------------------------- */
 4582 
 4583 struct lkpi_cfg80211_bss {
 4584         u_int refcnt;
 4585         struct cfg80211_bss bss;
 4586 };
 4587 
 4588 struct lkpi_cfg80211_get_bss_iter_lookup {
 4589         struct wiphy *wiphy;
 4590         struct linuxkpi_ieee80211_channel *chan;
 4591         const uint8_t *bssid;
 4592         const uint8_t *ssid;
 4593         size_t ssid_len;
 4594         enum ieee80211_bss_type bss_type;
 4595         enum ieee80211_privacy privacy;
 4596 
 4597         /*
 4598          * Something to store a copy of the result as the net80211 scan cache
 4599          * is not refoucnted so a scan entry might go away any time.
 4600          */
 4601         bool match;
 4602         struct cfg80211_bss *bss;
 4603 };
 4604 
 4605 static void
 4606 lkpi_cfg80211_get_bss_iterf(void *arg, const struct ieee80211_scan_entry *se)
 4607 {
 4608         struct lkpi_cfg80211_get_bss_iter_lookup *lookup;
 4609         size_t ielen;
 4610 
 4611         lookup = arg;
 4612 
 4613         /* Do not try to find another match. */
 4614         if (lookup->match)
 4615                 return;
 4616 
 4617         /* Nothing to store result. */
 4618         if (lookup->bss == NULL)
 4619                 return;
 4620 
 4621         if (lookup->privacy != IEEE80211_PRIVACY_ANY) {
 4622                 /* if (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) */
 4623                 /* We have no idea what to compare to as the drivers only request ANY */
 4624                 return;
 4625         }
 4626 
 4627         if (lookup->bss_type != IEEE80211_BSS_TYPE_ANY) {
 4628                 /* if (se->se_capinfo & (IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS)) */
 4629                 /* We have no idea what to compare to as the drivers only request ANY */
 4630                 return;
 4631         }
 4632 
 4633         if (lookup->chan != NULL) {
 4634                 struct linuxkpi_ieee80211_channel *chan;
 4635 
 4636                 chan = linuxkpi_ieee80211_get_channel(lookup->wiphy,
 4637                     se->se_chan->ic_freq);
 4638                 if (chan == NULL || chan != lookup->chan)
 4639                         return;
 4640         }
 4641 
 4642         if (lookup->bssid && !IEEE80211_ADDR_EQ(lookup->bssid, se->se_bssid))
 4643                 return;
 4644 
 4645         if (lookup->ssid) {
 4646                 if (lookup->ssid_len != se->se_ssid[1] ||
 4647                     se->se_ssid[1] == 0)
 4648                         return;
 4649                 if (memcmp(lookup->ssid, se->se_ssid+2, lookup->ssid_len) != 0)
 4650                         return;
 4651         }
 4652 
 4653         ielen = se->se_ies.len;
 4654 
 4655         lookup->bss->ies = malloc(sizeof(*lookup->bss->ies) + ielen,
 4656             M_LKPI80211, M_NOWAIT | M_ZERO);
 4657         if (lookup->bss->ies == NULL)
 4658                 return;
 4659 
 4660         lookup->bss->ies->data = (uint8_t *)lookup->bss->ies + sizeof(*lookup->bss->ies);
 4661         lookup->bss->ies->len = ielen;
 4662         if (ielen)
 4663                 memcpy(lookup->bss->ies->data, se->se_ies.data, ielen);
 4664 
 4665         lookup->match = true;
 4666 }
 4667 
 4668 struct cfg80211_bss *
 4669 linuxkpi_cfg80211_get_bss(struct wiphy *wiphy, struct linuxkpi_ieee80211_channel *chan,
 4670     const uint8_t *bssid, const uint8_t *ssid, size_t ssid_len,
 4671     enum ieee80211_bss_type bss_type, enum ieee80211_privacy privacy)
 4672 {
 4673         struct lkpi_cfg80211_bss *lbss;
 4674         struct lkpi_cfg80211_get_bss_iter_lookup lookup;
 4675         struct lkpi_hw *lhw;
 4676         struct ieee80211vap *vap;
 4677 
 4678         lhw = wiphy_priv(wiphy);
 4679 
 4680         /* Let's hope we can alloc. */
 4681         lbss = malloc(sizeof(*lbss), M_LKPI80211, M_NOWAIT | M_ZERO);
 4682         if (lbss == NULL) {
 4683                 ic_printf(lhw->ic, "%s: alloc failed.\n", __func__);
 4684                 return (NULL);
 4685         }
 4686 
 4687         lookup.wiphy = wiphy;
 4688         lookup.chan = chan;
 4689         lookup.bssid = bssid;
 4690         lookup.ssid = ssid;
 4691         lookup.ssid_len = ssid_len;
 4692         lookup.bss_type = bss_type;
 4693         lookup.privacy = privacy;
 4694         lookup.match = false;
 4695         lookup.bss = &lbss->bss;
 4696 
 4697         IMPROVE("Iterate over all VAPs comparing perm_addr and addresses?");
 4698         vap = TAILQ_FIRST(&lhw->ic->ic_vaps);
 4699         ieee80211_scan_iterate(vap, lkpi_cfg80211_get_bss_iterf, &lookup);
 4700         if (!lookup.match) {
 4701                 free(lbss, M_LKPI80211);
 4702                 return (NULL);
 4703         }
 4704 
 4705         refcount_init(&lbss->refcnt, 1);
 4706         return (&lbss->bss);
 4707 }
 4708 
 4709 void
 4710 linuxkpi_cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss)
 4711 {
 4712         struct lkpi_cfg80211_bss *lbss;
 4713 
 4714         lbss = container_of(bss, struct lkpi_cfg80211_bss, bss);
 4715 
 4716         /* Free everything again on refcount ... */
 4717         if (refcount_release(&lbss->refcnt)) {
 4718                 free(lbss->bss.ies, M_LKPI80211);
 4719                 free(lbss, M_LKPI80211);
 4720         }
 4721 }
 4722 
 4723 void
 4724 linuxkpi_cfg80211_bss_flush(struct wiphy *wiphy)
 4725 {
 4726         struct lkpi_hw *lhw;
 4727         struct ieee80211com *ic;
 4728         struct ieee80211vap *vap;
 4729 
 4730         lhw = wiphy_priv(wiphy);
 4731         ic = lhw->ic;
 4732 
 4733         /*
 4734          * If we haven't called ieee80211_ifattach() yet
 4735          * or there is no VAP, there are no scans to flush.
 4736          */
 4737         if (ic == NULL ||
 4738             (lhw->sc_flags & LKPI_MAC80211_DRV_STARTED) == 0)
 4739                 return;
 4740 
 4741         /* Should only happen on the current one? Not seen it late enough. */
 4742         IEEE80211_LOCK(ic);
 4743         TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
 4744                 ieee80211_scan_flush(vap);
 4745         IEEE80211_UNLOCK(ic);
 4746 }
 4747 
 4748 /* -------------------------------------------------------------------------- */
 4749 
 4750 MODULE_VERSION(linuxkpi_wlan, 1);
 4751 MODULE_DEPEND(linuxkpi_wlan, linuxkpi, 1, 1, 1);
 4752 MODULE_DEPEND(linuxkpi_wlan, wlan, 1, 1, 1);

Cache object: fbeb6d01c6bd93080ba2365df2adbabb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.