On Wed, Jul 28, 2021 at 02:13:41PM +0200, Stefan Sperling wrote:
> On Mon, Jul 26, 2021 at 06:21:46PM +0200, Stefan Sperling wrote:
> > This patch implements support for new iwx(4) -63 firmware images
> > available in the iwx-firmware-20210512 package (via fw_update).
> > 
> > Please test this patch and report back. If testing works out well
> > then I will commit these changes to CVS incrementally. Thanks!
> > 
> > For those testing my iwx Tx agg patch: Please remove that patch first.
> > Tx agg will come back later. Getting new firmware images to work is more
> > important right now because these images contain fixes for fragattacks.
> 
> Several people have reported messages such as:
>   iwx0: unhandled firmware response 0xc2/0xc rx ring 63[255]
> 
> The 0xc2 response is a new notification from firmware (BAR_FRAME_RELEASE).
> This updated version of the patch adds support for this feature.

Did anyone test this patch on an AX201 device? I currently cannot
do tests on AX201 myself, unfortunately.

I know that AX200 cards are working fine.

Several people have reported back without mentioning their chipset.
Please be clear about which device you are testing. When in doubt,
include your dmesg.

Thanks!

> diff 54a415eecf0903b6663209706a0fc6e2e9d40044 refs/heads/iwxfw
> blob - 48bf14d7a8a421c6f1bf2b4bfc6c1792396b5400
> blob + 0b97503422759e3898791e31f9999f096d6ce9cb
> --- sys/dev/pci/if_iwx.c
> +++ sys/dev/pci/if_iwx.c
> @@ -232,6 +232,7 @@ const int iwx_mcs2ridx[] = {
>  };
>  
>  uint8_t      iwx_lookup_cmd_ver(struct iwx_softc *, uint8_t, uint8_t);
> +uint8_t      iwx_lookup_notif_ver(struct iwx_softc *, uint8_t, uint8_t);
>  int  iwx_is_mimo_ht_plcp(uint8_t);
>  int  iwx_is_mimo_mcs(int);
>  int  iwx_store_cscheme(struct iwx_softc *, uint8_t *, size_t);
> @@ -297,6 +298,8 @@ int       iwx_nic_rx_init(struct iwx_softc *);
>  int  iwx_nic_init(struct iwx_softc *);
>  int  iwx_enable_txq(struct iwx_softc *, int, int, int, int);
>  void iwx_post_alive(struct iwx_softc *);
> +int  iwx_schedule_session_protection(struct iwx_softc *, struct iwx_node *,
> +         uint32_t);
>  void iwx_protect_session(struct iwx_softc *, struct iwx_node *, uint32_t,
>           uint32_t);
>  void iwx_unprotect_session(struct iwx_softc *, struct iwx_node *);
> @@ -315,6 +318,8 @@ int       iwx_ampdu_rx_start(struct ieee80211com *, 
> struct i
>  void iwx_ampdu_rx_stop(struct ieee80211com *, struct ieee80211_node *,
>           uint8_t);
>  void iwx_rx_ba_session_expired(void *);
> +void iwx_rx_bar_frame_release(struct iwx_softc *, struct iwx_rx_packet *,
> +         struct iwx_rx_data *, struct mbuf_list *);
>  void iwx_reorder_timer_expired(void *);
>  void iwx_sta_rx_agg(struct iwx_softc *, struct ieee80211_node *, uint8_t,
>           uint16_t, uint16_t, int, int);
> @@ -356,6 +361,10 @@ void     iwx_rx_tx_cmd(struct iwx_softc *, struct 
> iwx_rx_p
>  void iwx_rx_bmiss(struct iwx_softc *, struct iwx_rx_packet *,
>           struct iwx_rx_data *);
>  int  iwx_binding_cmd(struct iwx_softc *, struct iwx_node *, uint32_t);
> +int  iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *, struct iwx_phy_ctxt *, 
> uint8_t,
> +         uint8_t, uint32_t);
> +int  iwx_phy_ctxt_cmd_v3(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t,
> +         uint8_t, uint32_t);
>  int  iwx_phy_ctxt_cmd_uhb(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t,
>           uint8_t, uint32_t, uint32_t);
>  int  iwx_phy_ctxt_cmd(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t,
> @@ -387,7 +396,16 @@ int      iwx_add_sta_cmd(struct iwx_softc *, struct 
> iwx_nod
>  int  iwx_add_aux_sta(struct iwx_softc *);
>  int  iwx_rm_sta_cmd(struct iwx_softc *, struct iwx_node *);
>  int  iwx_fill_probe_req(struct iwx_softc *, struct iwx_scan_probe_req *);
> +int  iwx_config_umac_scan_reduced(struct iwx_softc *);
>  int  iwx_config_umac_scan(struct iwx_softc *);
> +uint16_t iwx_scan_umac_flags_v2(struct iwx_softc *, int);
> +void iwx_scan_umac_dwell_v10(struct iwx_softc *,
> +         struct iwx_scan_general_params_v10 *, int);
> +void iwx_scan_umac_fill_general_p_v10(struct iwx_softc *,
> +         struct iwx_scan_general_params_v10 *, uint16_t, int);
> +void iwx_scan_umac_fill_ch_p_v6(struct iwx_softc *,
> +         struct iwx_scan_channel_params_v6 *, uint32_t, int, int);
> +int  iwx_umac_scan_v14(struct iwx_softc *, int);
>  int  iwx_umac_scan(struct iwx_softc *, int);
>  void iwx_mcc_update(struct iwx_softc *, struct iwx_mcc_chub_notif *);
>  uint8_t      iwx_ridx2rate(struct ieee80211_rateset *, int);
> @@ -490,6 +508,21 @@ iwx_lookup_cmd_ver(struct iwx_softc *sc, uint8_t grp, 
>       return IWX_FW_CMD_VER_UNKNOWN;
>  }
>  
> +uint8_t
> +iwx_lookup_notif_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd)
> +{
> +     const struct iwx_fw_cmd_version *entry;
> +     int i;
> +
> +     for (i = 0; i < sc->n_cmd_versions; i++) {
> +             entry = &sc->cmd_versions[i];
> +             if (entry->group == grp && entry->cmd == cmd)
> +                     return entry->notif_ver;
> +     }
> +
> +     return IWX_FW_CMD_VER_UNKNOWN;
> +}
> +
>  int
>  iwx_is_mimo_ht_plcp(uint8_t ht_plcp)
>  {
> @@ -924,7 +957,7 @@ iwx_firmware_store_section(struct iwx_softc *sc, enum 
>  
>  #define IWX_DEFAULT_SCAN_CHANNELS    40
>  /* Newer firmware might support more channels. Raise this value if needed. */
> -#define IWX_MAX_SCAN_CHANNELS                52 /* as of 8265-34 firmware 
> image */
> +#define IWX_MAX_SCAN_CHANNELS                67 /* as of iwx-cc-a0-62 
> firmware */
>  
>  struct iwx_tlv_calib_data {
>       uint32_t ucode_type;
> @@ -1304,6 +1337,8 @@ iwx_read_firmware(struct iwx_softc *sc)
>                       break;
>  
>               case IWX_UCODE_TLV_FW_FSEQ_VERSION:
> +             case IWX_UCODE_TLV_PHY_INTEGRATION_VERSION:
> +             case IWX_UCODE_TLV_FW_NUM_STATIONS:
>                       break;
>  
>               /* undocumented TLVs found in iwx-cc-a0-46 image */
> @@ -1317,6 +1352,13 @@ iwx_read_firmware(struct iwx_softc *sc)
>               case 0x1000002:
>                       break;
>  
> +             case IWX_UCODE_TLV_TYPE_DEBUG_INFO:
> +             case IWX_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
> +             case IWX_UCODE_TLV_TYPE_HCMD:
> +             case IWX_UCODE_TLV_TYPE_REGIONS:
> +             case IWX_UCODE_TLV_TYPE_TRIGGERS:
> +                     break;
> +
>               default:
>                       err = EINVAL;
>                       goto parse_out;
> @@ -2559,6 +2601,23 @@ out:
>       return err;
>  }
>  
> +int
> +iwx_schedule_session_protection(struct iwx_softc *sc, struct iwx_node *in,
> +    uint32_t duration)
> +{
> +     struct iwx_session_prot_cmd cmd = {
> +             .id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(in->in_id,
> +                 in->in_color)),
> +             .action = htole32(IWX_FW_CTXT_ACTION_ADD),
> +             .conf_id = htole32(IWX_SESSION_PROTECT_CONF_ASSOC),
> +             .duration_tu = htole32(duration * IEEE80211_DUR_TU),
> +     };
> +     uint32_t cmd_id;
> +
> +     cmd_id = iwx_cmd_id(IWX_SESSION_PROTECTION_CMD, IWX_MAC_CONF_GROUP, 0);
> +     return iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);
> +}
> +
>  void
>  iwx_protect_session(struct iwx_softc *sc, struct iwx_node *in,
>      uint32_t duration, uint32_t max_delay)
> @@ -2810,6 +2869,41 @@ iwx_rx_ba_session_expired(void *arg)
>  }
>  
>  void
> +iwx_rx_bar_frame_release(struct iwx_softc *sc, struct iwx_rx_packet *pkt,
> +    struct iwx_rx_data *data, struct mbuf_list *ml)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct ieee80211_node *ni = ic->ic_bss;
> +     struct iwx_bar_frame_release *release = (void *)data;
> +     struct iwx_reorder_buffer *buf;
> +     struct iwx_rxba_data *rxba;
> +     unsigned int baid, nssn, sta_id, tid;
> +
> +     if (iwx_rx_packet_payload_len(pkt) < sizeof(*release))
> +             return;
> +
> +     baid = (le32toh(release->ba_info) & IWX_BAR_FRAME_RELEASE_BAID_MASK) >>
> +         IWX_BAR_FRAME_RELEASE_BAID_SHIFT;
> +     if (baid == IWX_RX_REORDER_DATA_INVALID_BAID ||
> +         baid >= nitems(sc->sc_rxba_data))
> +             return;
> +
> +     rxba = &sc->sc_rxba_data[baid];
> +     if (rxba == NULL || rxba->baid == IWX_RX_REORDER_DATA_INVALID_BAID)
> +             return;
> +
> +     tid = le32toh(release->sta_tid) & IWX_BAR_FRAME_RELEASE_TID_MASK;
> +     sta_id = (le32toh(release->sta_tid) &
> +         IWX_BAR_FRAME_RELEASE_STA_MASK) >> IWX_BAR_FRAME_RELEASE_STA_SHIFT;
> +     if (tid != rxba->tid || rxba->sta_id != IWX_STATION_ID)
> +             return;
> +
> +     nssn = le32toh(release->ba_info) & IWX_BAR_FRAME_RELEASE_NSSN_MASK;
> +     buf = &rxba->reorder_buf;
> +     iwx_release_frames(sc, ni, rxba, buf, nssn, ml);
> +}
> +
> +void
>  iwx_reorder_timer_expired(void *arg)
>  {
>       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
> @@ -4416,9 +4510,8 @@ iwx_binding_cmd(struct iwx_softc *sc, struct iwx_node 
>  }
>  
>  int
> -iwx_phy_ctxt_cmd_uhb(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
> -    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,
> -    uint32_t apply_time)
> +iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
> +    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action)
>  {
>       struct ieee80211com *ic = &sc->sc_ic;
>       struct iwx_phy_context_cmd_uhb cmd;
> @@ -4429,8 +4522,13 @@ iwx_phy_ctxt_cmd_uhb(struct iwx_softc *sc, struct iwx_
>       cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id,
>           ctxt->color));
>       cmd.action = htole32(action);
> -     cmd.apply_time = htole32(apply_time);
>  
> +     if (IEEE80211_IS_CHAN_2GHZ(ctxt->channel) ||
> +         !isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT))
> +             cmd.lmac_id = htole32(IWX_LMAC_24G_INDEX);
> +     else
> +             cmd.lmac_id = htole32(IWX_LMAC_5G_INDEX);
> +
>       cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
>           IWX_PHY_BAND_24 : IWX_PHY_BAND_5;
>       cmd.ci.channel = htole32(ieee80211_chan2ieee(ic, chan));
> @@ -4440,25 +4538,96 @@ iwx_phy_ctxt_cmd_uhb(struct iwx_softc *sc, struct iwx_
>       idle_cnt = chains_static;
>       active_cnt = chains_dynamic;
>       cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
> -                                     IWX_PHY_RX_CHAIN_VALID_POS);
> +         IWX_PHY_RX_CHAIN_VALID_POS);
>       cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);
>       cmd.rxchain_info |= htole32(active_cnt <<
>           IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
> -     cmd.txchain_info = htole32(iwx_fw_valid_tx_ant(sc));
>  
>       return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
>  }
>  
>  int
> -iwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
> -    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,
> -    uint32_t apply_time)
> +iwx_phy_ctxt_cmd_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
> +    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action)
>  {
>       struct ieee80211com *ic = &sc->sc_ic;
>       struct iwx_phy_context_cmd cmd;
>       uint8_t active_cnt, idle_cnt;
>       struct ieee80211_channel *chan = ctxt->channel;
>  
> +     memset(&cmd, 0, sizeof(cmd));
> +     cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id,
> +         ctxt->color));
> +     cmd.action = htole32(action);
> +
> +     if (IEEE80211_IS_CHAN_2GHZ(ctxt->channel) ||
> +         !isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_CDB_SUPPORT))
> +             cmd.lmac_id = htole32(IWX_LMAC_24G_INDEX);
> +     else
> +             cmd.lmac_id = htole32(IWX_LMAC_5G_INDEX);
> +
> +     cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
> +         IWX_PHY_BAND_24 : IWX_PHY_BAND_5;
> +     cmd.ci.channel = ieee80211_chan2ieee(ic, chan);
> +     cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE20;
> +     cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
> +
> +     idle_cnt = chains_static;
> +     active_cnt = chains_dynamic;
> +     cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
> +         IWX_PHY_RX_CHAIN_VALID_POS);
> +     cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);
> +     cmd.rxchain_info |= htole32(active_cnt <<
> +         IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
> +
> +     return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
> +}
> +
> +int
> +iwx_phy_ctxt_cmd_uhb(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
> +    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,
> +    uint32_t apply_time)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct iwx_phy_context_cmd_uhb_v1 cmd;
> +     uint8_t active_cnt, idle_cnt;
> +     struct ieee80211_channel *chan = ctxt->channel;
> +
> +     memset(&cmd, 0, sizeof(cmd));
> +     cmd.id_and_color = htole32(IWX_FW_CMD_ID_AND_COLOR(ctxt->id,
> +         ctxt->color));
> +     cmd.action = htole32(action);
> +     cmd.apply_time = htole32(apply_time);
> +
> +     cmd.ci.band = IEEE80211_IS_CHAN_2GHZ(chan) ?
> +         IWX_PHY_BAND_24 : IWX_PHY_BAND_5;
> +     cmd.ci.channel = htole32(ieee80211_chan2ieee(ic, chan));
> +     cmd.ci.width = IWX_PHY_VHT_CHANNEL_MODE20;
> +     cmd.ci.ctrl_pos = IWX_PHY_VHT_CTRL_POS_1_BELOW;
> +
> +     idle_cnt = chains_static;
> +     active_cnt = chains_dynamic;
> +     cmd.rxchain_info = htole32(iwx_fw_valid_rx_ant(sc) <<
> +                                     IWX_PHY_RX_CHAIN_VALID_POS);
> +     cmd.rxchain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS);
> +     cmd.rxchain_info |= htole32(active_cnt <<
> +         IWX_PHY_RX_CHAIN_MIMO_CNT_POS);
> +     cmd.txchain_info = htole32(iwx_fw_valid_tx_ant(sc));
> +
> +     return iwx_send_cmd_pdu(sc, IWX_PHY_CONTEXT_CMD, 0, sizeof(cmd), &cmd);
> +}
> +
> +int
> +iwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt,
> +    uint8_t chains_static, uint8_t chains_dynamic, uint32_t action,
> +    uint32_t apply_time)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct iwx_phy_context_cmd_v1 cmd;
> +     uint8_t active_cnt, idle_cnt;
> +     struct ieee80211_channel *chan = ctxt->channel;
> +     int cmdver;
> +
>       /*
>        * Intel increased the size of the fw_channel_info struct and neglected
>        * to bump the phy_context_cmd struct, which contains an fw_channel_info
> @@ -4466,6 +4635,17 @@ iwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_
>        * To keep things simple we use a separate function to handle the larger
>        * variant of the phy context command.
>        */
> +     cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_PHY_CONTEXT_CMD);
> +     if (cmdver == 3) {
> +             /* Version 3 differs in the "data" portion of the command. */
> +             if (isset(sc->sc_enabled_capa,
> +                 IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS)) {
> +                     return iwx_phy_ctxt_cmd_uhb_v3(sc, ctxt, chains_static,
> +                         chains_dynamic, action);
> +             }
> +             return iwx_phy_ctxt_cmd_v3(sc, ctxt, chains_static,
> +                 chains_dynamic, action);
> +     }
>       if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS))
>               return iwx_phy_ctxt_cmd_uhb(sc, ctxt, chains_static,
>                   chains_dynamic, action, apply_time);
> @@ -4542,15 +4722,24 @@ iwx_send_cmd(struct iwx_softc *sc, struct iwx_host_cmd
>       desc = &ring->desc[idx];
>       txdata = &ring->data[idx];
>  
> +     /*
> +      * XXX Intel inside (tm)
> +      * Firmware API versions >= 50 reject old-style commands in
> +      * group 0 with a "BAD_COMMAND" firmware error. We must pretend
> +      * that such commands were in the LONG_GROUP instead in order
> +      * for firmware to accept them.
> +      */
> +     if (iwx_cmd_groupid(code) == 0) {
> +             code = IWX_WIDE_ID(IWX_LONG_GROUP, code);
> +             txdata->flags |= IWX_TXDATA_FLAG_CMD_IS_NARROW;
> +     } else
> +             txdata->flags &= ~IWX_TXDATA_FLAG_CMD_IS_NARROW;
> +
>       group_id = iwx_cmd_groupid(code);
> -     if (group_id != 0) {
> -             hdrlen = sizeof(cmd->hdr_wide);
> -             datasz = sizeof(cmd->data_wide);
> -     } else {
> -             hdrlen = sizeof(cmd->hdr);
> -             datasz = sizeof(cmd->data);
> -     }
>  
> +     hdrlen = sizeof(cmd->hdr_wide);
> +     datasz = sizeof(cmd->data_wide);
> +
>       if (paylen > datasz) {
>               /* Command is too large to fit in pre-allocated space. */
>               size_t totlen = hdrlen + paylen;
> @@ -4583,21 +4772,14 @@ iwx_send_cmd(struct iwx_softc *sc, struct iwx_host_cmd
>               paddr = txdata->cmd_paddr;
>       }
>  
> -     if (group_id != 0) {
> -             cmd->hdr_wide.opcode = iwx_cmd_opcode(code);
> -             cmd->hdr_wide.group_id = group_id;
> -             cmd->hdr_wide.qid = ring->qid;
> -             cmd->hdr_wide.idx = idx;
> -             cmd->hdr_wide.length = htole16(paylen);
> -             cmd->hdr_wide.version = iwx_cmd_version(code);
> -             data = cmd->data_wide;
> -     } else {
> -             cmd->hdr.code = code;
> -             cmd->hdr.flags = 0;
> -             cmd->hdr.qid = ring->qid;
> -             cmd->hdr.idx = idx;
> -             data = cmd->data;
> -     }
> +     memset(cmd, 0, sizeof(*cmd));
> +     cmd->hdr_wide.opcode = iwx_cmd_opcode(code);
> +     cmd->hdr_wide.group_id = group_id;
> +     cmd->hdr_wide.qid = ring->qid;
> +     cmd->hdr_wide.idx = idx;
> +     cmd->hdr_wide.length = htole16(paylen);
> +     cmd->hdr_wide.version = iwx_cmd_version(code);
> +     data = cmd->data_wide;
>  
>       for (i = 0, off = 0; i < nitems(hcmd->data); i++) {
>               if (hcmd->len[i] == 0)
> @@ -4607,10 +4789,17 @@ iwx_send_cmd(struct iwx_softc *sc, struct iwx_host_cmd
>       }
>       KASSERT(off == paylen);
>  
> -     desc->tbs[0].tb_len = htole16(hdrlen + paylen);
> -     addr = htole64((uint64_t)paddr);
> +     desc->tbs[0].tb_len = htole16(MIN(hdrlen + paylen, IWX_FIRST_TB_SIZE));
> +     addr = htole64(paddr);
>       memcpy(&desc->tbs[0].addr, &addr, sizeof(addr));
> -     desc->num_tbs = 1;
> +     if (hdrlen + paylen > IWX_FIRST_TB_SIZE) {
> +             desc->tbs[1].tb_len = htole16(hdrlen + paylen -
> +                 IWX_FIRST_TB_SIZE);
> +             addr = htole64(paddr + IWX_FIRST_TB_SIZE);
> +             memcpy(&desc->tbs[1].addr, &addr, sizeof(addr));
> +             desc->num_tbs = htole16(2);
> +     } else
> +             desc->num_tbs = htole16(1);
>  
>       if (paylen > datasz) {
>               bus_dmamap_sync(sc->sc_dmat, txdata->map, 0,
> @@ -4874,7 +5063,7 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ie
>        * Tx aggregation will require additional queues (one queue per TID
>        * for which aggregation is enabled) but we do not implement this yet.
>        */
> -     ring = &sc->txq[ac + IWX_DQA_AUX_QUEUE + 1];
> +     ring = &sc->txq[ac + sc->first_data_qid];
>       desc = &ring->desc[ring->cur];
>       memset(desc, 0, sizeof(*desc));
>       data = &ring->data[ring->cur];
> @@ -5262,7 +5451,16 @@ iwx_add_aux_sta(struct iwx_softc *sc)
>       struct iwx_add_sta_cmd cmd;
>       int err, qid = IWX_DQA_AUX_QUEUE;
>       uint32_t status;
> +     uint8_t cmdver;
>  
> +     /*
> +      * ADD_STA command version >= 12 implies that firmware uses
> +      * an internal AUX station for scanning.
> +      */
> +     cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_ADD_STA);
> +     if (cmdver != IWX_FW_CMD_VER_UNKNOWN && cmdver >= 12)
> +             return 0;
> +
>       memset(&cmd, 0, sizeof(cmd));
>       cmd.sta_id = IWX_AUX_STA_ID;
>       cmd.station_type = IWX_STA_AUX_ACTIVITY;
> @@ -5304,7 +5502,8 @@ iwx_rm_sta_cmd(struct iwx_softc *sc, struct iwx_node *
>  
>  uint8_t
>  iwx_umac_scan_fill_channels(struct iwx_softc *sc,
> -    struct iwx_scan_channel_cfg_umac *chan, int n_ssids, int bgscan)
> +    struct iwx_scan_channel_cfg_umac *chan, size_t chan_nitems,
> +    int n_ssids, int bgscan)
>  {
>       struct ieee80211com *ic = &sc->sc_ic;
>       struct ieee80211_channel *c;
> @@ -5312,6 +5511,7 @@ iwx_umac_scan_fill_channels(struct iwx_softc *sc,
>  
>       for (nchan = 0, c = &ic->ic_channels[1];
>           c <= &ic->ic_channels[IEEE80211_CHAN_MAX] &&
> +         nchan < chan_nitems &&
>           nchan < sc->sc_capa_n_scan_channels;
>           c++) {
>               uint8_t channel_num;
> @@ -5460,10 +5660,48 @@ iwx_fill_probe_req(struct iwx_softc *sc, struct iwx_sc
>  }
>  
>  int
> +iwx_config_umac_scan_reduced(struct iwx_softc *sc)
> +{
> +     struct iwx_scan_config scan_cfg;
> +     struct iwx_host_cmd hcmd = {
> +             .id = iwx_cmd_id(IWX_SCAN_CFG_CMD, IWX_LONG_GROUP, 0),
> +             .len[0] = sizeof(scan_cfg),
> +             .data[0] = &scan_cfg,
> +             .flags = 0,
> +     };
> +     int cmdver;
> +
> +     memset(&scan_cfg, 0, sizeof(scan_cfg));
> +
> +     /*
> +      * ADD_STA command version >= 12 implies that firmware uses
> +      * an internal AUX station for scanning.
> +      */
> +     cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_ADD_STA);
> +     if (cmdver == IWX_FW_CMD_VER_UNKNOWN || cmdver < 12)
> +             scan_cfg.bcast_sta_id = IWX_AUX_STA_ID;
> +     else {
> +             /*
> +              * SCAN_CFG version >= 5 implies that the broadcast
> +              * STA ID field is deprecated.
> +              */
> +             cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP,
> +                 IWX_SCAN_CFG_CMD);
> +             if (cmdver == IWX_FW_CMD_VER_UNKNOWN || cmdver < 5)
> +                     scan_cfg.bcast_sta_id = 0xff;
> +     }
> +
> +     scan_cfg.tx_chains = htole32(iwx_fw_valid_tx_ant(sc));
> +     scan_cfg.rx_chains = htole32(iwx_fw_valid_rx_ant(sc));
> +
> +     return iwx_send_cmd(sc, &hcmd);
> +}
> +
> +int
>  iwx_config_umac_scan(struct iwx_softc *sc)
>  {
>       struct ieee80211com *ic = &sc->sc_ic;
> -     struct iwx_scan_config *scan_config;
> +     struct iwx_scan_config_v2 *scan_config;
>       int err, nchan;
>       size_t cmd_size;
>       struct ieee80211_channel *c;
> @@ -5479,6 +5717,9 @@ iwx_config_umac_scan(struct iwx_softc *sc)
>           IWX_SCAN_CONFIG_RATE_36M | IWX_SCAN_CONFIG_RATE_48M |
>           IWX_SCAN_CONFIG_RATE_54M);
>  
> +     if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_REDUCED_SCAN_CONFIG))
> +             return iwx_config_umac_scan_reduced(sc);
> +
>       cmd_size = sizeof(*scan_config) + sc->sc_capa_n_scan_channels;
>  
>       scan_config = malloc(cmd_size, M_DEVBUF, M_WAIT | M_CANFAIL | M_ZERO);
> @@ -5589,6 +5830,25 @@ iwx_get_scan_req_umac_data(struct iwx_softc *sc, struc
>  
>  }
>  
> +uint16_t
> +iwx_scan_umac_flags_v2(struct iwx_softc *sc, int bgscan)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     uint16_t flags = 0;
> +
> +     if (ic->ic_des_esslen == 0)
> +             flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;
> +
> +     flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL;
> +     flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_NTFY_ITER_COMPLETE;
> +     flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL;
> +
> +     return flags;
> +}
> +
> +#define IWX_SCAN_DWELL_ACTIVE                10
> +#define IWX_SCAN_DWELL_PASSIVE               110
> +
>  /* adaptive dwell max budget time [TU] for full scan */
>  #define IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
>  /* adaptive dwell max budget time [TU] for directed scan */
> @@ -5599,8 +5859,145 @@ iwx_get_scan_req_umac_data(struct iwx_softc *sc, struc
>  #define IWX_SCAN_ADWELL_DEFAULT_LB_N_APS 2
>  /* adaptive dwell default APs number in social channels (1, 6, 11) */
>  #define IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10
> +/* adaptive dwell number of APs override for p2p friendly GO channels */
> +#define IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY 10
> +/* adaptive dwell number of APs override for social channels */
> +#define IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS 2
>  
> +void
> +iwx_scan_umac_dwell_v10(struct iwx_softc *sc,
> +    struct iwx_scan_general_params_v10 *general_params, int bgscan)
> +{
> +     uint32_t suspend_time, max_out_time;
> +     uint8_t active_dwell, passive_dwell;
> +
> +     active_dwell = IWX_SCAN_DWELL_ACTIVE;
> +     passive_dwell = IWX_SCAN_DWELL_PASSIVE;
> +
> +     general_params->adwell_default_social_chn =
> +             IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL;
> +     general_params->adwell_default_2g = IWX_SCAN_ADWELL_DEFAULT_LB_N_APS;
> +     general_params->adwell_default_5g = IWX_SCAN_ADWELL_DEFAULT_HB_N_APS;
> +
> +     if (bgscan)
> +             general_params->adwell_max_budget =
> +                     htole16(IWX_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);
> +     else
> +             general_params->adwell_max_budget =
> +                     htole16(IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN);
> +
> +     general_params->scan_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);
> +     if (bgscan) {
> +             max_out_time = htole32(120);
> +             suspend_time = htole32(120);
> +     } else {
> +             max_out_time = htole32(0);
> +             suspend_time = htole32(0);
> +     }
> +     general_params->max_out_of_time[IWX_SCAN_LB_LMAC_IDX] =
> +             htole32(max_out_time);
> +     general_params->suspend_time[IWX_SCAN_LB_LMAC_IDX] =
> +             htole32(suspend_time);
> +     general_params->max_out_of_time[IWX_SCAN_HB_LMAC_IDX] =
> +             htole32(max_out_time);
> +     general_params->suspend_time[IWX_SCAN_HB_LMAC_IDX] =
> +             htole32(suspend_time);
> +
> +     general_params->active_dwell[IWX_SCAN_LB_LMAC_IDX] = active_dwell;
> +     general_params->passive_dwell[IWX_SCAN_LB_LMAC_IDX] = passive_dwell;
> +     general_params->active_dwell[IWX_SCAN_HB_LMAC_IDX] = active_dwell;
> +     general_params->passive_dwell[IWX_SCAN_HB_LMAC_IDX] = passive_dwell;
> +}
> +
> +void
> +iwx_scan_umac_fill_general_p_v10(struct iwx_softc *sc,
> +    struct iwx_scan_general_params_v10 *gp, uint16_t gen_flags, int bgscan)
> +{
> +     iwx_scan_umac_dwell_v10(sc, gp, bgscan);
> +
> +     gp->flags = htole16(gen_flags);
> +
> +     if (gen_flags & IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1)
> +             gp->num_of_fragments[IWX_SCAN_LB_LMAC_IDX] = 3;
> +     if (gen_flags & IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)
> +             gp->num_of_fragments[IWX_SCAN_HB_LMAC_IDX] = 3;
> +
> +     gp->scan_start_mac_id = 0;
> +}
> +
> +void
> +iwx_scan_umac_fill_ch_p_v6(struct iwx_softc *sc,
> +    struct iwx_scan_channel_params_v6 *cp, uint32_t channel_cfg_flags,
> +    int n_ssid, int bgscan)
> +{
> +     cp->flags = IWX_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER;
> +
> +     cp->count = iwx_umac_scan_fill_channels(sc, cp->channel_config,
> +         nitems(cp->channel_config), n_ssid, bgscan);
> +
> +     cp->n_aps_override[0] = IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY;
> +     cp->n_aps_override[1] = IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS;
> +}
> +
>  int
> +iwx_umac_scan_v14(struct iwx_softc *sc, int bgscan)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct iwx_host_cmd hcmd = {
> +             .id = iwx_cmd_id(IWX_SCAN_REQ_UMAC, IWX_LONG_GROUP, 0),
> +             .len = { 0, },
> +             .data = { NULL, },
> +             .flags = 0,
> +     };
> +     struct iwx_scan_req_umac_v14 *cmd;
> +     struct iwx_scan_req_params_v14 *scan_p;
> +     int err, async = bgscan, n_ssid = 0;
> +     uint16_t gen_flags;
> +     uint32_t bitmap_ssid = 0;
> +
> +     cmd = malloc(sizeof(*cmd), M_DEVBUF,
> +         (async ? M_NOWAIT : M_WAIT) | M_CANFAIL | M_ZERO);
> +     if (cmd == NULL)
> +             return ENOMEM;
> +
> +     scan_p = &cmd->scan_params;
> +
> +     cmd->ooc_priority = htole32(IWX_SCAN_PRIORITY_EXT_6);
> +     cmd->uid = htole32(0);
> +
> +     gen_flags = iwx_scan_umac_flags_v2(sc, bgscan);
> +     iwx_scan_umac_fill_general_p_v10(sc, &scan_p->general_params,
> +         gen_flags, bgscan);
> +
> +     scan_p->periodic_params.schedule[0].interval = htole16(0);
> +     scan_p->periodic_params.schedule[0].iter_count = 1;
> +
> +     err = iwx_fill_probe_req(sc, &scan_p->probe_params.preq);
> +     if (err)
> +             return err;
> +
> +     if (ic->ic_des_esslen != 0) {
> +             scan_p->probe_params.direct_scan[0].id = IEEE80211_ELEMID_SSID;
> +             scan_p->probe_params.direct_scan[0].len = ic->ic_des_esslen;
> +             memcpy(scan_p->probe_params.direct_scan[0].ssid,
> +                 ic->ic_des_essid, ic->ic_des_esslen);
> +             bitmap_ssid |= (1 << 0);
> +             n_ssid = 1;
> +     }
> +
> +     iwx_scan_umac_fill_ch_p_v6(sc, &scan_p->channel_params, bitmap_ssid,
> +         n_ssid, bgscan);
> +
> +     hcmd.len[0] = sizeof(*cmd);
> +     hcmd.data[0] = (void *)cmd;
> +     hcmd.flags |= async ? IWX_CMD_ASYNC : 0;
> +
> +     err = iwx_send_cmd(sc, &hcmd);
> +     free(cmd, M_DEVBUF, sizeof(*cmd));
> +     return err;
> +}
> +
> +int
>  iwx_umac_scan(struct iwx_softc *sc, int bgscan)
>  {
>       struct ieee80211com *ic = &sc->sc_ic;
> @@ -5617,7 +6014,12 @@ iwx_umac_scan(struct iwx_softc *sc, int bgscan)
>       struct iwx_scan_umac_chan_param *chanparam;
>       size_t req_len;
>       int err, async = bgscan;
> +     int cmdver;
>  
> +     cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_SCAN_REQ_UMAC);
> +     if (cmdver == 14)
> +             return iwx_umac_scan_v14(sc, bgscan);
> +
>       req_len = iwx_umac_scan_size(sc);
>       if ((req_len < IWX_SCAN_REQ_UMAC_SIZE_V1 +
>           sizeof(struct iwx_scan_req_umac_tail_v1)) ||
> @@ -5690,6 +6092,7 @@ iwx_umac_scan(struct iwx_softc *sc, int bgscan)
>       chanparam = iwx_get_scan_req_umac_chan_param(sc, req);
>       chanparam->count = iwx_umac_scan_fill_channels(sc,
>           (struct iwx_scan_channel_cfg_umac *)cmd_data,
> +         sc->sc_capa_n_scan_channels,
>           ic->ic_des_esslen != 0, bgscan);
>       chanparam->flags = 0;
>  
> @@ -6241,19 +6644,31 @@ iwx_scan_abort(struct iwx_softc *sc)
>  int
>  iwx_enable_data_tx_queues(struct iwx_softc *sc)
>  {
> -     int err, ac;
> +     int err, ac, cmdver;
>  
> +     /*
> +      * ADD_STA command version >= 12 implies that firmware uses
> +      * an internal AUX station for scanning. We do not configure
> +      * an AUX Tx queue in this case and data queue indices assigned
> +      * by firmware shift upwards accordingly.
> +      */
> +     cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_ADD_STA);
> +     if (cmdver != IWX_FW_CMD_VER_UNKNOWN && cmdver >= 12)
> +             sc->first_data_qid = IWX_DQA_CMD_QUEUE + 1;
> +     else
> +             sc->first_data_qid = IWX_DQA_AUX_QUEUE + 1;
> +
>       for (ac = 0; ac < EDCA_NUM_AC; ac++) {
> -             int qid = ac + IWX_DQA_AUX_QUEUE + 1;
> +             int qid = ac + sc->first_data_qid;
>               /*
>                * Regular data frames use the "MGMT" TID and queue.
>                * Other TIDs and queues are reserved for frame aggregation.
>                */
> -             err = iwx_enable_txq(sc, IWX_STATION_ID, qid, IWX_TID_NON_QOS,
> +             err = iwx_enable_txq(sc, IWX_STATION_ID, qid, IWX_MGMT_TID,
>                   IWX_TX_RING_COUNT);
>               if (err) {
>                       printf("%s: could not enable Tx queue %d (error %d)\n",
> -                         DEVNAME(sc), ac, err);
> +                         DEVNAME(sc), qid, err);
>                       return err;
>               }
>       }
> @@ -6302,10 +6717,17 @@ iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in)
>       struct ieee80211_rateset *rs = &ni->ni_rates;
>       struct iwx_tlc_config_cmd cfg_cmd;
>       uint32_t cmd_id;
> -     int i;
> +     int i, cmdver;
> +     size_t cmd_size = sizeof(cfg_cmd);
>  
>       memset(&cfg_cmd, 0, sizeof(cfg_cmd));
>  
> +     /* In old versions of the API the struct is 4 bytes smaller */
> +     cmdver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP,
> +         IWX_TLC_MNG_CONFIG_CMD);
> +     if (cmdver == IWX_FW_CMD_VER_UNKNOWN || cmdver < 3)
> +             cmd_size -= sizeof(uint32_t);
> +
>       for (i = 0; i < rs->rs_nrates; i++) {
>               uint8_t rval = rs->rs_rates[i] & IEEE80211_RATE_VAL;
>               int idx = iwx_rs_rval2idx(rval);
> @@ -6331,8 +6753,7 @@ iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in)
>               cfg_cmd.sgi_ch_width_supp = (1 << IWX_TLC_MNG_CH_WIDTH_20MHZ);
>  
>       cmd_id = iwx_cmd_id(IWX_TLC_MNG_CONFIG_CMD, IWX_DATA_PATH_GROUP, 0);
> -     return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC, sizeof(cfg_cmd),
> -         &cfg_cmd);
> +     return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC, cmd_size, &cfg_cmd);
>  }
>  
>  void
> @@ -6488,9 +6909,12 @@ iwx_auth(struct iwx_softc *sc)
>               duration = in->in_ni.ni_intval * 2;
>       else
>               duration = IEEE80211_DUR_TU; 
> -     iwx_protect_session(sc, in, duration, in->in_ni.ni_intval / 2);
> +     if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_SESSION_PROT_CMD))
> +             err = iwx_schedule_session_protection(sc, in, duration);
> +     else
> +             iwx_protect_session(sc, in, duration, in->in_ni.ni_intval / 2);
>  
> -     return 0;
> +     return err;
>  
>  rm_sta:
>       if (generation == sc->sc_generation) {
> @@ -8073,6 +8497,19 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *d
>               if (!iwx_rx_pkt_valid(pkt))
>                       break;
>  
> +             /*
> +              * XXX Intel inside (tm)
> +              * Any commands in the LONG_GROUP could actually be in the
> +              * LEGACY group. Firmware API versions >= 50 reject commands
> +              * in group 0, forcing us to use this hack.
> +              */
> +             if (iwx_cmd_groupid(code) == IWX_LONG_GROUP) {
> +                     struct iwx_tx_ring *ring = &sc->txq[qid];
> +                     struct iwx_tx_data *txdata = &ring->data[idx];
> +                     if (txdata->flags & IWX_TXDATA_FLAG_CMD_IS_NARROW)
> +                             code = iwx_cmd_opcode(code);
> +             }
> +
>               len = sizeof(pkt->len_n_flags) + iwx_rx_packet_len(pkt);
>               if (len < sizeof(pkt->hdr) ||
>                   len > (IWX_RBUF_SIZE - offset - minsz))
> @@ -8124,6 +8561,10 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *d
>                       break;
>               }
>  
> +             case IWX_BAR_FRAME_RELEASE:
> +                     iwx_rx_bar_frame_release(sc, pkt, data, ml);
> +                     break;
> +
>               case IWX_TX_CMD:
>                       iwx_rx_tx_cmd(sc, pkt, data);
>                       break;
> @@ -8137,9 +8578,37 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *d
>  
>               case IWX_ALIVE: {
>                       struct iwx_alive_resp_v4 *resp4;
> +                     struct iwx_alive_resp_v5 *resp5;
>  
>                       DPRINTF(("%s: firmware alive\n", __func__));
> -                     if (iwx_rx_packet_payload_len(pkt) == sizeof(*resp4)) {
> +                     sc->sc_uc.uc_ok = 0;
> +
> +                     /*
> +                      * For v5 and above, we can check the version, for older
> +                      * versions we need to check the size.
> +                      */
> +                      if (iwx_lookup_notif_ver(sc, IWX_LEGACY_GROUP,
> +                         IWX_ALIVE) == 5) {
> +                             SYNC_RESP_STRUCT(resp5, pkt);
> +                             if (iwx_rx_packet_payload_len(pkt) !=
> +                                 sizeof(*resp5)) {
> +                                     sc->sc_uc.uc_intr = 1;
> +                                     wakeup(&sc->sc_uc);
> +                                     break;
> +                             }
> +                             sc->sc_uc.uc_lmac_error_event_table[0] = 
> le32toh(
> +                                 
> resp5->lmac_data[0].dbg_ptrs.error_event_table_ptr);
> +                             sc->sc_uc.uc_lmac_error_event_table[1] = 
> le32toh(
> +                                 
> resp5->lmac_data[1].dbg_ptrs.error_event_table_ptr);
> +                             sc->sc_uc.uc_log_event_table = le32toh(
> +                                 
> resp5->lmac_data[0].dbg_ptrs.log_event_table_ptr);
> +                             sc->sched_base = le32toh(
> +                                 resp5->lmac_data[0].dbg_ptrs.scd_base_ptr);
> +                             sc->sc_uc.uc_umac_error_event_table = le32toh(
> +                                 resp5->umac_data.dbg_ptrs.error_info_addr);
> +                             if (resp5->status == IWX_ALIVE_STATUS_OK)
> +                                     sc->sc_uc.uc_ok = 1;
> +                     } else if (iwx_rx_packet_payload_len(pkt) == 
> sizeof(*resp4)) {
>                               SYNC_RESP_STRUCT(resp4, pkt);
>                               sc->sc_uc.uc_lmac_error_event_table[0] = 
> le32toh(
>                                   
> resp4->lmac_data[0].dbg_ptrs.error_event_table_ptr);
> @@ -8153,8 +8622,6 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *d
>                                   resp4->umac_data.dbg_ptrs.error_info_addr);
>                               if (resp4->status == IWX_ALIVE_STATUS_OK)
>                                       sc->sc_uc.uc_ok = 1;
> -                             else
> -                                     sc->sc_uc.uc_ok = 0;
>                       }
>  
>                       sc->sc_uc.uc_intr = 1;
> @@ -8189,6 +8656,8 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *d
>                       break;
>               }
>  
> +             case IWX_WIDE_ID(IWX_MAC_CONF_GROUP,
> +                 IWX_SESSION_PROTECTION_CMD):
>               case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP,
>                   IWX_NVM_GET_INFO):
>               case IWX_ADD_STA_KEY:
> @@ -8288,6 +8757,10 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *d
>                       break;
>               }
>  
> +             case IWX_WIDE_ID(IWX_MAC_CONF_GROUP,
> +                 IWX_SESSION_PROTECTION_NOTIF):
> +                     break;
> +
>               case IWX_WIDE_ID(IWX_SYSTEM_GROUP,
>                   IWX_FSEQ_VER_MISMATCH_NOTIFICATION):
>                   break;
> @@ -8844,7 +9317,7 @@ iwx_attach(struct device *parent, struct device *self,
>  
>       switch (PCI_PRODUCT(pa->pa_id)) {
>       case PCI_PRODUCT_INTEL_WL_22500_1:
> -             sc->sc_fwname = "iwx-cc-a0-48";
> +             sc->sc_fwname = "iwx-cc-a0-63";
>               sc->sc_device_family = IWX_DEVICE_FAMILY_22000;
>               sc->sc_fwdmasegsz = IWX_FWDMASEGSZ_8000;
>               sc->sc_integrated = 1;
> @@ -8862,7 +9335,7 @@ iwx_attach(struct device *parent, struct device *self,
>                       return;
>               }
>  
> -             sc->sc_fwname = "iwx-QuZ-a0-hr-b0-48";
> +             sc->sc_fwname = "iwx-QuZ-a0-hr-b0-63";
>               sc->sc_device_family = IWX_DEVICE_FAMILY_22000;
>               sc->sc_fwdmasegsz = IWX_FWDMASEGSZ_8000;
>               sc->sc_integrated = 1;
> @@ -8873,7 +9346,7 @@ iwx_attach(struct device *parent, struct device *self,
>               sc->sc_uhb_supported = 0;
>               break;
>       case PCI_PRODUCT_INTEL_WL_22500_4:
> -         sc->sc_fwname = "iwx-Qu-c0-hr-b0-48";
> +         sc->sc_fwname = "iwx-Qu-c0-hr-b0-63";
>           sc->sc_device_family = IWX_DEVICE_FAMILY_22000;
>           sc->sc_fwdmasegsz = IWX_FWDMASEGSZ_8000;
>           sc->sc_integrated = 1;
> blob - 55422b8d6961837cf9281b56c8671b1aea163b57
> blob + d7eda7cb6a3e1a7d8d3b605908a7185a8d8dd245
> --- sys/dev/pci/if_iwxreg.h
> +++ sys/dev/pci/if_iwxreg.h
> @@ -918,11 +918,27 @@ enum msix_ivar_for_cause {
>  #define IWX_UCODE_TLV_API_NAN2_VER2          31
>  #define IWX_UCODE_TLV_API_ADAPTIVE_DWELL     32
>  #define IWX_UCODE_TLV_API_NEW_RX_STATS               35
> +#define IWX_UCODE_TLV_API_WOWLAN_KEY_MATERIAL        36
> +#define IWX_UCODE_TLV_API_QUOTA_LOW_LATENCY  38
> +#define IWX_UCODE_TLV_API_DEPRECATE_TTAK     41
>  #define IWX_UCODE_TLV_API_ADAPTIVE_DWELL_V2  42
> +#define IWX_UCODE_TLV_API_NAN_NOTIF_V2               43
> +#define IWX_UCODE_TLV_API_FRAG_EBS           44
> +#define IWX_UCODE_TLV_API_REDUCE_TX_POWER    45
> +#define IWX_UCODE_TLV_API_SHORT_BEACON_NOTIF 46
>  #define IWX_UCODE_TLV_API_BEACON_FILTER_V4   47
> -#define IWX_UCODE_TLV_API_REGULATORY_NVM_INFO   48
> -#define IWX_UCODE_TLV_API_REDUCED_SCAN_CONFIG   56
> +#define IWX_UCODE_TLV_API_REGULATORY_NVM_INFO        48
> +#define IWX_UCODE_TLV_API_FTM_NEW_RANGE_REQ  49
> +#define IWX_UCODE_TLV_API_REDUCED_SCAN_CONFIG        56
> +#define IWX_UCODE_TLV_API_SCAN_OFFLOAD_CHANS 50
> +#define IWX_UCODE_TLV_API_MBSSID_HE          52
> +#define IWX_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE        53
> +#define IWX_UCODE_TLV_API_FTM_RTT_ACCURACY   54
> +#define IWX_UCODE_TLV_API_SAR_TABLE_VER              55
> +#define IWX_UCODE_TLV_API_REDUCED_SCAN_CONFIG        56
> +#define IWX_UCODE_TLV_API_ADWELL_HB_DEF_N_AP 57
>  #define IWX_UCODE_TLV_API_SCAN_EXT_CHAN_VER  58
> +#define IWX_UCODE_TLV_API_BAND_IN_RX_DATA    59
>  #define IWX_NUM_UCODE_TLV_API                        128
>  
>  #define IWX_UCODE_TLV_API_BITS \
> @@ -1013,18 +1029,36 @@ enum msix_ivar_for_cause {
>  #define IWX_UCODE_TLV_CAPA_GSCAN_SUPPORT             31
>  #define IWX_UCODE_TLV_CAPA_NAN_SUPPORT                       34
>  #define IWX_UCODE_TLV_CAPA_UMAC_UPLOAD                       35
> +#define IWM_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT               37
> +#define IWX_UCODE_TLV_CAPA_STA_PM_NOTIF                      38
>  #define IWX_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT               39
>  #define IWX_UCODE_TLV_CAPA_CDB_SUPPORT                       40
> -#define IWX_UCODE_TLV_CAPA_TLC_OFFLOAD                  43
> -#define IWX_UCODE_TLV_CAPA_DYNAMIC_QUOTA                44
> +#define IWX_UCODE_TLV_CAPA_D0I3_END_FIRST            41
> +#define IWX_UCODE_TLV_CAPA_TLC_OFFLOAD                       43
> +#define IWX_UCODE_TLV_CAPA_DYNAMIC_QUOTA             44
> +#define IWX_UCODE_TLV_CAPA_COEX_SCHEMA_2             45
> +#define IWX_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD                46
> +#define IWX_UCODE_TLV_CAPA_FTM_CALIBRATED            47
>  #define IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS         48
> +#define IWX_UCODE_TLV_CAPA_CS_MODIFY                 49
> +#define IWX_UCODE_TLV_CAPA_SET_LTR_GEN2                      50
> +#define IWX_UCODE_TLV_CAPA_SET_PPAG                  52
> +#define IWX_UCODE_TLV_CAPA_TAS_CFG                   53
> +#define IWX_UCODE_TLV_CAPA_SESSION_PROT_CMD          54
> +#define IWX_UCODE_TLV_CAPA_PROTECTED_TWT             56
> +#define IWX_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE                57
> +#define IWX_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN         58
> +#define IWX_UCODE_TLV_CAPA_PROTECTED_TWT             56
> +#define IWX_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE                57
> +#define IWX_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN         58
>  #define IWX_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE              64
>  #define IWX_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS         65
>  #define IWX_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT          67
>  #define IWX_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT    68
> +#define IWX_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD              70
>  #define IWX_UCODE_TLV_CAPA_BEACON_ANT_SELECTION              71
>  #define IWX_UCODE_TLV_CAPA_BEACON_STORING            72
> -#define IWX_UCODE_TLV_CAPA_LAR_SUPPORT_V2            73
> +#define IWX_UCODE_TLV_CAPA_LAR_SUPPORT_V3            73
>  #define IWX_UCODE_TLV_CAPA_CT_KILL_BY_FW             74
>  #define IWX_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT   75
>  #define IWX_UCODE_TLV_CAPA_CTDP_SUPPORT                      76
> @@ -1032,7 +1066,17 @@ enum msix_ivar_for_cause {
>  #define IWX_UCODE_TLV_CAPA_LMAC_UPLOAD                       79
>  #define IWX_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG     80
>  #define IWX_UCODE_TLV_CAPA_LQM_SUPPORT                       81
> +#define IWX_UCODE_TLV_CAPA_TX_POWER_ACK                      84
> +#define IWX_UCODE_TLV_CAPA_D3_DEBUG                  87
>  #define IWX_UCODE_TLV_CAPA_LED_CMD_SUPPORT           88
> +#define IWX_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT   89
> +#define IWX_UCODE_TLV_CAPA_CSI_REPORTING             90
> +#define IWX_UCODE_TLV_CAPA_CSI_REPORTING_V2          91
> +#define IWX_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP       92
> +#define IWX_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP    93
> +#define IWX_UCODE_TLV_CAPA_MLME_OFFLOAD                      96
> +#define IWX_UCODE_TLV_CAPA_BIGTK_SUPPORT             100
> +#define IWX_UCODE_TLV_CAPA_RFIM_SUPPORT                      102
>  
>  #define IWX_NUM_UCODE_TLV_CAPA 128
>  
> @@ -1189,7 +1233,13 @@ struct iwx_ucode_header {
>  #define IWX_UCODE_TLV_FW_RECOVERY_INFO       57
>  #define IWX_UCODE_TLV_FW_FMAC_RECOVERY_INFO 59
>  #define IWX_UCODE_TLV_FW_FSEQ_VERSION        60
> +#define IWX_UCODE_TLV_PHY_INTEGRATION_VERSION        61
> +#define IWX_UCODE_TLV_PNVM_VERSION           62
> +#define IWX_UCODE_TLV_PNVM_SKU                       64
>  
> +#define IWX_UCODE_TLV_CONST_BASE             0x100
> +#define IWX_UCODE_TLV_FW_NUM_STATIONS                
> (IWX_UCODE_TLV_CONST_BASE + 0)
> +
>  #define IWX_UCODE_TLV_DEBUG_BASE     0x1000005
>  #define IWX_UCODE_TLV_TYPE_DEBUG_INFO                
> (IWX_UCODE_TLV_DEBUG_BASE + 0)
>  #define IWX_UCODE_TLV_TYPE_BUFFER_ALLOCATION (IWX_UCODE_TLV_DEBUG_BASE + 1)
> @@ -1530,6 +1580,8 @@ struct iwx_tx_queue_cfg_rsp {
>  
>  #define IWX_REPLY_RX_PHY_CMD 0xc0
>  #define IWX_REPLY_RX_MPDU_CMD        0xc1
> +#define IWX_BAR_FRAME_RELEASE        0xc2
> +#define IWX_FRAME_RELEASE    0xc3
>  #define IWX_BA_NOTIF         0xc5
>  
>  /* Location Aware Regulatory */
> @@ -1605,6 +1657,10 @@ struct iwx_tx_queue_cfg_rsp {
>  #define IWX_INIT_EXTENDED_CFG_CMD    0x03
>  #define IWX_FW_ERROR_RECOVERY_CMD    0x07
>  
> +/* MAC_CONF group subcommand IDs */
> +#define IWX_SESSION_PROTECTION_CMD   0x05
> +#define IWX_SESSION_PROTECTION_NOTIF 0xfb
> +
>  /* DATA_PATH group subcommand IDs */
>  #define IWX_DQA_ENABLE_CMD   0x00
>  #define IWX_TLC_MNG_CONFIG_CMD       0x0f
> @@ -1922,6 +1978,19 @@ struct iwx_alive_resp_v4 {
>       struct iwx_umac_alive umac_data;
>  } __packed; /* ALIVE_RES_API_S_VER_4 */
>  
> +struct iwx_sku_id {
> +     uint32_t data[3];
> +} __packed; /* SKU_ID_API_S_VER_1 */
> +
> +struct iwx_alive_resp_v5 {
> +     uint16_t status;
> +     uint16_t flags;
> +     struct iwx_lmac_alive lmac_data[2];
> +     struct iwx_umac_alive umac_data;
> +     struct iwx_sku_id sku_id;
> +} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */
> +
> +
>  #define IWX_SOC_CONFIG_CMD_FLAGS_DISCRETE    (1 << 0)
>  #define IWX_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY (1 << 1)
>  
> @@ -2722,7 +2791,87 @@ struct iwx_time_event_notif {
>       uint32_t status;
>  } __packed; /* IWX_MAC_TIME_EVENT_NTFY_API_S_VER_1 */
>  
> +/**
> + * enum iwx_session_prot_conf_id - session protection's configurations
> + * @SESSION_PROTECT_CONF_ASSOC: Start a session protection for association.
> + *   The firmware will allocate two events.
> + *   Valid for BSS_STA and P2P_STA.
> + *   * A rather short event that can't be fragmented and with a very
> + *   high priority. If every goes well (99% of the cases) the
> + *   association should complete within this first event. During
> + *   that event, no other activity will happen in the firmware,
> + *   which is why it can't be too long.
> + *   The length of this event is hard-coded in the firmware: 300TUs.
> + *   * Another event which can be much longer (it's duration is
> + *   configurable by the driver) which has a slightly lower
> + *   priority and that can be fragmented allowing other activities
> + *   to run while this event is running.
> + *   The firmware will automatically remove both events once the driver sets
> + *   the BSS MAC as associated. Neither of the events will be removed
> + *   for the P2P_STA MAC.
> + *   Only the duration is configurable for this protection.
> + * @SESSION_PROTECT_CONF_GO_CLIENT_ASSOC: not used
> + * @SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV: Schedule the P2P Device to be in
> + *   listen mode. Will be fragmented. Valid only on the P2P Device MAC.
> + *   Valid only on the P2P Device MAC. The firmware will take into account
> + *   the duration, the interval and the repetition count.
> + * @SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION: Schedule the P2P Device to be be
> + *   able to run the GO Negotiation. Will not be fragmented and not
> + *   repetitive. Valid only on the P2P Device MAC. Only the duration will
> + *   be taken into account.
> + * @SESSION_PROTECT_CONF_MAX_ID: not used
> + */
> +enum iwx_session_prot_conf_id {
> +     IWX_SESSION_PROTECT_CONF_ASSOC,
> +     IWX_SESSION_PROTECT_CONF_GO_CLIENT_ASSOC,
> +     IWX_SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV,
> +     IWX_SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION,
> +     IWX_SESSION_PROTECT_CONF_MAX_ID,
> +}; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */
>  
> +/**
> + * struct iwx_session_prot_cmd - configure a session protection
> + * @id_and_color: the id and color of the mac for which this session 
> protection
> + *   is sent
> + * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE
> + * @conf_id: see &enum iwx_mvm_session_prot_conf_id
> + * @duration_tu: the duration of the whole protection in TUs.
> + * @repetition_count: not used
> + * @interval: not used
> + *
> + * Note: the session protection will always be scheduled to start as
> + * early as possible, but the maximum delay is configuration dependent.
> + * The firmware supports only one concurrent session protection per vif.
> + * Adding a new session protection will remove any currently running session.
> + */
> +struct iwx_session_prot_cmd {
> +     /* COMMON_INDEX_HDR_API_S_VER_1 hdr */
> +     uint32_t id_and_color;
> +     uint32_t action;
> +     uint32_t conf_id;
> +     uint32_t duration_tu;
> +     uint32_t repetition_count;
> +     uint32_t interval;
> +} __packed; /* SESSION_PROTECTION_CMD_API_S_VER_1 */
> +
> +/**
> + * struct iwx_session_prot_notif - session protection started / ended
> + * @mac_id: the mac id for which the session protection started / ended
> + * @status: 1 means success, 0 means failure
> + * @start: 1 means the session protection started, 0 means it ended
> + * @conf_id: see &enum iwx_mvm_session_prot_conf_id
> + *
> + * Note that any session protection will always get two notifications: start
> + * and end even the firmware could not schedule it.
> + */
> +struct iwx_session_prot_notif {
> +     uint32_t mac_id;
> +     uint32_t status;
> +     uint32_t start;
> +     uint32_t conf_id;
> +} __packed; /* SESSION_PROTECTION_NOTIFICATION_API_S_VER_2 */
> +
> +
>  /* Bindings and Time Quota */
>  
>  /**
> @@ -2861,6 +3010,40 @@ struct iwx_fw_channel_info {
>  /* TODO: fix the value, make it depend on firmware at runtime? */
>  #define IWX_NUM_PHY_CTX      3
>  
> +/**
> + * struct iwl_phy_context_cmd - config of the PHY context
> + * ( IWX_PHY_CONTEXT_CMD = 0x8 )
> + * @id_and_color: ID and color of the relevant Binding
> + * @action: action to perform, one of IWX_FW_CTXT_ACTION_*
> + * @lmac_id: the lmac id the phy context belongs to
> + * @ci: channel info
> + * @rxchain_info: ???
> + * @dsp_cfg_flags: set to 0
> + * @reserved: reserved to align to 64 bit
> + */
> +struct iwx_phy_context_cmd_uhb {
> +     /* COMMON_INDEX_HDR_API_S_VER_1 */
> +     uint32_t id_and_color;
> +     uint32_t action;
> +     /* PHY_CONTEXT_DATA_API_S_VER_3 */
> +     struct iwx_fw_channel_info ci;
> +     uint32_t lmac_id;
> +     uint32_t rxchain_info;
> +     uint32_t dsp_cfg_flags;
> +     uint32_t reserved;
> +} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */
> +struct iwx_phy_context_cmd {
> +     /* COMMON_INDEX_HDR_API_S_VER_1 */
> +     uint32_t id_and_color;
> +     uint32_t action;
> +     /* PHY_CONTEXT_DATA_API_S_VER_3 */
> +     struct iwx_fw_channel_info_v1 ci;
> +     uint32_t lmac_id;
> +     uint32_t rxchain_info;
> +     uint32_t dsp_cfg_flags;
> +     uint32_t reserved;
> +} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */
> +
>  /* TODO: complete missing documentation */
>  /**
>   * struct iwx_phy_context_cmd - config of the PHY context
> @@ -2884,7 +3067,7 @@ struct iwx_fw_channel_info {
>   * magic with pointers to struct members instead.)
>   */
>  /* This version must be used if IWX_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS is set: 
> */
> -struct iwx_phy_context_cmd_uhb {
> +struct iwx_phy_context_cmd_uhb_v1 {
>       /* COMMON_INDEX_HDR_API_S_VER_1 */
>       uint32_t id_and_color;
>       uint32_t action;
> @@ -2898,7 +3081,7 @@ struct iwx_phy_context_cmd_uhb {
>       uint32_t dsp_cfg_flags;
>  } __packed; /* IWX_PHY_CONTEXT_CMD_API_VER_1 */
>  /* This version must be used otherwise: */
> -struct iwx_phy_context_cmd {
> +struct iwx_phy_context_cmd_v1 {
>       /* COMMON_INDEX_HDR_API_S_VER_1 */
>       uint32_t id_and_color;
>       uint32_t action;
> @@ -3136,7 +3319,44 @@ struct iwx_rx_mpdu_desc {
>       struct iwx_rx_mpdu_desc_v1 v1;
>  } __packed;
>  
> +struct iwx_frame_release {
> +     uint8_t baid;
> +     uint8_t reserved;
> +     uint16_t nssn;
> +};
> +
>  /**
> + * enum iwx_bar_frame_release_sta_tid - STA/TID information for BAR release
> + * @IWX_BAR_FRAME_RELEASE_TID_MASK: TID mask
> + * @IWX_BAR_FRAME_RELEASE_STA_MASK: STA mask
> + */
> +#define IWX_BAR_FRAME_RELEASE_TID_MASK       0x0000000f
> +#define IWX_BAR_FRAME_RELEASE_STA_MASK       0x000001f0
> +#define IWX_BAR_FRAME_RELEASE_STA_SHIFT      4
> +
> +/**
> + * enum iwx_bar_frame_release_ba_info - BA information for BAR release
> + * @IWL_BAR_FRAME_RELEASE_NSSN_MASK: NSSN mask
> + * @IWL_BAR_FRAME_RELEASE_SN_MASK: SN mask (ignored by driver)
> + * @IWL_BAR_FRAME_RELEASE_BAID_MASK: BAID mask
> + */
> +#define IWX_BAR_FRAME_RELEASE_NSSN_MASK              0x00000fff
> +#define IWX_BAR_FRAME_RELEASE_SN_MASK                0x00fff000
> +#define IWX_BAR_FRAME_RELEASE_SN_SHIFT               12
> +#define IWX_BAR_FRAME_RELEASE_BAID_MASK              0x3f000000
> +#define IWX_BAR_FRAME_RELEASE_BAID_SHIFT     24
> +
> +/**
> + * struct iwx_bar_frame_release - frame release from BAR info
> + * @sta_tid: STA & TID information, see &enum iwx_bar_frame_release_sta_tid.
> + * @ba_info: BA information, see &enum iwx_bar_frame_release_ba_info.
> + */
> +struct iwx_bar_frame_release {
> +     uint32_t sta_tid;
> +     uint32_t ba_info;
> +} __packed; /* RX_BAR_TO_FRAME_RELEASE_API_S_VER_1 */
> +
> +/**
>   * struct iwx_radio_version_notif - information on the radio version
>   * ( IWX_RADIO_VERSION_NOTIFICATION = 0x68 )
>   * @radio_flavor:
> @@ -4574,6 +4794,8 @@ enum iwx_tlc_mng_ht_rates {
>   * @sgi_ch_width_supp: bitmap of SGI support per channel width
>   *                  use (1 << @enum iwx_tlc_mng_cfg_cw)
>   * @reserved2: reserved
> + * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),
> + *          set zero for no limit.
>   */
>  struct iwx_tlc_config_cmd {
>       uint8_t sta_id;
> @@ -4587,8 +4809,9 @@ struct iwx_tlc_config_cmd {
>       uint16_t ht_rates[IWX_TLC_NSS_MAX][2];
>       uint16_t max_mpdu_len;
>       uint8_t sgi_ch_width_supp;
> -     uint8_t reserved2[1];
> -} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_2 */
> +     uint8_t reserved2;
> +     uint32_t max_tx_op;
> +} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_3 */
>  
>  /**
>   * @IWX_TLC_NOTIF_FLAG_RATE: last initial rate update
> @@ -5315,6 +5538,10 @@ struct iwx_scan_probe_req {
>  #define IWX_SCAN_CHANNEL_FLAG_EBS            (1 << 0)
>  #define IWX_SCAN_CHANNEL_FLAG_EBS_ACCURATE   (1 << 1)
>  #define IWX_SCAN_CHANNEL_FLAG_CACHE_ADD              (1 << 2)
> +#define IWX_SCAN_CHANNEL_FLAG_EBS_FRAG               (1 << 3)
> +#define IWX_SCAN_CHANNEL_FLAG_FORCE_EBS              (1 << 4)
> +#define IWX_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER      (1 << 5)
> +#define IWX_SCAN_CHANNEL_FLAG_6G_PSC_NO_FILTER       (1 << 6)
>  
>  /* iwx_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
>   * @flags: enum iwx_scan_channel_flags
> @@ -5332,6 +5559,17 @@ struct iwx_scan_channel_opt {
>  #define IWX_SCAN_PRIORITY_MEDIUM     1
>  #define IWX_SCAN_PRIORITY_HIGH               2
>  
> +enum iwx_scan_priority_ext {
> +     IWX_SCAN_PRIORITY_EXT_0_LOWEST,
> +     IWX_SCAN_PRIORITY_EXT_1,
> +     IWX_SCAN_PRIORITY_EXT_2,
> +     IWX_SCAN_PRIORITY_EXT_3,
> +     IWX_SCAN_PRIORITY_EXT_4,
> +     IWX_SCAN_PRIORITY_EXT_5,
> +     IWX_SCAN_PRIORITY_EXT_6,
> +     IWX_SCAN_PRIORITY_EXT_7_HIGHEST,
> +};
> +
>  /**
>   * iwx_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
>   * @last_schedule_line: last schedule line executed (fast or regular)
> @@ -5501,7 +5739,26 @@ struct iwx_scan_dwell {
>  #define IWX_SCAN_HB_LMAC_IDX 1 /* high-band */
>  
>  /**
> - * struct iwx_scan_config
> + * struct iwl_scan_config
> + * @enable_cam_mode: whether to enable CAM mode.
> + * @enable_promiscouos_mode: whether to enable promiscouos mode
> + * @bcast_sta_id: the index of the station in the fw. Deprecated starting 
> with
> + *     API version 5.
> + * @reserved: reserved
> + * @tx_chains: valid_tx antenna - ANT_* definitions
> + * @rx_chains: valid_rx antenna - ANT_* definitions
> + */
> +struct iwx_scan_config {
> +     uint8_t enable_cam_mode;
> +     uint8_t enable_promiscouos_mode;
> +     uint8_t bcast_sta_id;
> +     uint8_t reserved;
> +     uint32_t tx_chains;
> +     uint32_t rx_chains;
> +} __packed; /* SCAN_CONFIG_DB_CMD_API_S_5 */
> +
> +/**
> + * struct iwx_scan_config_v2
>   * @flags:                   enum scan_config_flags
>   * @tx_chains:                       valid_tx antenna - ANT_* definitions
>   * @rx_chains:                       valid_rx antenna - ANT_* definitions
> @@ -5518,7 +5775,7 @@ struct iwx_scan_dwell {
>   *                           scan_config_channel_flag
>   * @channel_array:           default supported channels
>   */
> -struct iwx_scan_config {
> +struct iwx_scan_config_v2 {
>       uint32_t flags;
>       uint32_t tx_chains;
>       uint32_t rx_chains;
> @@ -5819,6 +6076,125 @@ struct iwx_scan_req_umac {
>  #define IWX_SCAN_REQ_UMAC_SIZE_V1 36
>  
>  /**
> + * struct iwx_scan_general_params_v10
> + * @flags: &enum iwx_umac_scan_flags
> + * @reserved: reserved for future
> + * @scan_start_mac_id: report the scan start TSF time according to this mac 
> TSF
> + * @active_dwell: dwell time for active scan per LMAC
> + * @adwell_default_2g: adaptive dwell default number of APs
> + *                        for 2.4GHz channel
> + * @adwell_default_5g: adaptive dwell default number of APs
> + *                        for 5GHz channels
> + * @adwell_default_social_chn: adaptive dwell default number of
> + *                             APs per social channel
> + * @reserved1: reserved for future
> + * @adwell_max_budget: the maximal number of TUs that adaptive dwell
> + *                     can add to the total scan time
> + * @max_out_of_time: max out of serving channel time, per LMAC
> + * @suspend_time: max suspend time, per LMAC
> + * @scan_priority: priority of the request
> + * @passive_dwell: continues dwell time for passive channel
> + *                 (without adaptive dwell)
> + * @num_of_fragments: number of fragments needed for full fragmented
> + *                    scan coverage.
> + */
> +struct iwx_scan_general_params_v10 {
> +     uint16_t flags;
> +     uint8_t reserved;
> +     uint8_t scan_start_mac_id;
> +     uint8_t active_dwell[IWX_SCAN_TWO_LMACS];
> +     uint8_t adwell_default_2g;
> +     uint8_t adwell_default_5g;
> +     uint8_t adwell_default_social_chn;
> +     uint8_t reserved1;
> +     uint16_t adwell_max_budget;
> +     uint32_t max_out_of_time[IWX_SCAN_TWO_LMACS];
> +     uint32_t suspend_time[IWX_SCAN_TWO_LMACS];
> +     uint32_t scan_priority;
> +     uint8_t passive_dwell[IWX_SCAN_TWO_LMACS];
> +     uint8_t num_of_fragments[IWX_SCAN_TWO_LMACS];
> +} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_10 */
> +
> +/**
> + * struct iwx_scan_channel_params_v6
> + * @flags: channel flags &enum iwl_scan_channel_flags
> + * @count: num of channels in scan request
> + * @n_aps_override: override the number of APs the FW uses to calculate dwell
> + *   time when adaptive dwell is used.
> + *   Channel k will use n_aps_override[i] when BIT(20 + i) is set in
> + *   channel_config[k].flags
> + * @channel_config: array of explicit channel configurations
> + *                  for 2.4Ghz and 5.2Ghz bands
> + */
> +struct iwx_scan_channel_params_v6 {
> +     uint8_t flags;
> +     uint8_t count;
> +     uint8_t n_aps_override[2];
> +     struct iwx_scan_channel_cfg_umac channel_config[67];
> +} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */
> +
> +/**
> + * struct iwx_scan_periodic_parms_v1
> + * @schedule: can scheduling parameter
> + * @delay: initial delay of the periodic scan in seconds
> + * @reserved: reserved for future
> + */
> +struct iwx_scan_periodic_parms_v1 {
> +     struct iwx_scan_umac_schedule schedule[IWX_MAX_SCHED_SCAN_PLANS];
> +     uint16_t delay;
> +     uint16_t reserved;
> +} __packed; /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
> +
> +#define IWX_SCAN_SHORT_SSID_MAX_SIZE        8
> +#define IWX_SCAN_BSSID_MAX_SIZE             16
> +
> +/**
> + * struct iwx_scan_probe_params_v4
> + * @preq: scan probe request params
> + * @short_ssid_num: number of valid short SSIDs in short ssid array
> + * @bssid_num: number of valid bssid in bssids array
> + * @reserved: reserved
> + * @direct_scan: list of ssids
> + * @short_ssid: array of short ssids
> + * @bssid_array: array of bssids
> + */
> +struct iwx_scan_probe_params_v4 {
> +     struct iwx_scan_probe_req preq;
> +     uint8_t short_ssid_num;
> +     uint8_t bssid_num;
> +     uint16_t reserved;
> +     struct iwx_ssid_ie direct_scan[IWX_PROBE_OPTION_MAX];
> +     uint32_t short_ssid[IWX_SCAN_SHORT_SSID_MAX_SIZE];
> +     uint8_t bssid_array[IWX_SCAN_BSSID_MAX_SIZE][ETHER_ADDR_LEN];
> +} __packed; /* SCAN_PROBE_PARAMS_API_S_VER_4 */
> +
> +/**
> + * struct iwx_scan_req_params_v14
> + * @general_params: &struct iwx_scan_general_params_v10
> + * @channel_params: &struct iwx_scan_channel_params_v6
> + * @periodic_params: &struct iwx_scan_periodic_parms_v1
> + * @probe_params: &struct iwx_scan_probe_params_v4
> + */
> +struct iwx_scan_req_params_v14 {
> +     struct iwx_scan_general_params_v10 general_params;
> +     struct iwx_scan_channel_params_v6 channel_params;
> +     struct iwx_scan_periodic_parms_v1 periodic_params;
> +     struct iwx_scan_probe_params_v4 probe_params;
> +} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_14 */
> +
> +/**
> + * struct iwx_scan_req_umac_v14
> + * @uid: scan id, &enum iwl_umac_scan_uid_offsets
> + * @ooc_priority: out of channel priority - &enum iwx_scan_priority
> + * @scan_params: scan parameters
> + */
> +struct iwx_scan_req_umac_v14 {
> +     uint32_t uid;
> +     uint32_t ooc_priority;
> +     struct iwx_scan_req_params_v14 scan_params;
> +} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_14 */
> +
> +/**
>   * struct iwx_umac_scan_abort
>   * @uid: scan id, &enum iwx_umac_scan_uid_offsets
>   * @flags: reserved
> @@ -6533,7 +6909,7 @@ struct iwx_cmd_header_wide {
>  #define IWX_POWER_SCHEME_LP  3
>  
>  #define IWX_DEF_CMD_PAYLOAD_SIZE 320
> -#define IWX_MAX_CMD_PAYLOAD_SIZE ((4096 - 4) - sizeof(struct iwx_cmd_header))
> +#define IWX_MAX_CMD_PAYLOAD_SIZE (4096 - sizeof(struct iwx_cmd_header_wide))
>  #define IWX_CMD_FAILED_MSK 0x40
>  
>  /**
> blob - 928b4d9ec79fed1937e4e147b905cf0da7c36750
> blob + 4d297250743b79e9f6bd250041b7ff3b51f43cea
> --- sys/dev/pci/if_iwxvar.h
> +++ sys/dev/pci/if_iwxvar.h
> @@ -123,7 +123,7 @@ struct iwx_tx_radiotap_header {
>        (1 << IEEE80211_RADIOTAP_RATE) |                               \
>        (1 << IEEE80211_RADIOTAP_CHANNEL))
>  
> -#define IWX_UCODE_SECT_MAX 42
> +#define IWX_UCODE_SECT_MAX 47
>  #define IWX_FWDMASEGSZ (192*1024)
>  #define IWX_FWDMASEGSZ_8000 (320*1024)
>  /* sanity check value */
> @@ -236,6 +236,8 @@ struct iwx_tx_data {
>       bus_addr_t      cmd_paddr;
>       struct mbuf     *m;
>       struct iwx_node *in;
> +     int flags;
> +#define IWX_TXDATA_FLAG_CMD_IS_NARROW        0x01
>  };
>  
>  struct iwx_tx_ring {
> @@ -501,6 +503,7 @@ struct iwx_softc {
>       struct iwx_tx_ring txq[IWX_MAX_QUEUES];
>       struct iwx_rx_ring rxq;
>       int qfullmsk;
> +     int first_data_qid;
>  
>       int sc_sf_state;
>  
> @@ -536,7 +539,7 @@ struct iwx_softc {
>       int sc_capa_n_scan_channels;
>       uint8_t sc_ucode_api[howmany(IWX_NUM_UCODE_TLV_API, NBBY)];
>       uint8_t sc_enabled_capa[howmany(IWX_NUM_UCODE_TLV_CAPA, NBBY)];
> -#define IWX_MAX_FW_CMD_VERSIONS      64
> +#define IWX_MAX_FW_CMD_VERSIONS      167
>       struct iwx_fw_cmd_version cmd_versions[IWX_MAX_FW_CMD_VERSIONS];
>       int n_cmd_versions;
>  
> 
> 
> 

Reply via email to