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. 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;