diff --git a/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwx.c b/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwx.c index 00e19e1f2c..dd00226952 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwx.c +++ b/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwx.c,v 1.153 2023/02/19 12:23:27 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.176 2023/08/26 09:05:34 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh @@ -244,7 +244,6 @@ 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); int iwx_alloc_fw_monitor_block(struct iwx_softc *, uint8_t, uint8_t); int iwx_alloc_fw_monitor(struct iwx_softc *, uint8_t); @@ -389,10 +388,10 @@ 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); uint8_t iwx_get_vht_ctrl_pos(struct ieee80211com *, struct ieee80211_channel *); -int iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t, - uint8_t, uint32_t, uint8_t, uint8_t); -int iwx_phy_ctxt_cmd_v3(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t, - uint8_t, uint32_t, uint8_t, uint8_t); +int iwx_phy_ctxt_cmd_uhb_v3_v4(struct iwx_softc *, struct iwx_phy_ctxt *, + uint8_t, uint8_t, uint32_t, uint8_t, uint8_t, int); +int iwx_phy_ctxt_cmd_v3_v4(struct iwx_softc *, struct iwx_phy_ctxt *, + uint8_t, uint8_t, uint32_t, uint8_t, uint8_t, int); int iwx_phy_ctxt_cmd(struct iwx_softc *, struct iwx_phy_ctxt *, uint8_t, uint8_t, uint32_t, uint32_t, uint8_t, uint8_t); int iwx_send_cmd(struct iwx_softc *, struct iwx_host_cmd *); @@ -404,6 +403,8 @@ int iwx_send_cmd_pdu_status(struct iwx_softc *, uint32_t, uint16_t, const void *, uint32_t *); void iwx_free_resp(struct iwx_softc *, struct iwx_host_cmd *); void iwx_cmd_done(struct iwx_softc *, int, int, int); +uint32_t iwx_fw_rateidx_ofdm(uint8_t); +uint32_t iwx_fw_rateidx_cck(uint8_t); const struct iwx_rate *iwx_tx_fill_cmd(struct iwx_softc *, struct iwx_node *, struct ieee80211_frame *, uint16_t *, uint32_t *); void iwx_tx_update_byte_tbl(struct iwx_softc *, struct iwx_tx_ring *, int, @@ -433,7 +434,7 @@ void iwx_scan_umac_dwell_v10(struct iwx_softc *, 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); + struct iwx_scan_channel_params_v6 *, uint32_t, int); int iwx_umac_scan_v14(struct iwx_softc *, int); void iwx_mcc_update(struct iwx_softc *, struct iwx_mcc_chub_notif *); uint8_t iwx_ridx2rate(struct ieee80211_rateset *, int); @@ -455,11 +456,16 @@ void iwx_bgscan_done_task(void *); int iwx_umac_scan_abort(struct iwx_softc *); int iwx_scan_abort(struct iwx_softc *); int iwx_enable_mgmt_queue(struct iwx_softc *); +int iwx_disable_mgmt_queue(struct iwx_softc *); int iwx_rs_rval2idx(uint8_t); uint16_t iwx_rs_ht_rates(struct iwx_softc *, struct ieee80211_node *, int); uint16_t iwx_rs_vht_rates(struct iwx_softc *, struct ieee80211_node *, int); +int iwx_rs_init_v3(struct iwx_softc *, struct iwx_node *); +int iwx_rs_init_v4(struct iwx_softc *, struct iwx_node *); int iwx_rs_init(struct iwx_softc *, struct iwx_node *); int iwx_enable_data_tx_queues(struct iwx_softc *); +int iwx_phy_send_rlc(struct iwx_softc *, struct iwx_phy_ctxt *, + uint8_t, uint8_t); int iwx_phy_ctxt_update(struct iwx_softc *, struct iwx_phy_ctxt *, struct ieee80211_channel *, uint8_t, uint8_t, uint32_t, uint8_t, uint8_t); @@ -560,16 +566,21 @@ iwx_lookup_notif_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd) int iwx_is_mimo_ht_plcp(uint8_t ht_plcp) { - return (ht_plcp != IWX_RATE_HT_SISO_MCS_INV_PLCP && - (ht_plcp & IWX_RATE_HT_MCS_NSS_MSK)); -} + switch (ht_plcp) { + case IWX_RATE_HT_MIMO2_MCS_8_PLCP: + case IWX_RATE_HT_MIMO2_MCS_9_PLCP: + case IWX_RATE_HT_MIMO2_MCS_10_PLCP: + case IWX_RATE_HT_MIMO2_MCS_11_PLCP: + case IWX_RATE_HT_MIMO2_MCS_12_PLCP: + case IWX_RATE_HT_MIMO2_MCS_13_PLCP: + case IWX_RATE_HT_MIMO2_MCS_14_PLCP: + case IWX_RATE_HT_MIMO2_MCS_15_PLCP: + return 1; + default: + break; + } -int -iwx_is_mimo_mcs(int mcs) -{ - int ridx = iwx_mcs2ridx[mcs]; - return iwx_is_mimo_ht_plcp(iwx_rates[ridx].ht_plcp); - + return 0; } int @@ -722,7 +733,7 @@ iwx_init_fw_sec(struct iwx_softc *sc, const struct iwx_fw_sects *fws, return 0; } - + void iwx_fw_version_str(char *buf, size_t bufsize, uint32_t major, uint32_t minor, uint32_t api) @@ -1073,7 +1084,7 @@ iwx_ctxt_info_gen3_init(struct iwx_softc *sc, const struct iwx_fw_sects *fws) IWX_SETBITS(sc, IWX_CSR_CTXT_INFO_BOOT_CTRL, IWX_CSR_AUTO_FUNC_BOOT_ENA); - + /* kick FW self load */ if (!iwx_nic_lock(sc)) { iwx_dma_contig_free(&sc->iml_dma); @@ -1546,6 +1557,7 @@ iwx_read_firmware(struct iwx_softc *sc) case IWX_UCODE_TLV_FW_FSEQ_VERSION: case IWX_UCODE_TLV_PHY_INTEGRATION_VERSION: case IWX_UCODE_TLV_FW_NUM_STATIONS: + case IWX_UCODE_TLV_FW_NUM_BEACONS: break; /* undocumented TLVs found in iwx-cc-a0-46 image */ @@ -1565,12 +1577,23 @@ iwx_read_firmware(struct iwx_softc *sc) case IWX_UCODE_TLV_TYPE_REGIONS: case IWX_UCODE_TLV_TYPE_TRIGGERS: case IWX_UCODE_TLV_TYPE_CONF_SET: + case IWX_UCODE_TLV_SEC_TABLE_ADDR: + case IWX_UCODE_TLV_D3_KEK_KCK_ADDR: + case IWX_UCODE_TLV_CURRENT_PC: break; /* undocumented TLV found in iwx-cc-a0-67 image */ case 0x100000b: break; + /* undocumented TLV found in iwx-ty-a0-gf-a0-73 image */ + case 0x101: + break; + + /* undocumented TLV found in iwx-ty-a0-gf-a0-77 image */ + case 0x100000c: + break; + default: err = EINVAL; goto parse_out; @@ -1699,7 +1722,7 @@ iwx_read_mem(struct iwx_softc *sc, uint32_t addr, void *buf, int dwords) int iwx_write_mem(struct iwx_softc *sc, uint32_t addr, const void *buf, int dwords) { - int offs; + int offs; const uint32_t *vals = buf; if (iwx_nic_lock(sc)) { @@ -2329,7 +2352,7 @@ iwx_prepare_card_hw(struct iwx_softc *sc) IWX_SETBITS(sc, IWX_CSR_DBG_LINK_PWR_MGMT_REG, IWX_CSR_RESET_LINK_PWR_MGMT_DISABLED); DELAY(1000); - + for (ntries = 0; ntries < 10; ntries++) { /* If HW is not ready, prepare the conditions to check again */ IWX_SETBITS(sc, IWX_CSR_HW_IF_CONFIG_REG, @@ -2695,7 +2718,7 @@ iwx_stop_device(struct iwx_softc *sc) */ iwx_conf_msix_hw(sc, 1); - /* + /* * Upon stop, the APM issues an interrupt if HW RF kill is set. * Clear the interrupt again. */ @@ -2802,31 +2825,52 @@ int iwx_enable_txq(struct iwx_softc *sc, int sta_id, int qid, int tid, int num_slots) { - struct iwx_tx_queue_cfg_cmd cmd; struct iwx_rx_packet *pkt; struct iwx_tx_queue_cfg_rsp *resp; + struct iwx_tx_queue_cfg_cmd cmd_v0; + struct iwx_scd_queue_cfg_cmd cmd_v3; struct iwx_host_cmd hcmd = { - .id = IWX_SCD_QUEUE_CFG, .flags = IWX_CMD_WANT_RESP, .resp_pkt_len = sizeof(*pkt) + sizeof(*resp), }; struct iwx_tx_ring *ring = &sc->txq[qid]; - int err, fwqid; + int err, fwqid, cmd_ver; uint32_t wr_idx; size_t resp_len; iwx_reset_tx_ring(sc, ring); - memset(&cmd, 0, sizeof(cmd)); - cmd.sta_id = sta_id; - cmd.tid = tid; - cmd.flags = htole16(IWX_TX_QUEUE_CFG_ENABLE_QUEUE); - cmd.cb_size = htole32(IWX_TFD_QUEUE_CB_SIZE(num_slots)); - cmd.byte_cnt_addr = htole64(ring->bc_tbl.paddr); - cmd.tfdq_addr = htole64(ring->desc_dma.paddr); - - hcmd.data[0] = &cmd; - hcmd.len[0] = sizeof(cmd); + cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_SCD_QUEUE_CONFIG_CMD); + if (cmd_ver == 0 || cmd_ver == IWX_FW_CMD_VER_UNKNOWN) { + memset(&cmd_v0, 0, sizeof(cmd_v0)); + cmd_v0.sta_id = sta_id; + cmd_v0.tid = tid; + cmd_v0.flags = htole16(IWX_TX_QUEUE_CFG_ENABLE_QUEUE); + cmd_v0.cb_size = htole32(IWX_TFD_QUEUE_CB_SIZE(num_slots)); + cmd_v0.byte_cnt_addr = htole64(ring->bc_tbl.paddr); + cmd_v0.tfdq_addr = htole64(ring->desc_dma.paddr); + hcmd.id = IWX_SCD_QUEUE_CFG; + hcmd.data[0] = &cmd_v0; + hcmd.len[0] = sizeof(cmd_v0); + } else if (cmd_ver == 3) { + memset(&cmd_v3, 0, sizeof(cmd_v3)); + cmd_v3.operation = htole32(IWX_SCD_QUEUE_ADD); + cmd_v3.u.add.tfdq_dram_addr = htole64(ring->desc_dma.paddr); + cmd_v3.u.add.bc_dram_addr = htole64(ring->bc_tbl.paddr); + cmd_v3.u.add.cb_size = htole32(IWX_TFD_QUEUE_CB_SIZE(num_slots)); + cmd_v3.u.add.flags = htole32(0); + cmd_v3.u.add.sta_mask = htole32(1 << sta_id); + cmd_v3.u.add.tid = tid; + hcmd.id = IWX_WIDE_ID(IWX_DATA_PATH_GROUP, + IWX_SCD_QUEUE_CONFIG_CMD); + hcmd.data[0] = &cmd_v3; + hcmd.len[0] = sizeof(cmd_v3); + } else { + printf("%s: unsupported SCD_QUEUE_CFG command version %d\n", + DEVNAME(sc), cmd_ver); + return ENOTSUP; + } err = iwx_send_cmd(sc, &hcmd); if (err) @@ -2834,14 +2878,12 @@ iwx_enable_txq(struct iwx_softc *sc, int sta_id, int qid, int tid, pkt = hcmd.resp_pkt; if (!pkt || (pkt->hdr.flags & IWX_CMD_FAILED_MSK)) { - DPRINTF(("SCD_QUEUE_CFG command failed\n")); err = EIO; goto out; } resp_len = iwx_rx_packet_payload_len(pkt); if (resp_len != sizeof(*resp)) { - DPRINTF(("SCD_QUEUE_CFG returned %zu bytes, expected %zu bytes\n", resp_len, sizeof(*resp))); err = EIO; goto out; } @@ -2852,14 +2894,11 @@ iwx_enable_txq(struct iwx_softc *sc, int sta_id, int qid, int tid, /* Unlike iwlwifi, we do not support dynamic queue ID assignment. */ if (fwqid != qid) { - DPRINTF(("requested qid %d but %d was assigned\n", qid, fwqid)); err = EIO; goto out; } if (wr_idx != ring->cur_hw) { - DPRINTF(("fw write index is %d but ring is %d\n", - wr_idx, ring->cur_hw)); err = EIO; goto out; } @@ -2874,27 +2913,44 @@ out: int iwx_disable_txq(struct iwx_softc *sc, int sta_id, int qid, uint8_t tid) { - struct iwx_tx_queue_cfg_cmd cmd; struct iwx_rx_packet *pkt; struct iwx_tx_queue_cfg_rsp *resp; + struct iwx_tx_queue_cfg_cmd cmd_v0; + struct iwx_scd_queue_cfg_cmd cmd_v3; struct iwx_host_cmd hcmd = { - .id = IWX_SCD_QUEUE_CFG, .flags = IWX_CMD_WANT_RESP, .resp_pkt_len = sizeof(*pkt) + sizeof(*resp), }; struct iwx_tx_ring *ring = &sc->txq[qid]; - int err; + int err, cmd_ver; - memset(&cmd, 0, sizeof(cmd)); - cmd.sta_id = sta_id; - cmd.tid = tid; - cmd.flags = htole16(0); /* clear "queue enabled" flag */ - cmd.cb_size = htole32(0); - cmd.byte_cnt_addr = htole64(0); - cmd.tfdq_addr = htole64(0); - - hcmd.data[0] = &cmd; - hcmd.len[0] = sizeof(cmd); + cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_SCD_QUEUE_CONFIG_CMD); + if (cmd_ver == 0 || cmd_ver == IWX_FW_CMD_VER_UNKNOWN) { + memset(&cmd_v0, 0, sizeof(cmd_v0)); + cmd_v0.sta_id = sta_id; + cmd_v0.tid = tid; + cmd_v0.flags = htole16(0); /* clear "queue enabled" flag */ + cmd_v0.cb_size = htole32(0); + cmd_v0.byte_cnt_addr = htole64(0); + cmd_v0.tfdq_addr = htole64(0); + hcmd.id = IWX_SCD_QUEUE_CFG; + hcmd.data[0] = &cmd_v0; + hcmd.len[0] = sizeof(cmd_v0); + } else if (cmd_ver == 3) { + memset(&cmd_v3, 0, sizeof(cmd_v3)); + cmd_v3.operation = htole32(IWX_SCD_QUEUE_REMOVE); + cmd_v3.u.remove.sta_mask = htole32(1 << sta_id); + cmd_v3.u.remove.tid = tid; + hcmd.id = IWX_WIDE_ID(IWX_DATA_PATH_GROUP, + IWX_SCD_QUEUE_CONFIG_CMD); + hcmd.data[0] = &cmd_v3; + hcmd.len[0] = sizeof(cmd_v3); + } else { + printf("%s: unsupported SCD_QUEUE_CFG command version %d\n", + DEVNAME(sc), cmd_ver); + return ENOTSUP; + } err = iwx_send_cmd(sc, &hcmd); if (err) @@ -2902,7 +2958,6 @@ iwx_disable_txq(struct iwx_softc *sc, int sta_id, int qid, uint8_t tid) pkt = hcmd.resp_pkt; if (!pkt || (pkt->hdr.flags & IWX_CMD_FAILED_MSK)) { - DPRINTF(("SCD_QUEUE_CFG command failed\n")); err = EIO; goto out; } @@ -2917,19 +2972,29 @@ out: void iwx_post_alive(struct iwx_softc *sc) { + int txcmd_ver; + iwx_ict_reset(sc); + + txcmd_ver = iwx_lookup_notif_ver(sc, IWX_LONG_GROUP, IWX_TX_CMD) ; + if (txcmd_ver != IWX_FW_CMD_VER_UNKNOWN && txcmd_ver > 6) + sc->sc_rate_n_flags_version = 2; + else + sc->sc_rate_n_flags_version = 1; + + txcmd_ver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_TX_CMD); } int iwx_schedule_session_protection(struct iwx_softc *sc, struct iwx_node *in, - uint32_t duration) + uint32_t duration_tu) { 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), + .duration_tu = htole32(duration_tu), }; uint32_t cmd_id; int err; @@ -3294,25 +3359,84 @@ iwx_reorder_timer_expired(void *arg) #define IWX_MAX_RX_BA_SESSIONS 16 -void -iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid, - uint16_t ssn, uint16_t winsize, int timeout_val, int start) +struct iwx_rxba_data * +iwx_find_rxba_data(struct iwx_softc *sc, uint8_t tid) +{ + int i; + + for (i = 0; i < nitems(sc->sc_rxba_data); i++) { + if (sc->sc_rxba_data[i].baid == + IWX_RX_REORDER_DATA_INVALID_BAID) + continue; + if (sc->sc_rxba_data[i].tid == tid) + return &sc->sc_rxba_data[i]; + } + + return NULL; +} + +int +iwx_sta_rx_agg_baid_cfg_cmd(struct iwx_softc *sc, struct ieee80211_node *ni, + uint8_t tid, uint16_t ssn, uint16_t winsize, int timeout_val, int start, + uint8_t *baid) +{ + struct iwx_rx_baid_cfg_cmd cmd; + uint32_t new_baid = 0; + int err; + + splassert(IPL_NET); + + memset(&cmd, 0, sizeof(cmd)); + + if (start) { + cmd.action = IWX_RX_BAID_ACTION_ADD; + cmd.alloc.sta_id_mask = htole32(1 << IWX_STATION_ID); + cmd.alloc.tid = tid; + cmd.alloc.ssn = htole16(ssn); + cmd.alloc.win_size = htole16(winsize); + } else { + struct iwx_rxba_data *rxba; + + rxba = iwx_find_rxba_data(sc, tid); + if (rxba == NULL) + return ENOENT; + *baid = rxba->baid; + + cmd.action = IWX_RX_BAID_ACTION_REMOVE; + if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RX_BAID_ALLOCATION_CONFIG_CMD) == 1) { + cmd.remove_v1.baid = rxba->baid; + } else { + cmd.remove.sta_id_mask = htole32(1 << IWX_STATION_ID); + cmd.remove.tid = tid; + } + } + + err = iwx_send_cmd_pdu_status(sc, IWX_WIDE_ID(IWX_DATA_PATH_GROUP, + IWX_RX_BAID_ALLOCATION_CONFIG_CMD), sizeof(cmd), &cmd, &new_baid); + if (err) + return err; + + if (start) { + if (new_baid >= nitems(sc->sc_rxba_data)) + return ERANGE; + *baid = new_baid; + } + + return 0; +} + +int +iwx_sta_rx_agg_sta_cmd(struct iwx_softc *sc, struct ieee80211_node *ni, + uint8_t tid, uint16_t ssn, uint16_t winsize, int timeout_val, int start, + uint8_t *baid) { - struct ieee80211com *ic = &sc->sc_ic; struct iwx_add_sta_cmd cmd; struct iwx_node *in = (void *)ni; - int err, s; + int err; uint32_t status; - struct iwx_rxba_data *rxba = NULL; - uint8_t baid = 0; - - s = splnet(); - if (start && sc->sc_rx_ba_sessions >= IWX_MAX_RX_BA_SESSIONS) { - ieee80211_addba_req_refuse(ic, ni, tid); - splx(s); - return; - } + splassert(IPL_NET); memset(&cmd, 0, sizeof(cmd)); @@ -3326,6 +3450,13 @@ iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid, cmd.add_immediate_ba_ssn = htole16(ssn); cmd.rx_ba_window = htole16(winsize); } else { + struct iwx_rxba_data *rxba; + + rxba = iwx_find_rxba_data(sc, tid); + if (rxba == NULL) + return ENOENT; + *baid = rxba->baid; + cmd.remove_immediate_ba_tid = (uint8_t)tid; } cmd.modify_mask = start ? IWX_STA_MODIFY_ADD_BA_TID : @@ -3334,30 +3465,60 @@ iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid, status = IWX_ADD_STA_SUCCESS; err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA, sizeof(cmd), &cmd, &status); + if (err) + return err; - if (err || (status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS) { - if (start) - ieee80211_addba_req_refuse(ic, ni, tid); + if ((status & IWX_ADD_STA_STATUS_MASK) != IWX_ADD_STA_SUCCESS) + return EIO; + + if (!(status & IWX_ADD_STA_BAID_VALID_MASK)) + return EINVAL; + + if (start) { + *baid = (status & IWX_ADD_STA_BAID_MASK) >> + IWX_ADD_STA_BAID_SHIFT; + if (*baid == IWX_RX_REORDER_DATA_INVALID_BAID || + *baid >= nitems(sc->sc_rxba_data)) + return ERANGE; + } + + return 0; +} + +void +iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid, + uint16_t ssn, uint16_t winsize, int timeout_val, int start) +{ + struct ieee80211com *ic = &sc->sc_ic; + int err, s; + struct iwx_rxba_data *rxba = NULL; + uint8_t baid = 0; + + s = splnet(); + + if (start && sc->sc_rx_ba_sessions >= IWX_MAX_RX_BA_SESSIONS) { + ieee80211_addba_req_refuse(ic, ni, tid); splx(s); return; } + if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_BAID_ML_SUPPORT)) { + err = iwx_sta_rx_agg_baid_cfg_cmd(sc, ni, tid, ssn, winsize, + timeout_val, start, &baid); + } else { + err = iwx_sta_rx_agg_sta_cmd(sc, ni, tid, ssn, winsize, + timeout_val, start, &baid); + } + if (err) { + ieee80211_addba_req_refuse(ic, ni, tid); + splx(s); + return; + } + + rxba = &sc->sc_rxba_data[baid]; + /* Deaggregation is done in hardware. */ if (start) { - if (!(status & IWX_ADD_STA_BAID_VALID_MASK)) { - ieee80211_addba_req_refuse(ic, ni, tid); - splx(s); - return; - } - baid = (status & IWX_ADD_STA_BAID_MASK) >> - IWX_ADD_STA_BAID_SHIFT; - if (baid == IWX_RX_REORDER_DATA_INVALID_BAID || - baid >= nitems(sc->sc_rxba_data)) { - ieee80211_addba_req_refuse(ic, ni, tid); - splx(s); - return; - } - rxba = &sc->sc_rxba_data[baid]; if (rxba->baid != IWX_RX_REORDER_DATA_INVALID_BAID) { ieee80211_addba_req_refuse(ic, ni, tid); splx(s); @@ -3378,19 +3539,8 @@ iwx_sta_rx_agg(struct iwx_softc *sc, struct ieee80211_node *ni, uint8_t tid, ba = &ni->ni_rx_ba[tid]; ba->ba_timeout_val = 0; } - } else { - int i; - for (i = 0; i < nitems(sc->sc_rxba_data); i++) { - rxba = &sc->sc_rxba_data[i]; - if (rxba->baid == - IWX_RX_REORDER_DATA_INVALID_BAID) - continue; - if (rxba->tid != tid) - continue; - iwx_clear_reorder_buffer(sc, rxba); - break; - } - } + } else + iwx_clear_reorder_buffer(sc, rxba); if (start) { sc->sc_rx_ba_sessions++; @@ -4255,7 +4405,7 @@ iwx_run_init_mvm_ucode(struct iwx_softc *sc, int readnvm) if (IEEE80211_ADDR_EQ(etheranyaddr, sc->sc_ic.ic_myaddr)) IEEE80211_ADDR_COPY(sc->sc_ic.ic_myaddr, sc->sc_nvm.hw_addr); - + } return 0; } @@ -4516,7 +4666,7 @@ iwx_rx_frame(struct iwx_softc *sc, struct mbuf *m, int chanidx, struct ieee80211_frame *wh; struct ieee80211_node *ni; - if (chanidx < 0 || chanidx >= nitems(ic->ic_channels)) + if (chanidx < 0 || chanidx >= nitems(ic->ic_channels)) chanidx = ieee80211_chan2ieee(ic, ic->ic_ibss_chan); wh = mtod(m, struct ieee80211_frame *); @@ -4533,6 +4683,8 @@ iwx_rx_frame(struct iwx_softc *sc, struct mbuf *m, int chanidx, if (sc->sc_drvbpf != NULL) { struct iwx_rx_radiotap_header *tap = &sc->sc_rxtap; uint16_t chan_flags; + int have_legacy_rate = 1; + uint8_t mcs, rate; tap->wr_flags = 0; if (is_shortpre) @@ -4551,14 +4703,36 @@ iwx_rx_frame(struct iwx_softc *sc, struct mbuf *m, int chanidx, tap->wr_dbm_antsignal = (int8_t)rxi->rxi_rssi; tap->wr_dbm_antnoise = (int8_t)sc->sc_noise; tap->wr_tsft = device_timestamp; - if (rate_n_flags & IWX_RATE_MCS_HT_MSK) { - uint8_t mcs = (rate_n_flags & - (IWX_RATE_HT_MCS_RATE_CODE_MSK | - IWX_RATE_HT_MCS_NSS_MSK)); + if (sc->sc_rate_n_flags_version >= 2) { + uint32_t mod_type = (rate_n_flags & + IWX_RATE_MCS_MOD_TYPE_MSK); + const struct ieee80211_rateset *rs = NULL; + uint32_t ridx; + have_legacy_rate = (mod_type == IWX_RATE_MCS_CCK_MSK || + mod_type == IWX_RATE_MCS_LEGACY_OFDM_MSK); + mcs = (rate_n_flags & IWX_RATE_HT_MCS_CODE_MSK); + ridx = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK); + if (mod_type == IWX_RATE_MCS_CCK_MSK) + rs = &ieee80211_std_rateset_11b; + else if (mod_type == IWX_RATE_MCS_LEGACY_OFDM_MSK) + rs = &ieee80211_std_rateset_11a; + if (rs && ridx < rs->rs_nrates) { + rate = (rs->rs_rates[ridx] & + IEEE80211_RATE_VAL); + } else + rate = 0; + } else { + have_legacy_rate = ((rate_n_flags & + (IWX_RATE_MCS_HT_MSK_V1 | + IWX_RATE_MCS_VHT_MSK_V1)) == 0); + mcs = (rate_n_flags & + (IWX_RATE_HT_MCS_RATE_CODE_MSK_V1 | + IWX_RATE_HT_MCS_NSS_MSK_V1)); + rate = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1); + } + if (!have_legacy_rate) { tap->wr_rate = (0x80 | mcs); } else { - uint8_t rate = (rate_n_flags & - IWX_RATE_LEGACY_RATE_MSK); switch (rate) { /* CCK rates. */ case 10: tap->wr_rate = 2; break; @@ -5044,7 +5218,7 @@ iwx_rx_mpdu_mq(struct iwx_softc *sc, struct mbuf *m, void *pktdata, /* Padding is inserted after the IV. */ hdrlen += IEEE80211_CCMP_HDRLEN; } - + memmove(m->m_data + 2, m->m_data, hdrlen); m_adj(m, 2); } @@ -5080,7 +5254,7 @@ iwx_rx_mpdu_mq(struct iwx_softc *sc, struct mbuf *m, void *pktdata, struct ieee80211_qosframe *qwh = mtod(m, struct ieee80211_qosframe *); qwh->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU); - } + } } /* @@ -5387,7 +5561,7 @@ uint8_t iwx_get_vht_ctrl_pos(struct ieee80211com *ic, struct ieee80211_channel *chan) { int center_idx = ic->ic_bss->ni_vht_chan_center_freq_idx0; - int primary_idx = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); + int primary_idx = ic->ic_bss->ni_primary_chan; /* * The FW is expected to check the control channel position only * when in HT/VHT and the channel width is not 20MHz. Return @@ -5416,9 +5590,9 @@ iwx_get_vht_ctrl_pos(struct ieee80211com *ic, struct ieee80211_channel *chan) } int -iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, +iwx_phy_ctxt_cmd_uhb_v3_v4(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, uint8_t chains_static, uint8_t chains_dynamic, uint32_t action, uint8_t sco, - uint8_t vht_chan_width) + uint8_t vht_chan_width, int cmdver) { struct ieee80211com *ic = &sc->sc_ic; struct iwx_phy_context_cmd_uhb cmd; @@ -5460,21 +5634,25 @@ iwx_phy_ctxt_cmd_uhb_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, 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); + if (cmdver < 4 && iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RLC_CONFIG_CMD) != 2) { + 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_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, +iwx_phy_ctxt_cmd_v3_v4(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, uint8_t chains_static, uint8_t chains_dynamic, uint32_t action, uint8_t sco, - uint8_t vht_chan_width) + uint8_t vht_chan_width, int cmdver) { struct ieee80211com *ic = &sc->sc_ic; struct iwx_phy_context_cmd cmd; @@ -5516,13 +5694,17 @@ iwx_phy_ctxt_cmd_v3(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, 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); + if (cmdver < 4 && iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RLC_CONFIG_CMD) != 2) { + 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); } @@ -5535,8 +5717,8 @@ iwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, int cmdver; cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_PHY_CONTEXT_CMD); - if (cmdver != 3) { - printf("%s: firmware does not support phy-context-cmd v3\n", + if (cmdver != 3 && cmdver != 4) { + printf("%s: firmware does not support phy-context-cmd v3/v4\n", DEVNAME(sc)); return ENOTSUP; } @@ -5549,12 +5731,12 @@ iwx_phy_ctxt_cmd(struct iwx_softc *sc, struct iwx_phy_ctxt *ctxt, * variant of the phy context 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, sco, vht_chan_width); + return iwx_phy_ctxt_cmd_uhb_v3_v4(sc, ctxt, chains_static, + chains_dynamic, action, sco, vht_chan_width, cmdver); } - return iwx_phy_ctxt_cmd_v3(sc, ctxt, chains_static, chains_dynamic, - action, sco, vht_chan_width); + return iwx_phy_ctxt_cmd_v3_v4(sc, ctxt, chains_static, chains_dynamic, + action, sco, vht_chan_width, cmdver); } int @@ -5717,7 +5899,7 @@ iwx_send_cmd(struct iwx_softc *sc, struct iwx_host_cmd *hcmd) } else if (generation == sc->sc_generation) { free(sc->sc_cmd_resp_pkt[idx], M_DEVBUF, sc->sc_cmd_resp_len[idx]); - sc->sc_cmd_resp_pkt[idx] = NULL; + sc->sc_cmd_resp_pkt[idx] = NULL; } } out: @@ -5822,6 +6004,36 @@ iwx_cmd_done(struct iwx_softc *sc, int qid, int idx, int code) ring->queued--; } +uint32_t +iwx_fw_rateidx_ofdm(uint8_t rval) +{ + /* Firmware expects indices which match our 11a rate set. */ + const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11a; + int i; + + for (i = 0; i < rs->rs_nrates; i++) { + if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rval) + return i; + } + + return 0; +} + +uint32_t +iwx_fw_rateidx_cck(uint8_t rval) +{ + /* Firmware expects indices which match our 11b rate set. */ + const struct ieee80211_rateset *rs = &ieee80211_std_rateset_11b; + int i; + + for (i = 0; i < rs->rs_nrates; i++) { + if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rval) + return i; + } + + return 0; +} + /* * Determine the Tx command flags and Tx rate+flags to use. * Return the selected Tx rate. @@ -5837,6 +6049,7 @@ iwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in, int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; int min_ridx = iwx_rval2ridx(ieee80211_min_basic_rate(ic)); int ridx, rate_flags; + uint8_t rval; *flags = 0; @@ -5845,16 +6058,9 @@ iwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in, /* for non-data, use the lowest supported rate */ ridx = min_ridx; *flags |= IWX_TX_FLAGS_CMD_RATE; - } else if (ic->ic_fixed_mcs != -1) { - ridx = sc->sc_fixed_ridx; - *flags |= IWX_TX_FLAGS_CMD_RATE; - } else if (ic->ic_fixed_rate != -1) { - ridx = sc->sc_fixed_ridx; - *flags |= IWX_TX_FLAGS_CMD_RATE; } else if (ni->ni_flags & IEEE80211_NODE_HT) { ridx = iwx_mcs2ridx[ni->ni_txmcs]; } else { - uint8_t rval; rval = (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL); ridx = iwx_rval2ridx(rval); if (ridx < min_ridx) @@ -5866,45 +6072,42 @@ iwx_tx_fill_cmd(struct iwx_softc *sc, struct iwx_node *in, *flags |= IWX_TX_FLAGS_HIGH_PRI; rinfo = &iwx_rates[ridx]; - if (iwx_is_mimo_ht_plcp(rinfo->ht_plcp)) - rate_flags = IWX_RATE_MCS_ANT_AB_MSK; - else - rate_flags = IWX_RATE_MCS_ANT_A_MSK; - if (IWX_RIDX_IS_CCK(ridx)) - rate_flags |= IWX_RATE_MCS_CCK_MSK; - if ((ni->ni_flags & IEEE80211_NODE_HT) && - type == IEEE80211_FC0_TYPE_DATA && - rinfo->ht_plcp != IWX_RATE_HT_SISO_MCS_INV_PLCP) { - uint8_t sco = IEEE80211_HTOP0_SCO_SCN; - uint8_t vht_chan_width = IEEE80211_VHTOP0_CHAN_WIDTH_HT; - if ((ni->ni_flags & IEEE80211_NODE_VHT) && - IEEE80211_CHAN_80MHZ_ALLOWED(ni->ni_chan) && - ieee80211_node_supports_vht_chan80(ni)) - vht_chan_width = IEEE80211_VHTOP0_CHAN_WIDTH_80; - else if (IEEE80211_CHAN_40MHZ_ALLOWED(ni->ni_chan) && - ieee80211_node_supports_ht_chan40(ni)) - sco = (ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK); - if (ni->ni_flags & IEEE80211_NODE_VHT) - rate_flags |= IWX_RATE_MCS_VHT_MSK; + + /* + * Do not fill rate_n_flags if firmware controls the Tx rate. + * For data frames we rely on Tx rate scaling in firmware by default. + */ + if ((*flags & IWX_TX_FLAGS_CMD_RATE) == 0) { + *rate_n_flags = 0; + return rinfo; + } + + /* + * Forcing a CCK/OFDM legacy rate is important for management frames. + * Association will only succeed if we do this correctly. + */ + rate_flags = IWX_RATE_MCS_ANT_A_MSK; + if (IWX_RIDX_IS_CCK(ridx)) { + if (sc->sc_rate_n_flags_version >= 2) + rate_flags |= IWX_RATE_MCS_CCK_MSK; else - rate_flags |= IWX_RATE_MCS_HT_MSK; - if (vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80 && - in->in_phyctxt != NULL && - in->in_phyctxt->vht_chan_width == vht_chan_width) { - rate_flags |= IWX_RATE_MCS_CHAN_WIDTH_80; - if (ieee80211_node_supports_vht_sgi80(ni)) - rate_flags |= IWX_RATE_MCS_SGI_MSK; - } else if ((sco == IEEE80211_HTOP0_SCO_SCA || - sco == IEEE80211_HTOP0_SCO_SCB) && - in->in_phyctxt != NULL && in->in_phyctxt->sco == sco) { - rate_flags |= IWX_RATE_MCS_CHAN_WIDTH_40; - if (ieee80211_node_supports_ht_sgi40(ni)) - rate_flags |= IWX_RATE_MCS_SGI_MSK; - } else if (ieee80211_node_supports_ht_sgi20(ni)) - rate_flags |= IWX_RATE_MCS_SGI_MSK; - *rate_n_flags = rate_flags | rinfo->ht_plcp; + rate_flags |= IWX_RATE_MCS_CCK_MSK_V1; + } else if (sc->sc_rate_n_flags_version >= 2) + rate_flags |= IWX_RATE_MCS_LEGACY_OFDM_MSK; + + rval = (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL); + if (sc->sc_rate_n_flags_version >= 2) { + if (rate_flags & IWX_RATE_MCS_LEGACY_OFDM_MSK) { + rate_flags |= (iwx_fw_rateidx_ofdm(rval) & + IWX_RATE_LEGACY_RATE_MSK); + } else { + rate_flags |= (iwx_fw_rateidx_cck(rval) & + IWX_RATE_LEGACY_RATE_MSK); + } } else - *rate_n_flags = rate_flags | rinfo->plcp; + rate_flags |= rinfo->plcp; + + *rate_n_flags = rate_flags; return rinfo; } @@ -6608,7 +6811,7 @@ iwx_rm_sta(struct iwx_softc *sc, struct iwx_node *in) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = &in->in_ni; - int err, i; + int err, i, cmd_ver; err = iwx_flush_sta(sc, in); if (err) { @@ -6616,6 +6819,33 @@ iwx_rm_sta(struct iwx_softc *sc, struct iwx_node *in) DEVNAME(sc), err); return err; } + + /* + * New SCD_QUEUE_CONFIG API requires explicit queue removal + * before a station gets removed. + */ + cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_SCD_QUEUE_CONFIG_CMD); + if (cmd_ver != 0 && cmd_ver != IWX_FW_CMD_VER_UNKNOWN) { + err = iwx_disable_mgmt_queue(sc); + if (err) + return err; + for (i = IWX_FIRST_AGG_TX_QUEUE; + i < IWX_LAST_AGG_TX_QUEUE; i++) { + struct iwx_tx_ring *ring = &sc->txq[i]; + if ((sc->qenablemsk & (1 << i)) == 0) + continue; + err = iwx_disable_txq(sc, IWX_STATION_ID, + ring->qid, ring->tid); + if (err) { + printf("%s: could not disable Tx queue %d " + "(error %d)\n", DEVNAME(sc), ring->qid, + err); + return err; + } + } + } + err = iwx_rm_sta_cmd(sc, in); if (err) { printf("%s: could not remove STA (error %d)\n", @@ -6646,7 +6876,7 @@ iwx_rm_sta(struct iwx_softc *sc, struct iwx_node *in) uint8_t iwx_umac_scan_fill_channels(struct iwx_softc *sc, struct iwx_scan_channel_cfg_umac *chan, size_t chan_nitems, - int n_ssids, int bgscan) + int n_ssids, uint32_t channel_cfg_flags) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *c; @@ -6677,8 +6907,8 @@ iwx_umac_scan_fill_channels(struct iwx_softc *sc, chan->v1.iter_count = 1; chan->v1.iter_interval = htole16(0); } - if (n_ssids != 0 && !bgscan) - chan->flags = htole32(1 << 0); /* select SSID 0 */ + + chan->flags = htole32(channel_cfg_flags); chan++; nchan++; } @@ -6737,7 +6967,7 @@ iwx_fill_probe_req(struct iwx_softc *sc, struct iwx_scan_probe_req *preq) frm = ieee80211_add_xrates(frm, rs); remain -= frm - pos; - if (isset(sc->sc_enabled_capa, + if (isset(sc->sc_enabled_capa, IWX_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) { if (remain < 3) return ENOBUFS; @@ -6919,12 +7149,12 @@ iwx_scan_umac_fill_general_p_v10(struct iwx_softc *sc, 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) + int n_ssid) { 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); + nitems(cp->channel_config), n_ssid, channel_cfg_flags); cp->n_aps_override[0] = IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY; cp->n_aps_override[1] = IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS; @@ -6979,7 +7209,7 @@ iwx_umac_scan_v14(struct iwx_softc *sc, int bgscan) } iwx_scan_umac_fill_ch_p_v6(sc, &scan_p->channel_params, bitmap_ssid, - n_ssid, bgscan); + n_ssid); hcmd.len[0] = sizeof(*cmd); hcmd.data[0] = (void *)cmd; @@ -7062,7 +7292,7 @@ iwx_ack_rates(struct iwx_softc *sc, struct iwx_node *in, int *cck_rates, } for (i = IWX_FIRST_OFDM_RATE; i <= IWX_LAST_NON_HT_RATE; i++) { if ((iwx_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0) - continue; + continue; ofdm |= (1 << (i - IWX_FIRST_OFDM_RATE)); if (lowest_present_ofdm == -1 || lowest_present_ofdm > i) lowest_present_ofdm = i; @@ -7227,15 +7457,16 @@ iwx_mac_ctxt_cmd_fill_sta(struct iwx_softc *sc, struct iwx_node *in, tsf = letoh64(tsf); sta->is_assoc = htole32(assoc); - sta->dtim_time = htole32(ni->ni_rstamp + dtim_off); - sta->dtim_tsf = htole64(tsf + dtim_off); + if (assoc) { + sta->dtim_time = htole32(ni->ni_rstamp + dtim_off); + sta->dtim_tsf = htole64(tsf + dtim_off); + sta->assoc_beacon_arrive_time = htole32(ni->ni_rstamp); + } sta->bi = htole32(ni->ni_intval); - sta->bi_reciprocal = htole32(iwx_reciprocal(ni->ni_intval)); sta->dtim_interval = htole32(ni->ni_intval * ni->ni_dtimperiod); - sta->dtim_reciprocal = htole32(iwx_reciprocal(sta->dtim_interval)); + sta->data_policy = htole32(0); sta->listen_interval = htole32(10); sta->assoc_id = htole32(ni->ni_associd); - sta->assoc_beacon_arrive_time = htole32(ni->ni_rstamp); } int @@ -7268,15 +7499,14 @@ iwx_mac_ctxt_cmd(struct iwx_softc *sc, struct iwx_node *in, uint32_t action, IWX_MAC_FILTER_IN_BEACON | IWX_MAC_FILTER_IN_PROBE_REQUEST | IWX_MAC_FILTER_IN_CRC32); - } else if (!assoc || !ni->ni_associd || !ni->ni_dtimperiod) - /* + } else if (!assoc || !ni->ni_associd || !ni->ni_dtimperiod) { + /* * Allow beacons to pass through as long as we are not * associated or we do not have dtim period information. */ cmd.filter_flags |= htole32(IWX_MAC_FILTER_IN_BEACON); - else - iwx_mac_ctxt_cmd_fill_sta(sc, in, &cmd.sta, assoc); - + } + iwx_mac_ctxt_cmd_fill_sta(sc, in, &cmd.sta, assoc); return iwx_send_cmd_pdu(sc, IWX_MAC_CONTEXT_CMD, 0, sizeof(cmd), &cmd); } @@ -7371,7 +7601,7 @@ iwx_scan(struct iwx_softc *sc) } int -iwx_bgscan(struct ieee80211com *ic) +iwx_bgscan(struct ieee80211com *ic) { struct iwx_softc *sc = IC2IFP(ic)->if_softc; int err; @@ -7379,11 +7609,6 @@ iwx_bgscan(struct ieee80211com *ic) if (sc->sc_flags & IWX_FLAG_SCANNING) return 0; -#ifdef __HAIKU__ - // Stops working after 40 scans and crashes the firmware, so let's not do it. - return EOPNOTSUPP; -#endif - err = iwx_umac_scan_v14(sc, 1); if (err) { printf("%s: could not initiate scan\n", DEVNAME(sc)); @@ -7403,7 +7628,7 @@ iwx_bgscan_done(struct ieee80211com *ic, free(sc->bgscan_unref_arg, M_DEVBUF, sc->bgscan_unref_arg_size); sc->bgscan_unref_arg = arg; sc->bgscan_unref_arg_size = arg_size; - iwx_add_task(sc, sc->sc_nswq, &sc->bgscan_done_task); + iwx_add_task(sc, systq, &sc->bgscan_done_task); } void @@ -7509,6 +7734,30 @@ iwx_enable_mgmt_queue(struct iwx_softc *sc) return 0; } +int +iwx_disable_mgmt_queue(struct iwx_softc *sc) +{ + int err, cmd_ver; + + /* Explicit removal is only required with old SCD_QUEUE_CFG command. */ + cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_SCD_QUEUE_CONFIG_CMD); + if (cmd_ver == 0 || cmd_ver == IWX_FW_CMD_VER_UNKNOWN) + return 0; + + sc->first_data_qid = IWX_DQA_CMD_QUEUE + 1; + + err = iwx_disable_txq(sc, IWX_STATION_ID, sc->first_data_qid, + IWX_MGMT_TID); + if (err) { + printf("%s: could not disable Tx queue %d (error %d)\n", + DEVNAME(sc), sc->first_data_qid, err); + return err; + } + + return 0; +} + int iwx_rs_rval2idx(uint8_t rval) { @@ -7571,16 +7820,16 @@ iwx_rs_vht_rates(struct iwx_softc *sc, struct ieee80211_node *ni, int num_ss) /* Should not happen; Values above cover the possible range. */ panic("invalid VHT Rx MCS value %u", rx_mcs); } - + return ((1 << (max_mcs + 1)) - 1); } int -iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in) +iwx_rs_init_v3(struct iwx_softc *sc, struct iwx_node *in) { struct ieee80211_node *ni = &in->in_ni; struct ieee80211_rateset *rs = &ni->ni_rates; - struct iwx_tlc_config_cmd cfg_cmd; + struct iwx_tlc_config_cmd_v3 cfg_cmd; uint32_t cmd_id; int i; size_t cmd_size = sizeof(cfg_cmd); @@ -7597,16 +7846,16 @@ iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in) if (ni->ni_flags & IEEE80211_NODE_VHT) { cfg_cmd.mode = IWX_TLC_MNG_MODE_VHT; - cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_HT_BW_NONE_160] = + cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_vht_rates(sc, ni, 1)); - cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_HT_BW_NONE_160] = + cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_vht_rates(sc, ni, 2)); } else if (ni->ni_flags & IEEE80211_NODE_HT) { cfg_cmd.mode = IWX_TLC_MNG_MODE_HT; - cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_HT_BW_NONE_160] = + cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_ht_rates(sc, ni, IEEE80211_HT_RATESET_SISO)); - cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_HT_BW_NONE_160] = + cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = htole16(iwx_rs_ht_rates(sc, ni, IEEE80211_HT_RATESET_MIMO2)); } else @@ -7643,6 +7892,86 @@ iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in) return iwx_send_cmd_pdu(sc, cmd_id, IWX_CMD_ASYNC, cmd_size, &cfg_cmd); } +int +iwx_rs_init_v4(struct iwx_softc *sc, struct iwx_node *in) +{ + struct ieee80211_node *ni = &in->in_ni; + struct ieee80211_rateset *rs = &ni->ni_rates; + struct iwx_tlc_config_cmd_v4 cfg_cmd; + uint32_t cmd_id; + int i; + size_t cmd_size = sizeof(cfg_cmd); + + memset(&cfg_cmd, 0, sizeof(cfg_cmd)); + + for (i = 0; i < rs->rs_nrates; i++) { + uint8_t rval = rs->rs_rates[i] & IEEE80211_RATE_VAL; + int idx = iwx_rs_rval2idx(rval); + if (idx == -1) + return EINVAL; + cfg_cmd.non_ht_rates |= (1 << idx); + } + + if (ni->ni_flags & IEEE80211_NODE_VHT) { + cfg_cmd.mode = IWX_TLC_MNG_MODE_VHT; + cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = + htole16(iwx_rs_vht_rates(sc, ni, 1)); + cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = + htole16(iwx_rs_vht_rates(sc, ni, 2)); + } else if (ni->ni_flags & IEEE80211_NODE_HT) { + cfg_cmd.mode = IWX_TLC_MNG_MODE_HT; + cfg_cmd.ht_rates[IWX_TLC_NSS_1][IWX_TLC_MCS_PER_BW_80] = + htole16(iwx_rs_ht_rates(sc, ni, + IEEE80211_HT_RATESET_SISO)); + cfg_cmd.ht_rates[IWX_TLC_NSS_2][IWX_TLC_MCS_PER_BW_80] = + htole16(iwx_rs_ht_rates(sc, ni, + IEEE80211_HT_RATESET_MIMO2)); + } else + cfg_cmd.mode = IWX_TLC_MNG_MODE_NON_HT; + + cfg_cmd.sta_id = IWX_STATION_ID; + if (in->in_phyctxt->vht_chan_width == IEEE80211_VHTOP0_CHAN_WIDTH_80) + cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_80MHZ; + else if (in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCA || + in->in_phyctxt->sco == IEEE80211_HTOP0_SCO_SCB) + cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_40MHZ; + else + cfg_cmd.max_ch_width = IWX_TLC_MNG_CH_WIDTH_20MHZ; + cfg_cmd.chains = IWX_TLC_MNG_CHAIN_A_MSK | IWX_TLC_MNG_CHAIN_B_MSK; + if (ni->ni_flags & IEEE80211_NODE_VHT) + cfg_cmd.max_mpdu_len = htole16(3895); + else + cfg_cmd.max_mpdu_len = htole16(3839); + if (ni->ni_flags & IEEE80211_NODE_HT) { + if (ieee80211_node_supports_ht_sgi20(ni)) { + cfg_cmd.sgi_ch_width_supp |= (1 << + IWX_TLC_MNG_CH_WIDTH_20MHZ); + } + if (ieee80211_node_supports_ht_sgi40(ni)) { + cfg_cmd.sgi_ch_width_supp |= (1 << + IWX_TLC_MNG_CH_WIDTH_40MHZ); + } + } + if ((ni->ni_flags & IEEE80211_NODE_VHT) && + ieee80211_node_supports_vht_sgi80(ni)) + cfg_cmd.sgi_ch_width_supp |= (1 << IWX_TLC_MNG_CH_WIDTH_80MHZ); + + 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, cmd_size, &cfg_cmd); +} + +int +iwx_rs_init(struct iwx_softc *sc, struct iwx_node *in) +{ + int cmd_ver; + + cmd_ver = iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_TLC_MNG_CONFIG_CMD); + if (cmd_ver == 4) + return iwx_rs_init_v4(sc, in); + return iwx_rs_init_v3(sc, in); +} + void iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif) { @@ -7650,43 +7979,107 @@ iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif) struct ieee80211_node *ni = ic->ic_bss; struct ieee80211_rateset *rs = &ni->ni_rates; uint32_t rate_n_flags; - int i; + uint8_t plcp, rval; + int i, cmd_ver, rate_n_flags_ver2 = 0; if (notif->sta_id != IWX_STATION_ID || (le32toh(notif->flags) & IWX_TLC_NOTIF_FLAG_RATE) == 0) return; rate_n_flags = le32toh(notif->rate); - if (rate_n_flags & IWX_RATE_MCS_VHT_MSK) { - ni->ni_txmcs = (rate_n_flags & IWX_RATE_VHT_MCS_RATE_CODE_MSK); - ni->ni_vht_ss = ((rate_n_flags & IWX_RATE_VHT_MCS_NSS_MSK) >> - IWX_RATE_VHT_MCS_NSS_POS) + 1; - } else if (rate_n_flags & IWX_RATE_MCS_HT_MSK) { - ni->ni_txmcs = (rate_n_flags & - (IWX_RATE_HT_MCS_RATE_CODE_MSK | - IWX_RATE_HT_MCS_NSS_MSK)); + + cmd_ver = iwx_lookup_notif_ver(sc, IWX_DATA_PATH_GROUP, + IWX_TLC_MNG_UPDATE_NOTIF); + if (cmd_ver != IWX_FW_CMD_VER_UNKNOWN && cmd_ver >= 3) + rate_n_flags_ver2 = 1; + if (rate_n_flags_ver2) { + uint32_t mod_type = (rate_n_flags & IWX_RATE_MCS_MOD_TYPE_MSK); + if (mod_type == IWX_RATE_MCS_VHT_MSK) { + ni->ni_txmcs = (rate_n_flags & + IWX_RATE_HT_MCS_CODE_MSK); + ni->ni_vht_ss = ((rate_n_flags & + IWX_RATE_MCS_NSS_MSK) >> + IWX_RATE_MCS_NSS_POS) + 1; + return; + } else if (mod_type == IWX_RATE_MCS_HT_MSK) { + ni->ni_txmcs = IWX_RATE_HT_MCS_INDEX(rate_n_flags); + return; + } } else { - uint8_t plcp = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK); - uint8_t rval = 0; + if (rate_n_flags & IWX_RATE_MCS_VHT_MSK_V1) { + ni->ni_txmcs = (rate_n_flags & + IWX_RATE_VHT_MCS_RATE_CODE_MSK); + ni->ni_vht_ss = ((rate_n_flags & + IWX_RATE_VHT_MCS_NSS_MSK) >> + IWX_RATE_VHT_MCS_NSS_POS) + 1; + return; + } else if (rate_n_flags & IWX_RATE_MCS_HT_MSK_V1) { + ni->ni_txmcs = (rate_n_flags & + (IWX_RATE_HT_MCS_RATE_CODE_MSK_V1 | + IWX_RATE_HT_MCS_NSS_MSK_V1)); + return; + } + } + + if (rate_n_flags_ver2) { + const struct ieee80211_rateset *rs; + uint32_t ridx = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK); + if (rate_n_flags & IWX_RATE_MCS_LEGACY_OFDM_MSK) + rs = &ieee80211_std_rateset_11a; + else + rs = &ieee80211_std_rateset_11b; + if (ridx < rs->rs_nrates) + rval = (rs->rs_rates[ridx] & IEEE80211_RATE_VAL); + else + rval = 0; + } else { + plcp = (rate_n_flags & IWX_RATE_LEGACY_RATE_MSK_V1); + + rval = 0; for (i = IWX_RATE_1M_INDEX; i < nitems(iwx_rates); i++) { if (iwx_rates[i].plcp == plcp) { rval = iwx_rates[i].rate; break; } } - if (rval) { - uint8_t rv; - for (i = 0; i < rs->rs_nrates; i++) { - rv = rs->rs_rates[i] & IEEE80211_RATE_VAL; - if (rv == rval) { - ni->ni_txrate = i; - break; - } + } + + if (rval) { + uint8_t rv; + for (i = 0; i < rs->rs_nrates; i++) { + rv = rs->rs_rates[i] & IEEE80211_RATE_VAL; + if (rv == rval) { + ni->ni_txrate = i; + break; } } } } +int +iwx_phy_send_rlc(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt, + uint8_t chains_static, uint8_t chains_dynamic) +{ + struct iwx_rlc_config_cmd cmd; + uint32_t cmd_id; + uint8_t active_cnt, idle_cnt; + + memset(&cmd, 0, sizeof(cmd)); + + idle_cnt = chains_static; + active_cnt = chains_dynamic; + + cmd.phy_id = htole32(phyctxt->id); + cmd.rlc.rx_chain_info = htole32(iwx_fw_valid_rx_ant(sc) << + IWX_PHY_RX_CHAIN_VALID_POS); + cmd.rlc.rx_chain_info |= htole32(idle_cnt << IWX_PHY_RX_CHAIN_CNT_POS); + cmd.rlc.rx_chain_info |= htole32(active_cnt << + IWX_PHY_RX_CHAIN_MIMO_CNT_POS); + + cmd_id = iwx_cmd_id(IWX_RLC_CONFIG_CMD, IWX_DATA_PATH_GROUP, 2); + return iwx_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd); +} + int iwx_phy_ctxt_update(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt, struct ieee80211_channel *chan, uint8_t chains_static, @@ -7731,6 +8124,12 @@ iwx_phy_ctxt_update(struct iwx_softc *sc, struct iwx_phy_ctxt *phyctxt, phyctxt->sco = sco; phyctxt->vht_chan_width = vht_chan_width; + + if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RLC_CONFIG_CMD) == 2) + return iwx_phy_send_rlc(sc, phyctxt, + chains_static, chains_dynamic); + return 0; } @@ -7758,7 +8157,7 @@ iwx_auth(struct iwx_softc *sc) return err; } in->in_phyctxt = &sc->sc_phyctxt[0]; - IEEE80211_ADDR_COPY(in->in_macaddr, in->in_ni.ni_macaddr); + IEEE80211_ADDR_COPY(in->in_macaddr, in->in_ni.ni_macaddr); err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_ADD, 0); if (err) { @@ -7799,17 +8198,20 @@ iwx_auth(struct iwx_softc *sc) err = iwx_clear_statistics(sc); if (err) - goto rm_sta; + goto rm_mgmt_queue; /* * Prevent the FW from wandering off channel during association * by "protecting" the session with a time event. */ if (in->in_ni.ni_intval) - duration = in->in_ni.ni_intval * 2; + duration = in->in_ni.ni_intval * 9; else - duration = IEEE80211_DUR_TU; + duration = 900; return iwx_schedule_session_protection(sc, in, duration); +rm_mgmt_queue: + if (generation == sc->sc_generation) + iwx_disable_mgmt_queue(sc); rm_sta: if (generation == sc->sc_generation) { iwx_rm_sta_cmd(sc, in); @@ -7963,7 +8365,7 @@ iwx_run(struct iwx_softc *sc) return err; } #ifdef notyet - /* + /* * Disabled for now. Default beacon filter settings * prevent net80211 from getting ERP and HT protection * updates from beacons. @@ -8041,7 +8443,7 @@ iwx_run_stop(struct iwx_softc *sc) printf("%s: could not disable beacon filter (error %d)\n", DEVNAME(sc), err); return err; - } + } /* Mark station as disassociated. */ err = iwx_mac_ctxt_cmd(sc, in, IWX_FW_CTXT_ACTION_MODIFY, 0); @@ -8050,17 +8452,6 @@ iwx_run_stop(struct iwx_softc *sc) return err; } - /* Reset Tx chains in case MIMO or 40 MHz channels were enabled. */ - if (in->in_ni.ni_flags & IEEE80211_NODE_HT) { - err = iwx_phy_ctxt_update(sc, in->in_phyctxt, - in->in_phyctxt->channel, 1, 1, 0, IEEE80211_HTOP0_SCO_SCN, - IEEE80211_VHTOP0_CHAN_WIDTH_HT); - if (err) { - printf("%s: failed to update PHY\n", DEVNAME(sc)); - return err; - } - } - return 0; } @@ -8202,6 +8593,9 @@ iwx_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, return; } + if ((sc->sc_flags & IWX_FLAG_STA_ACTIVE) == 0) + return; + memset(&cmd, 0, sizeof(cmd)); cmd.common.key_flags = htole16(IWX_STA_KEY_NOT_VALID | @@ -8221,27 +8615,12 @@ iwx_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, int iwx_media_change(struct ifnet *ifp) { - struct iwx_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - uint8_t rate, ridx; int err; err = ieee80211_media_change(ifp); if (err != ENETRESET) return err; - if (ic->ic_fixed_mcs != -1) - sc->sc_fixed_ridx = iwx_mcs2ridx[ic->ic_fixed_mcs]; - else if (ic->ic_fixed_rate != -1) { - rate = ic->ic_sup_rates[ic->ic_curmode]. - rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; - /* Map 802.11 rate to HW rate index. */ - for (ridx = 0; ridx <= IWX_RIDX_MAX; ridx++) - if (iwx_rates[ridx].rate == rate) - break; - sc->sc_fixed_ridx = ridx; - } - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) { iwx_stop(ifp); @@ -8711,6 +9090,15 @@ iwx_init_hw(struct iwx_softc *sc) DEVNAME(sc), i, err); goto err; } + if (iwx_lookup_cmd_ver(sc, IWX_DATA_PATH_GROUP, + IWX_RLC_CONFIG_CMD) == 2) { + err = iwx_phy_send_rlc(sc, &sc->sc_phyctxt[i], 1, 1); + if (err) { + printf("%s: could not configure RLC for PHY " + "%d (error %d)\n", DEVNAME(sc), i, err); + goto err; + } + } } err = iwx_config_ltr(sc); @@ -8832,7 +9220,7 @@ iwx_init(struct ifnet *ifp) ieee80211_begin_scan(ifp); - /* + /* * ieee80211_begin_scan() ends up scheduling iwx_newstate_task(). * Wait until the transition to SCAN state has completed. */ @@ -9488,6 +9876,7 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml) case IWX_ALIVE: { struct iwx_alive_resp_v4 *resp4; struct iwx_alive_resp_v5 *resp5; + struct iwx_alive_resp_v6 *resp6; DPRINTF(("%s: firmware alive\n", __func__)); sc->sc_uc.uc_ok = 0; @@ -9497,6 +9886,31 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml) * versions we need to check the size. */ if (iwx_lookup_notif_ver(sc, IWX_LEGACY_GROUP, + IWX_ALIVE) == 6) { + SYNC_RESP_STRUCT(resp6, pkt); + if (iwx_rx_packet_payload_len(pkt) != + sizeof(*resp6)) { + sc->sc_uc.uc_intr = 1; + wakeup(&sc->sc_uc); + break; + } + sc->sc_uc.uc_lmac_error_event_table[0] = le32toh( + resp6->lmac_data[0].dbg_ptrs.error_event_table_ptr); + sc->sc_uc.uc_lmac_error_event_table[1] = le32toh( + resp6->lmac_data[1].dbg_ptrs.error_event_table_ptr); + sc->sc_uc.uc_log_event_table = le32toh( + resp6->lmac_data[0].dbg_ptrs.log_event_table_ptr); + sc->sc_uc.uc_umac_error_event_table = le32toh( + resp6->umac_data.dbg_ptrs.error_info_addr); + sc->sc_sku_id[0] = + le32toh(resp6->sku_id.data[0]); + sc->sc_sku_id[1] = + le32toh(resp6->sku_id.data[1]); + sc->sc_sku_id[2] = + le32toh(resp6->sku_id.data[2]); + if (resp6->status == IWX_ALIVE_STATUS_OK) + sc->sc_uc.uc_ok = 1; + } else if (iwx_lookup_notif_ver(sc, IWX_LEGACY_GROUP, IWX_ALIVE) == 5) { SYNC_RESP_STRUCT(resp5, pkt); if (iwx_rx_packet_payload_len(pkt) != @@ -9567,6 +9981,10 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml) break; } + case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, + IWX_SCD_QUEUE_CONFIG_CMD): + case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, + IWX_RX_BAID_ALLOCATION_CONFIG_CMD): case IWX_WIDE_ID(IWX_MAC_CONF_GROUP, IWX_SESSION_PROTECTION_CMD): case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP, @@ -9645,7 +10063,7 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml) iwx_mcc_update(sc, notif); break; } - + case IWX_REPLY_ERROR: { struct iwx_error_resp *resp; SYNC_RESP_STRUCT(resp, pkt); @@ -9727,6 +10145,13 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml) break; } + case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, IWX_RLC_CONFIG_CMD): + break; + + /* undocumented notification from iwx-ty-a0-gf-a0-77 image */ + case IWX_WIDE_ID(IWX_DATA_PATH_GROUP, 0xf8): + break; + case IWX_WIDE_ID(IWX_REGULATORY_AND_NVM_GROUP, IWX_PNVM_INIT_COMPLETE): sc->sc_init_complete |= IWX_PNVM_COMPLETE; @@ -9745,7 +10170,7 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml) /* * uCode sets bit 0x80 when it originates the notification, * i.e. when the notification is not a direct response to a - * command sent by the driver. + * command sent by the driver. * For example, uCode issues IWX_REPLY_RX when it sends a * received frame to the driver. */ @@ -10028,6 +10453,7 @@ static const struct pci_matchid iwx_devices[] = { #define PCI_PRODUCT_INTEL_WL_22500_14 0x7e40 /* Wi-Fi 6 AX210 */ #define PCI_PRODUCT_INTEL_WL_22500_15 0x7f70 /* Wi-Fi 6 AX211 */ #define PCI_PRODUCT_INTEL_WL_22500_16 0x54f0 /* Wi-Fi 6 AX211 */ +#define PCI_PRODUCT_INTEL_WL_22500_17 0x51f1 /* Wi-Fi 6 AX211 */ #endif { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_1 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_2 }, @@ -10045,6 +10471,7 @@ static const struct pci_matchid iwx_devices[] = { /* _14 is an MA device, not yet supported */ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_15,}, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_16,}, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_17,}, }; #ifdef __FreeBSD_version @@ -10090,7 +10517,7 @@ iwx_match(struct device *parent, iwx_match_t match __unused, void *aux) * Part of this complexity comes from iwlwifi supporting both iwm(4) and iwx(4) * devices in the same driver. * - * Our table below contains mostly "new" entries declared in iwlwifi + * Our table below contains mostly "new" entries declared in iwlwifi * with the _IWL_DEV_INFO() macro (with a leading underscore). * Other devices are matched based on PCI vendor/product ID as usual, * unless matching specific PCI subsystem vendor/product IDs is required. @@ -10151,6 +10578,8 @@ static const struct iwx_dev_info iwx_dev_info_table[] = { IWX_DEV_INFO(0x2725, 0x1674, iwx_2ax_cfg_ty_gf_a0), /* killer_1675x */ IWX_DEV_INFO(0x51f0, 0x1691, iwx_2ax_cfg_so_gf4_a0), /* killer_1690s */ IWX_DEV_INFO(0x51f0, 0x1692, iwx_2ax_cfg_so_gf4_a0), /* killer_1690i */ + IWX_DEV_INFO(0x51f1, 0x1691, iwx_2ax_cfg_so_gf4_a0), + IWX_DEV_INFO(0x51f1, 0x1692, iwx_2ax_cfg_so_gf4_a0), IWX_DEV_INFO(0x54f0, 0x1691, iwx_2ax_cfg_so_gf4_a0), /* killer_1690s */ IWX_DEV_INFO(0x54f0, 0x1692, iwx_2ax_cfg_so_gf4_a0), /* killer_1690i */ IWX_DEV_INFO(0x7a70, 0x0090, iwx_2ax_cfg_so_gf_a0_long), @@ -10790,7 +11219,6 @@ iwx_attach(struct device *parent, struct device *self, void *aux) case PCI_PRODUCT_INTEL_WL_22500_9: case PCI_PRODUCT_INTEL_WL_22500_10: case PCI_PRODUCT_INTEL_WL_22500_11: - case PCI_PRODUCT_INTEL_WL_22500_12: case PCI_PRODUCT_INTEL_WL_22500_13: /* _14 is an MA device, not yet supported */ case PCI_PRODUCT_INTEL_WL_22500_15: @@ -10805,6 +11233,19 @@ iwx_attach(struct device *parent, struct device *self, void *aux) sc->sc_tx_with_siso_diversity = 0; sc->sc_uhb_supported = 1; break; + case PCI_PRODUCT_INTEL_WL_22500_12: + case PCI_PRODUCT_INTEL_WL_22500_17: + sc->sc_fwname = IWX_SO_A_GF_A_FW; + sc->sc_pnvm_name = IWX_SO_A_GF_A_PNVM; + sc->sc_device_family = IWX_DEVICE_FAMILY_AX210; + sc->sc_integrated = 1; + sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_2500; + sc->sc_low_latency_xtal = 1; + sc->sc_xtal_latency = 12000; + sc->sc_tx_with_siso_diversity = 0; + sc->sc_uhb_supported = 0; + sc->sc_imr_enabled = 1; + break; default: printf("%s: unknown adapter type\n", DEVNAME(sc)); goto fail; diff --git a/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwxreg.h b/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwxreg.h index 3b9cbde8fc..083ffb9e2f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwxreg.h +++ b/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwxreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwxreg.h,v 1.41 2023/02/14 12:14:07 stsp Exp $ */ +/* $OpenBSD: if_iwxreg.h,v 1.51 2023/03/06 11:18:37 stsp Exp $ */ /*- * Based on BSD-licensed source modules in the Linux iwlwifi driver, @@ -1387,6 +1387,7 @@ enum msix_ivar_for_cause { #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_BAID_ML_SUPPORT 63 #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 @@ -1574,8 +1575,13 @@ struct iwx_ucode_header { #define IWX_UCODE_TLV_PNVM_VERSION 62 #define IWX_UCODE_TLV_PNVM_SKU 64 +#define IWX_UCODE_TLV_SEC_TABLE_ADDR 66 +#define IWX_UCODE_TLV_D3_KEK_KCK_ADDR 67 +#define IWX_UCODE_TLV_CURRENT_PC 68 + #define IWX_UCODE_TLV_CONST_BASE 0x100 #define IWX_UCODE_TLV_FW_NUM_STATIONS (IWX_UCODE_TLV_CONST_BASE + 0) +#define IWX_UCODE_TLV_FW_NUM_BEACONS (IWX_UCODE_TLV_CONST_BASE + 2) #define IWX_UCODE_TLV_DEBUG_BASE 0x1000005 #define IWX_UCODE_TLV_TYPE_DEBUG_INFO (IWX_UCODE_TLV_DEBUG_BASE + 0) @@ -1999,7 +2005,10 @@ struct iwx_tx_queue_cfg_rsp { /* DATA_PATH group subcommand IDs */ #define IWX_DQA_ENABLE_CMD 0x00 +#define IWX_RLC_CONFIG_CMD 0x08 #define IWX_TLC_MNG_CONFIG_CMD 0x0f +#define IWX_RX_BAID_ALLOCATION_CONFIG_CMD 0x16 +#define IWX_SCD_QUEUE_CONFIG_CMD 0x17 #define IWX_RX_NO_DATA_NOTIF 0xf5 #define IWX_TLC_MNG_UPDATE_NOTIF 0xf7 @@ -2328,6 +2337,21 @@ struct iwx_alive_resp_v5 { struct iwx_sku_id sku_id; } __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */ +struct iwx_imr_alive_info { + uint64_t base_addr; + uint32_t size; + uint32_t enabled; +} __packed; /* IMR_ALIVE_INFO_API_S_VER_1 */ + +struct iwx_alive_resp_v6 { + 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; + struct iwx_imr_alive_info imr; +} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_6 */ + #define IWX_SOC_CONFIG_CMD_FLAGS_DISCRETE (1 << 0) #define IWX_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY (1 << 1) @@ -3374,13 +3398,13 @@ 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 */ + /* PHY_CONTEXT_DATA_API_S_VER_3, PHY_CONTEXT_DATA_API_S_VER_4 */ struct iwx_fw_channel_info_v1 ci; uint32_t lmac_id; - uint32_t rxchain_info; + uint32_t rxchain_info; /* reserved in _VER_4 */ uint32_t dsp_cfg_flags; uint32_t reserved; -} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */ +} __packed; /* PHY_CONTEXT_CMD_API_VER_3, PHY_CONTEXT_CMD_API_VER_4 */ /* TODO: complete missing documentation */ /** @@ -4283,15 +4307,33 @@ struct iwx_mac_data_ibss { uint32_t beacon_template; } __packed; /* IBSS_MAC_DATA_API_S_VER_1 */ +/** + * enum iwx_mac_data_policy - policy of the data path for this MAC + * @TWT_SUPPORTED: twt is supported + * @MORE_DATA_ACK_SUPPORTED: AP supports More Data Ack according to + * paragraph 9.4.1.17 in P802.11ax_D4 specification. Used for TWT + * early termination detection. + * @FLEXIBLE_TWT_SUPPORTED: AP supports flexible TWT schedule + * @PROTECTED_TWT_SUPPORTED: AP supports protected TWT frames (with 11w) + * @BROADCAST_TWT_SUPPORTED: AP and STA support broadcast TWT + * @COEX_HIGH_PRIORITY_ENABLE: high priority mode for BT coex, to be used + * during 802.1X negotiation (and allowed during 4-way-HS) + */ +#define IWX_TWT_SUPPORTED BIT (1 << 0) +#define IWX_MORE_DATA_ACK_SUPPORTED (1 << 1) +#define IWX_FLEXIBLE_TWT_SUPPORTED (1 << 2) +#define IWX_PROTECTED_TWT_SUPPORTED (1 << 3) +#define IWX_BROADCAST_TWT_SUPPORTED (1 << 4) +#define IWX_COEX_HIGH_PRIORITY_ENABLE (1 << 5) + /** * struct iwx_mac_data_sta - configuration data for station MAC context * @is_assoc: 1 for associated state, 0 otherwise * @dtim_time: DTIM arrival time in system time * @dtim_tsf: DTIM arrival time in TSF * @bi: beacon interval in TU, applicable only when associated - * @bi_reciprocal: 2^32 / bi , applicable only when associated + * @data_policy: see &enum iwl_mac_data_policy * @dtim_interval: DTIM interval in TU, applicable only when associated - * @dtim_reciprocal: 2^32 / dtim_interval , applicable only when associated * @listen_interval: in beacon intervals, applicable only when associated * @assoc_id: unique ID assigned by the AP during association */ @@ -4300,13 +4342,13 @@ struct iwx_mac_data_sta { uint32_t dtim_time; uint64_t dtim_tsf; uint32_t bi; - uint32_t bi_reciprocal; + uint32_t reserved1; uint32_t dtim_interval; - uint32_t dtim_reciprocal; + uint32_t data_policy; uint32_t listen_interval; uint32_t assoc_id; uint32_t assoc_beacon_arrive_time; -} __packed; /* IWX_STA_MAC_DATA_API_S_VER_1 */ +} __packed; /* IWX_STA_MAC_DATA_API_S_VER_2 */ /** * struct iwx_mac_data_go - configuration data for P2P GO MAC context @@ -4882,7 +4924,7 @@ enum { #define IWX_RATE_INVM_PLCP 0xff /* - * rate_n_flags bit fields + * rate_n_flags bit fields version 1 * * The 32-bit value has different layouts in the low 8 bites depending on the * format. There are three formats, HT, VHT and legacy (11abg, with subformats @@ -4900,15 +4942,15 @@ enum { /* Bit 8: (1) HT format, (0) legacy or VHT format */ #define IWX_RATE_MCS_HT_POS 8 -#define IWX_RATE_MCS_HT_MSK (1 << IWX_RATE_MCS_HT_POS) +#define IWX_RATE_MCS_HT_MSK_V1 (1 << IWX_RATE_MCS_HT_POS) /* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */ -#define IWX_RATE_MCS_CCK_POS 9 -#define IWX_RATE_MCS_CCK_MSK (1 << IWX_RATE_MCS_CCK_POS) +#define IWX_RATE_MCS_CCK_POS_V1 9 +#define IWX_RATE_MCS_CCK_MSK_V1 (1 << IWX_RATE_MCS_CCK_POS_V1) /* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */ -#define IWX_RATE_MCS_VHT_POS 26 -#define IWX_RATE_MCS_VHT_MSK (1 << IWX_RATE_MCS_VHT_POS) +#define IWX_RATE_MCS_VHT_POS_V1 26 +#define IWX_RATE_MCS_VHT_MSK_V1 (1 << IWX_RATE_MCS_VHT_POS_V1) /* @@ -4934,15 +4976,16 @@ enum { * streams and 16-23 have three streams. We could also support MCS 32 * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) */ -#define IWX_RATE_HT_MCS_RATE_CODE_MSK 0x7 -#define IWX_RATE_HT_MCS_NSS_POS 3 -#define IWX_RATE_HT_MCS_NSS_MSK (3 << IWX_RATE_HT_MCS_NSS_POS) +#define IWX_RATE_HT_MCS_RATE_CODE_MSK_V1 0x7 +#define IWX_RATE_HT_MCS_NSS_POS_V1 3 +#define IWX_RATE_HT_MCS_NSS_MSK_V1 (3 << IWX_RATE_HT_MCS_NSS_POS_V1) +#define IWX_RATE_HT_MCS_MIMO2_MSK_V1 (1 << IWX_RATE_HT_MCS_NSS_POS_V1) /* Bit 10: (1) Use Green Field preamble */ #define IWX_RATE_HT_MCS_GF_POS 10 #define IWX_RATE_HT_MCS_GF_MSK (1 << IWX_RATE_HT_MCS_GF_POS) -#define IWX_RATE_HT_MCS_INDEX_MSK 0x3f +#define IWX_RATE_HT_MCS_INDEX_MSK_V1 0x3f /* * Very High-throughput (VHT) rate format for bits 7:0 @@ -4958,6 +5001,7 @@ enum { #define IWX_RATE_VHT_MCS_RATE_CODE_MSK 0xf #define IWX_RATE_VHT_MCS_NSS_POS 4 #define IWX_RATE_VHT_MCS_NSS_MSK (3 << IWX_RATE_VHT_MCS_NSS_POS) +#define IWX_RATE_VHT_MCS_MIMO2_MSK (1 << IWX_RATE_VHT_MCS_NSS_POS) /* * Legacy OFDM rate format for bits 7:0 @@ -4981,55 +5025,242 @@ enum { * 110) 11 Mbps * (bit 7 is 0) */ -#define IWX_RATE_LEGACY_RATE_MSK 0xff +#define IWX_RATE_LEGACY_RATE_MSK_V1 0xff +/* Bit 10 - OFDM HE */ +#define IWX_RATE_MCS_HE_POS_V1 10 +#define IWX_RATE_MCS_HE_MSK_V1 (1 << RATE_MCS_HE_POS_V1) /* * Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz * 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT */ #define IWX_RATE_MCS_CHAN_WIDTH_POS 11 -#define IWX_RATE_MCS_CHAN_WIDTH_MSK (3 << IWX_RATE_MCS_CHAN_WIDTH_POS) -#define IWX_RATE_MCS_CHAN_WIDTH_20 (0 << IWX_RATE_MCS_CHAN_WIDTH_POS) -#define IWX_RATE_MCS_CHAN_WIDTH_40 (1 << IWX_RATE_MCS_CHAN_WIDTH_POS) -#define IWX_RATE_MCS_CHAN_WIDTH_80 (2 << IWX_RATE_MCS_CHAN_WIDTH_POS) -#define IWX_RATE_MCS_CHAN_WIDTH_160 (3 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_MSK_V1 (3 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_20_V1 (0 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_40_V1 (1 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_80_V1 (2 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_160_V1 (3 << IWX_RATE_MCS_CHAN_WIDTH_POS) /* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ -#define IWX_RATE_MCS_SGI_POS 13 -#define IWX_RATE_MCS_SGI_MSK (1 << IWX_RATE_MCS_SGI_POS) +#define IWX_RATE_MCS_SGI_POS_V1 13 +#define IWX_RATE_MCS_SGI_MSK_V1 (1 << IWX_RATE_MCS_SGI_POS_V1) -/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */ +/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C (unused) */ #define IWX_RATE_MCS_ANT_POS 14 #define IWX_RATE_MCS_ANT_A_MSK (1 << IWX_RATE_MCS_ANT_POS) #define IWX_RATE_MCS_ANT_B_MSK (2 << IWX_RATE_MCS_ANT_POS) -#define IWX_RATE_MCS_ANT_C_MSK (4 << IWX_RATE_MCS_ANT_POS) #define IWX_RATE_MCS_ANT_AB_MSK (IWX_RATE_MCS_ANT_A_MSK | \ IWX_RATE_MCS_ANT_B_MSK) -#define IWX_RATE_MCS_ANT_ABC_MSK (IWX_RATE_MCS_ANT_AB_MSK | \ - IWX_RATE_MCS_ANT_C_MSK) #define IWX_RATE_MCS_ANT_MSK IWX_RATE_MCS_ANT_ABC_MSK -#define IWX_RATE_MCS_ANT_NUM 3 +#define IWX_RATE_MCS_ANT_NUM 2 -/* Bit 17-18: (0) SS, (1) SS*2 */ +/* Bit 17: (0) SS, (1) SS*2 */ #define IWX_RATE_MCS_STBC_POS 17 #define IWX_RATE_MCS_STBC_MSK (1 << IWX_RATE_MCS_STBC_POS) +/* Bit 18: OFDM-HE dual carrier mode */ +#define IWX_RATE_HE_DUAL_CARRIER_MODE 18 +#define IWX_RATE_HE_DUAL_CARRIER_MODE_MSK (1 << IWX_RATE_HE_DUAL_CARRIER_MODE) + /* Bit 19: (0) Beamforming is off, (1) Beamforming is on */ #define IWX_RATE_MCS_BF_POS 19 #define IWX_RATE_MCS_BF_MSK (1 << IWX_RATE_MCS_BF_POS) -/* Bit 20: (0) ZLF is off, (1) ZLF is on */ -#define IWX_RATE_MCS_ZLF_POS 20 -#define IWX_RATE_MCS_ZLF_MSK (1 << IWX_RATE_MCS_ZLF_POS) +/* + * Bit 20-21: HE LTF type and guard interval + * HE (ext) SU: + * 0 1xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 & SGI (bit 13) clear 4xLTF+3.2us + * 3 & SGI (bit 13) set 4xLTF+0.8us + * HE MU: + * 0 4xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 4xLTF+3.2us + * HE TRIG: + * 0 1xLTF+1.6us + * 1 2xLTF+1.6us + * 2 4xLTF+3.2us + * 3 (does not occur) + */ +#define IWX_RATE_MCS_HE_GI_LTF_POS 20 +#define IWX_RATE_MCS_HE_GI_LTF_MSK_V1 (3 << IWX_RATE_MCS_HE_GI_LTF_POS) + +/* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */ +#define IWX_RATE_MCS_HE_TYPE_POS_V1 22 +#define IWX_RATE_MCS_HE_TYPE_SU_V1 (0 << IWX_RATE_MCS_HE_TYPE_POS_V1) +#define IWX_RATE_MCS_HE_TYPE_EXT_SU_V1 (1 << IWX_RATE_MCS_HE_TYPE_POS_V1) +#define IWX_RATE_MCS_HE_TYPE_MU_V1 (2 << IWX_RATE_MCS_HE_TYPE_POS_V1) +#define IWX_RATE_MCS_HE_TYPE_TRIG_V1 (3 << IWX_RATE_MCS_HE_TYPE_POS_V1) +#define IWX_RATE_MCS_HE_TYPE_MSK_V1 (3 << IWX_RATE_MCS_HE_TYPE_POS_V1) /* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */ -#define IWX_RATE_MCS_DUP_POS 24 -#define IWX_RATE_MCS_DUP_MSK (3 << IWX_RATE_MCS_DUP_POS) +#define IWX_RATE_MCS_DUP_POS_V1 24 +#define IWX_RATE_MCS_DUP_MSK_V1 (3 << IWX_RATE_MCS_DUP_POS_V1) /* Bit 27: (1) LDPC enabled, (0) LDPC disabled */ -#define IWX_RATE_MCS_LDPC_POS 27 -#define IWX_RATE_MCS_LDPC_MSK (1 << IWX_RATE_MCS_LDPC_POS) +#define IWX_RATE_MCS_LDPC_POS_V1 27 +#define IWX_RATE_MCS_LDPC_MSK_V1 (1 << IWX_RATE_MCS_LDPC_POS_V1) + +/* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */ +#define IWX_RATE_MCS_HE_106T_POS_V1 28 +#define IWX_RATE_MCS_HE_106T_MSK_V1 (1 << IWX_RATE_MCS_HE_106T_POS_V1) + +/* Bit 30-31: (1) RTS, (2) CTS */ +#define IWX_RATE_MCS_RTS_REQUIRED_POS (30) +#define IWX_RATE_MCS_RTS_REQUIRED_MSK (1 << IWX_RATE_MCS_RTS_REQUIRED_POS) +#define IWX_RATE_MCS_CTS_REQUIRED_POS (31) +#define IWX_RATE_MCS_CTS_REQUIRED_MSK (1 << IWX_RATE_MCS_CTS_REQUIRED_POS) + + +/* rate_n_flags bit field version 2 + * + * The 32-bit value has different layouts in the low 8 bits depending on the + * format. There are three formats, HT, VHT and legacy (11abg, with subformats + * for CCK and OFDM). + * + */ + +/* Bits 10-8: rate format + * (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT) + * (3) Very High-throughput (VHT) (4) High-efficiency (HE) + * (5) Extremely High-throughput (EHT) + */ +#define IWX_RATE_MCS_MOD_TYPE_POS 8 +#define IWX_RATE_MCS_MOD_TYPE_MSK (0x7 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_CCK_MSK (0 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_LEGACY_OFDM_MSK (1 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_HT_MSK (2 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_VHT_MSK (3 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_HE_MSK (4 << IWX_RATE_MCS_MOD_TYPE_POS) +#define IWX_RATE_MCS_EHT_MSK (5 << IWX_RATE_MCS_MOD_TYPE_POS) + +/* + * Legacy CCK rate format for bits 0:3: + * + * (0) 0xa - 1 Mbps + * (1) 0x14 - 2 Mbps + * (2) 0x37 - 5.5 Mbps + * (3) 0x6e - 11 nbps + * + * Legacy OFDM rate format for bits 0:3: + * + * (0) 6 Mbps + * (1) 9 Mbps + * (2) 12 Mbps + * (3) 18 Mbps + * (4) 24 Mbps + * (5) 36 Mbps + * (6) 48 Mbps + * (7) 54 Mbps + * + */ +#define IWX_RATE_LEGACY_RATE_MSK 0x7 + +/* + * HT, VHT, HE, EHT rate format for bits 3:0 + * 3-0: MCS + * + */ +#define IWX_RATE_HT_MCS_CODE_MSK 0x7 +#define IWX_RATE_MCS_NSS_POS 4 +#define IWX_RATE_MCS_NSS_MSK (1 << IWX_RATE_MCS_NSS_POS) +#define IWX_RATE_MCS_CODE_MSK 0xf +#define IWX_RATE_HT_MCS_INDEX(r) ((((r) & IWX_RATE_MCS_NSS_MSK) >> 1) | \ + ((r) & IWX_RATE_HT_MCS_CODE_MSK)) + +/* Bits 7-5: reserved */ + +/* + * Bits 13-11: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz, (4) 320MHz + */ +#define IWX_RATE_MCS_CHAN_WIDTH_MSK (0x7 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_20 (0 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_40 (1 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_80 (2 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_160 (3 << IWX_RATE_MCS_CHAN_WIDTH_POS) +#define IWX_RATE_MCS_CHAN_WIDTH_320 (4 << IWX_RATE_MCS_CHAN_WIDTH_POS) + +/* Bit 15-14: Antenna selection: + * Bit 14: Ant A active + * Bit 15: Ant B active + * + * All relevant definitions are same as in v1 + */ + +/* Bit 16 (1) LDPC enables, (0) LDPC disabled */ +#define IWX_RATE_MCS_LDPC_POS 16 +#define IWX_RATE_MCS_LDPC_MSK (1 << IWX_RATE_MCS_LDPC_POS) + +/* Bit 17: (0) SS, (1) SS*2 (same as v1) */ + +/* Bit 18: OFDM-HE dual carrier mode (same as v1) */ + +/* Bit 19: (0) Beamforming is off, (1) Beamforming is on (same as v1) */ + +/* + * Bit 22-20: HE LTF type and guard interval + * CCK: + * 0 long preamble + * 1 short preamble + * HT/VHT: + * 0 0.8us + * 1 0.4us + * HE (ext) SU: + * 0 1xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 4xLTF+3.2us + * 4 4xLTF+0.8us + * HE MU: + * 0 4xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 4xLTF+3.2us + * HE TRIG: + * 0 1xLTF+1.6us + * 1 2xLTF+1.6us + * 2 4xLTF+3.2us + * */ +#define IWX_RATE_MCS_HE_GI_LTF_MSK (0x7 << IWX_RATE_MCS_HE_GI_LTF_POS) +#define IWX_RATE_MCS_SGI_POS IWX_RATE_MCS_HE_GI_LTF_POS +#define IWX_RATE_MCS_SGI_MSK (1 << IWX_RATE_MCS_SGI_POS) +#define IWX_RATE_MCS_HE_SU_4_LTF 3 +#define IWX_RATE_MCS_HE_SU_4_LTF_08_GI 4 + +/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */ +#define IWX_RATE_MCS_HE_TYPE_POS 23 +#define IWX_RATE_MCS_HE_TYPE_SU (0 << IWX_RATE_MCS_HE_TYPE_POS) +#define IWX_RATE_MCS_HE_TYPE_EXT_SU (1 << IWX_RATE_MCS_HE_TYPE_POS) +#define IWX_RATE_MCS_HE_TYPE_MU (2 << IWX_RATE_MCS_HE_TYPE_POS) +#define IWX_RATE_MCS_HE_TYPE_TRIG (3 << IWX_RATE_MCS_HE_TYPE_POS) +#define IWX_RATE_MCS_HE_TYPE_MSK (3 << IWX_RATE_MCS_HE_TYPE_POS) + +/* Bit 25: duplicate channel enabled + * + * if this bit is set, duplicate is according to BW (bits 11-13): + * + * CCK: 2x 20MHz + * OFDM Legacy: N x 20Mhz, (N = BW \ 2 , either 2, 4, 8, 16) + * EHT: 2 x BW/2, (80 - 2x40, 160 - 2x80, 320 - 2x160) + * */ +#define IWX_RATE_MCS_DUP_POS 25 +#define IWX_RATE_MCS_DUP_MSK (1 << IWX_RATE_MCS_DUP_POS) + +/* Bit 26: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */ +#define IWX_RATE_MCS_HE_106T_POS 26 +#define IWX_RATE_MCS_HE_106T_MSK (1 << IWX_RATE_MCS_HE_106T_POS) + +/* Bit 27: EHT extra LTF: + * instead of 1 LTF for SISO use 2 LTFs, + * instead of 2 LTFs for NSTS=2 use 4 LTFs*/ +#define IWX_RATE_MCS_EHT_EXTRA_LTF_POS 27 +#define IWX_RATE_MCS_EHT_EXTRA_LTF_MSK (1 << IWX_RATE_MCS_EHT_EXTRA_LTF_POS) + +/* Bit 31-28: reserved */ /* Link Quality definitions */ @@ -5063,6 +5294,192 @@ enum { #define IWX_LQ_FLAG_DYNAMIC_BW_POS 6 #define IWX_LQ_FLAG_DYNAMIC_BW_MSK (1 << IWX_LQ_FLAG_DYNAMIC_BW_POS) +#define IWX_RLC_CHAIN_INFO_DRIVER_FORCE (1 << 0) +#define IWL_RLC_CHAIN_INFO_VALID 0x000e +#define IWL_RLC_CHAIN_INFO_FORCE 0x0070 +#define IWL_RLC_CHAIN_INFO_FORCE_MIMO 0x0380 +#define IWL_RLC_CHAIN_INFO_COUNT 0x0c00 +#define IWL_RLC_CHAIN_INFO_MIMO_COUNT 0x3000 + +/** + * struct iwx_rlc_properties - RLC properties + * @rx_chain_info: RX chain info, IWX_RLC_CHAIN_INFO_* + * @reserved: reserved + */ +struct iwx_rlc_properties { + uint32_t rx_chain_info; + uint32_t reserved; +} __packed; /* RLC_PROPERTIES_S_VER_1 */ + +#define IWX_SAD_MODE_ENABLED (1 << 0) +#define IWX_SAD_MODE_DEFAULT_ANT_MSK 0x6 +#define IWX_SAD_MODE_DEFAULT_ANT_FW 0x0 +#define IWX_SAD_MODE_DEFAULT_ANT_A 0x2 +#define IWX_SAD_MODE_DEFAULT_ANT_B 0x4 + +/** + * struct iwx_sad_properties - SAD properties + * @chain_a_sad_mode: chain A SAD mode, IWX_SAD_MODE_* + * @chain_b_sad_mode: chain B SAD mode, IWX_SAD_MODE_* + * @mac_id: MAC index + * @reserved: reserved + */ +struct iwx_sad_properties { + uint32_t chain_a_sad_mode; + uint32_t chain_b_sad_mode; + uint32_t mac_id; + uint32_t reserved; +} __packed; + +/** + * struct iwx_rlc_config_cmd - RLC configuration + * @phy_id: PHY index + * @rlc: RLC properties, &struct iwx_rlc_properties + * @sad: SAD (single antenna diversity) options, &struct iwx_sad_properties + * @flags: flags, IWX_RLC_FLAGS_* + * @reserved: reserved + */ +struct iwx_rlc_config_cmd { + uint32_t phy_id; + struct iwx_rlc_properties rlc; + struct iwx_sad_properties sad; + uint8_t flags; + uint8_t reserved[3]; +} __packed; /* RLC_CONFIG_CMD_API_S_VER_2 */ + +#define IWX_MAX_BAID_OLD 16 /* MAX_IMMEDIATE_BA_API_D_VER_2 */ +#define IWX_MAX_BAID 32 /* MAX_IMMEDIATE_BA_API_D_VER_3 */ + +/** + * BAID allocation/config action + * @IWX_RX_BAID_ACTION_ADD: add a new BAID session + * @IWX_RX_BAID_ACTION_MODIFY: modify the BAID session + * @IWX_RX_BAID_ACTION_REMOVE: remove the BAID session + */ +#define IWX_RX_BAID_ACTION_ADD 0 +#define IWX_RX_BAID_ACTION_MODIFY 1 +#define IWX_RX_BAID_ACTION_REMOVE 2 +/* RX_BAID_ALLOCATION_ACTION_E_VER_1 */ + +/** + * struct iwx_rx_baid_cfg_cmd_alloc - BAID allocation data + * @sta_id_mask: station ID mask + * @tid: the TID for this session + * @reserved: reserved + * @ssn: the starting sequence number + * @win_size: RX BA session window size + */ +struct iwx_rx_baid_cfg_cmd_alloc { + uint32_t sta_id_mask; + uint8_t tid; + uint8_t reserved[3]; + uint16_t ssn; + uint16_t win_size; +} __packed; /* RX_BAID_ALLOCATION_ADD_CMD_API_S_VER_1 */ + +/** + * struct iwx_rx_baid_cfg_cmd_modify - BAID modification data + * @old_sta_id_mask: old station ID mask + * @new_sta_id_mask: new station ID mask + * @tid: TID of the BAID + */ +struct iwx_rx_baid_cfg_cmd_modify { + uint32_t old_sta_id_mask; + uint32_t new_sta_id_mask; + uint32_t tid; +} __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_2 */ + +/** + * struct iwx_rx_baid_cfg_cmd_remove_v1 - BAID removal data + * @baid: the BAID to remove + */ +struct iwx_rx_baid_cfg_cmd_remove_v1 { + uint32_t baid; +} __packed; /* RX_BAID_ALLOCATION_REMOVE_CMD_API_S_VER_1 */ + +/** + * struct iwx_rx_baid_cfg_cmd_remove - BAID removal data + * @sta_id_mask: the station mask of the BAID to remove + * @tid: the TID of the BAID to remove + */ +struct iwx_rx_baid_cfg_cmd_remove { + uint32_t sta_id_mask; + uint32_t tid; +} __packed; /* RX_BAID_ALLOCATION_REMOVE_CMD_API_S_VER_2 */ + +/** + * struct iwx_rx_baid_cfg_cmd - BAID allocation/config command + * @action: the action, from &enum iwx_rx_baid_action + */ +struct iwx_rx_baid_cfg_cmd { + uint32_t action; + union { + struct iwx_rx_baid_cfg_cmd_alloc alloc; + struct iwx_rx_baid_cfg_cmd_modify modify; + struct iwx_rx_baid_cfg_cmd_remove_v1 remove_v1; + struct iwx_rx_baid_cfg_cmd_remove remove; + }; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_2 */ +} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_2 */ + +/** + * struct iwx_rx_baid_cfg_resp - BAID allocation response + * @baid: the allocated BAID + */ +struct iwx_rx_baid_cfg_resp { + uint32_t baid; +}; /* RX_BAID_ALLOCATION_RESPONSE_API_S_VER_1 */ + +/** + * scheduler queue operation + * @IWX_SCD_QUEUE_ADD: allocate a new queue + * @IWX_SCD_QUEUE_REMOVE: remove a queue + * @IWX_SCD_QUEUE_MODIFY: modify a queue + */ +#define IWX_SCD_QUEUE_ADD 0 +#define IWX_SCD_QUEUE_REMOVE 1 +#define IWX_SCD_QUEUE_MODIFY 2 + +/** + * struct iwx_scd_queue_cfg_cmd - scheduler queue allocation command + * @operation: the operation, see &enum iwl_scd_queue_cfg_operation + * @u.add.sta_mask: station mask + * @u.add.tid: TID + * @u.add.reserved: reserved + * @u.add.flags: flags from &enum iwl_tx_queue_cfg_actions, except + * %TX_QUEUE_CFG_ENABLE_QUEUE is not valid + * @u.add.cb_size: size code + * @u.add.bc_dram_addr: byte-count table IOVA + * @u.add.tfdq_dram_addr: TFD queue IOVA + * @u.remove.sta_mask: station mask of queue to remove + * @u.remove.tid: TID of queue to remove + * @u.modify.old_sta_mask: old station mask for modify + * @u.modify.tid: TID of queue to modify + * @u.modify.new_sta_mask: new station mask for modify + */ +struct iwx_scd_queue_cfg_cmd { + uint32_t operation; + union { + struct { + uint32_t sta_mask; + uint8_t tid; + uint8_t reserved[3]; + uint32_t flags; + uint32_t cb_size; + uint64_t bc_dram_addr; + uint64_t tfdq_dram_addr; + } __packed add; /* TX_QUEUE_CFG_CMD_ADD_API_S_VER_1 */ + struct { + uint32_t sta_mask; + uint32_t tid; + } __packed remove; /* TX_QUEUE_CFG_CMD_REMOVE_API_S_VER_1 */ + struct { + uint32_t old_sta_mask; + uint32_t tid; + uint32_t new_sta_mask; + } __packed modify; /* TX_QUEUE_CFG_CMD_MODIFY_API_S_VER_1 */ + } __packed u; /* TX_QUEUE_CFG_CMD_OPERATION_API_U_VER_1 */ +} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_3 */ + /** * Options for TLC config flags * @IWX_TLC_MNG_CFG_FLAGS_STBC_MSK: enable STBC. For HE this enables STBC for @@ -5089,14 +5506,14 @@ enum { * @IWX_TLC_MNG_CH_WIDTH_40MHZ: 40MHZ channel * @IWX_TLC_MNG_CH_WIDTH_80MHZ: 80MHZ channel * @IWX_TLC_MNG_CH_WIDTH_160MHZ: 160MHZ channel - * @IWX_TLC_MNG_CH_WIDTH_LAST: maximum value + * @IWX_TLC_MNG_CH_WIDTH_320MHZ: 320MHZ channel */ enum iwx_tlc_mng_cfg_cw { IWX_TLC_MNG_CH_WIDTH_20MHZ, IWX_TLC_MNG_CH_WIDTH_40MHZ, IWX_TLC_MNG_CH_WIDTH_80MHZ, IWX_TLC_MNG_CH_WIDTH_160MHZ, - IWX_TLC_MNG_CH_WIDTH_LAST = IWX_TLC_MNG_CH_WIDTH_160MHZ, + IWX_TLC_MNG_CH_WIDTH_320MHZ, }; /** @@ -5114,8 +5531,7 @@ enum iwx_tlc_mng_cfg_cw { * @IWX_TLC_MNG_MODE_HT: enable HT * @IWX_TLC_MNG_MODE_VHT: enable VHT * @IWX_TLC_MNG_MODE_HE: enable HE - * @IWX_TLC_MNG_MODE_INVALID: invalid value - * @IWX_TLC_MNG_MODE_NUM: a count of possible modes + * @IWX_TLC_MNG_MODE_EHT: enable EHT */ enum iwx_tlc_mng_cfg_mode { IWX_TLC_MNG_MODE_CCK = 0, @@ -5124,8 +5540,7 @@ enum iwx_tlc_mng_cfg_mode { IWX_TLC_MNG_MODE_HT, IWX_TLC_MNG_MODE_VHT, IWX_TLC_MNG_MODE_HE, - IWX_TLC_MNG_MODE_INVALID, - IWX_TLC_MNG_MODE_NUM = IWX_TLC_MNG_MODE_INVALID, + IWX_TLC_MNG_MODE_EHT, }; /** @@ -5163,11 +5578,23 @@ enum iwx_tlc_mng_ht_rates { #define IWX_TLC_NSS_2 1 #define IWX_TLC_NSS_MAX 2 -#define IWX_TLC_HT_BW_NONE_160 0 -#define IWX_TLC_HT_BW_160 1 /** - * struct iwx_tlc_config_cmd - TLC configuration + * IWX_TLC_MCS_PER_BW - mcs index per BW + * @IWX_TLC_MCS_PER_BW_80: mcs for bw - 20Hhz, 40Hhz, 80Hhz + * @IWX_TLC_MCS_PER_BW_160: mcs for bw - 160Mhz + * @IWX_TLC_MCS_PER_BW_320: mcs for bw - 320Mhz + * @IWX_TLC_MCS_PER_BW_NUM_V3: number of entries up to version 3 + * @IWX_TLC_MCS_PER_BW_NUM_V4: number of entries from version 4 + */ +#define IWX_TLC_MCS_PER_BW_80 0 +#define IWX_TLC_MCS_PER_BW_160 1 +#define IWX_TLC_MCS_PER_BW_320 2 +#define IWX_TLC_MCS_PER_BW_NUM_V3 (IWX_TLC_MCS_PER_BW_160 + 1) +#define IWX_TLC_MCS_PER_BW_NUM_V4 (IWX_TLC_MCS_PER_BW_320 + 1) + +/** + * struct iwx_tlc_config_cmd_v3 - TLC configuration version 3 * @sta_id: station id * @reserved1: reserved * @max_ch_width: max supported channel width from @enum iwx_tlc_mng_cfg_cw @@ -5176,16 +5603,16 @@ enum iwx_tlc_mng_ht_rates { * @amsdu: 1 = TX amsdu is supported, 0 = not supported * @flags: bitmask of IWX_TLC_MNG_CFG_* * @non_ht_rates: bitmap of supported legacy rates - * @ht_rates: bitmap of &enum iwx_tlc_mng_ht_rates, per + * @ht_rates: MCS index 0 - 11, per * pair (0 - 80mhz width and below, 1 - 160mhz). * @max_mpdu_len: max MPDU length, in bytes * @sgi_ch_width_supp: bitmap of SGI support per channel width - * use (1 << @enum iwx_tlc_mng_cfg_cw) + * use (1 << 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 { +struct iwx_tlc_config_cmd_v3 { uint8_t sta_id; uint8_t reserved1[3]; uint8_t max_ch_width; @@ -5194,13 +5621,44 @@ struct iwx_tlc_config_cmd { uint8_t amsdu; uint16_t flags; uint16_t non_ht_rates; - uint16_t ht_rates[IWX_TLC_NSS_MAX][2]; + uint16_t ht_rates[IWX_TLC_NSS_MAX][IWX_TLC_MCS_PER_BW_NUM_V3]; uint16_t max_mpdu_len; uint8_t sgi_ch_width_supp; uint8_t reserved2; uint32_t max_tx_op; } __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_3 */ +/** + * struct iwx_tlc_config_cmd_v4 - TLC configuration + * @sta_id: station id + * @reserved1: reserved + * @max_ch_width: max supported channel width from @enum iwx_tlc_mng_cfg_cw + * @mode: &enum iwx_tlc_mng_cfg_mode + * @chains: bitmask of IWX_TLC_MNG_CHAIN_*_MSK + * @sgi_ch_width_supp: bitmap of SGI support per channel width + * use (1 << IWX_TLC_MNG_CFG_CW_*) + * @flags: bitmask of IWX_TLC_MNG_CFG_* + * @non_ht_rates: bitmap of supported legacy rates + * @ht_rates: MCS index 0 - 11, per + * pair (0 - 80mhz width and below, 1 - 160mhz, 2 - 320mhz). + * @max_mpdu_len: max MPDU length, in bytes + * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI), + * set zero for no limit. + */ +struct iwx_tlc_config_cmd_v4 { + uint8_t sta_id; + uint8_t reserved1[3]; + uint8_t max_ch_width; + uint8_t mode; + uint8_t chains; + uint8_t sgi_ch_width_supp; + uint16_t flags; + uint16_t non_ht_rates; + uint16_t ht_rates[IWX_TLC_NSS_MAX][IWX_TLC_MCS_PER_BW_NUM_V4]; + uint16_t max_mpdu_len; + uint16_t max_tx_op; +} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_4 */ + /** * @IWX_TLC_NOTIF_FLAG_RATE: last initial rate update * @IWX_TLC_NOTIF_FLAG_AMSDU: umsdu parameters update @@ -5213,7 +5671,8 @@ struct iwx_tlc_config_cmd { * @sta_id: station id * @reserved: reserved * @flags: bitmap of notifications reported - * @rate: current initial rate + * @rate: current initial rate; using rate_n_flags version 1 if notification + * version is < 3 at run-time, else rate_n_flags version 2 * @amsdu_size: Max AMSDU size, in bytes * @amsdu_enabled: bitmap for per-TID AMSDU enablement */ @@ -5344,10 +5803,14 @@ struct iwx_dram_sec_info { * @IWX_TX_FLAGS_HIGH_PRI: high priority frame (like EAPOL) - can affect rate * selection, retry limits and BT kill */ +/* Valid for TX_FLAGS_BITS_API_S_VER_3: */ #define IWX_TX_FLAGS_CMD_RATE (1 << 0) #define IWX_TX_FLAGS_ENCRYPT_DIS (1 << 1) #define IWX_TX_FLAGS_HIGH_PRI (1 << 2) -/* TX_FLAGS_BITS_API_S_VER_3 */ +/* Valid for TX_FLAGS_BITS_API_S_VER_4 and above: */ +#define IWX_TX_FLAGS_RTS (1 << 3) +#define IWX_TX_FLAGS_CTS (1 << 4) +/* TX_FLAGS_BITS_API_S_VER_4 */ /** * struct iwx_tx_cmd_gen2 - TX command struct to FW for 22000 devices diff --git a/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwxvar.h b/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwxvar.h index d754ad755f..fece0caaae 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwxvar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iaxwifi200/dev/pci/if_iwxvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwxvar.h,v 1.37 2022/05/14 05:48:44 stsp Exp $ */ +/* $OpenBSD: if_iwxvar.h,v 1.41 2023/03/06 11:53:24 stsp Exp $ */ /* * Copyright (c) 2014 genua mbh @@ -123,7 +123,7 @@ struct iwx_tx_radiotap_header { (1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_CHANNEL)) -#define IWX_UCODE_SECT_MAX 54 +#define IWX_UCODE_SECT_MAX 57 /* * fw_status is used to determine if we've already parsed the firmware file @@ -471,21 +471,21 @@ struct iwx_device_cfg { }; /* Firmware listed here must be available in fw_update(8). */ -#define IWX_CC_A_FW "iwx-cc-a0-67" -#define IWX_TY_A_GF_A_FW "iwx-ty-a0-gf-a0-67" +#define IWX_CC_A_FW "iwx-cc-a0-77" +#define IWX_TY_A_GF_A_FW "iwx-ty-a0-gf-a0-77" #define IWX_TY_A_GF_A_PNVM "iwx-ty-a0-gf-a0.pnvm" -#define IWX_QU_B_HR_B_FW "iwx-Qu-b0-hr-b0-63" -#define IWX_QU_B_JF_B_FW "iwx-Qu-b0-jf-b0-63" -#define IWX_QU_C_HR_B_FW "iwx-Qu-c0-hr-b0-63" -#define IWX_QU_C_JF_B_FW "iwx-Qu-c0-jf-b0-63" -#define IWX_QUZ_A_HR_B_FW "iwx-QuZ-a0-hr-b0-67" -#define IWX_QUZ_A_JF_B_FW "iwx-QuZ-a0-jf-b0-63" -#define IWX_SO_A_GF_A_FW "iwx-so-a0-gf-a0-67" +#define IWX_QU_B_HR_B_FW "iwx-Qu-b0-hr-b0-77" +#define IWX_QU_B_JF_B_FW "iwx-Qu-b0-jf-b0-77" +#define IWX_QU_C_HR_B_FW "iwx-Qu-c0-hr-b0-77" +#define IWX_QU_C_JF_B_FW "iwx-Qu-c0-jf-b0-77" +#define IWX_QUZ_A_HR_B_FW "iwx-QuZ-a0-hr-b0-77" +#define IWX_QUZ_A_JF_B_FW "iwx-QuZ-a0-jf-b0-77" +#define IWX_SO_A_GF_A_FW "iwx-so-a0-gf-a0-77" #define IWX_SO_A_GF_A_PNVM "iwx-so-a0-gf-a0.pnvm" -#define IWX_SO_A_GF4_A_FW "iwx-so-a0-gf4-a0-67" +#define IWX_SO_A_GF4_A_FW "iwx-so-a0-gf4-a0-77" #define IWX_SO_A_GF4_A_PNVM "iwx-so-a0-gf4-a0.pnvm" -#define IWX_SO_A_HR_B_FW "iwx-so-a0-hr-b0-64" -#define IWX_SO_A_JF_B_FW "iwx-so-a0-jf-b0-64" +#define IWX_SO_A_HR_B_FW "iwx-so-a0-hr-b0-77" +#define IWX_SO_A_JF_B_FW "iwx-so-a0-jf-b0-77" const struct iwx_device_cfg iwx_9560_quz_a0_jf_b0_cfg = { .fw_name = IWX_QUZ_A_JF_B_FW, @@ -718,6 +718,7 @@ struct iwx_softc { #define IWX_MAX_FW_CMD_VERSIONS 704 struct iwx_fw_cmd_version cmd_versions[IWX_MAX_FW_CMD_VERSIONS]; int n_cmd_versions; + int sc_rate_n_flags_version; int sc_intmask; int sc_flags; @@ -752,8 +753,6 @@ struct iwx_softc { int sc_scan_last_antenna; - int sc_fixed_ridx; - int sc_staid; int sc_nodecolor; @@ -765,7 +764,6 @@ struct iwx_softc { struct iwx_rx_phy_info sc_last_phy_info; int sc_ampdu_ref; -#define IWX_MAX_BAID 32 struct iwx_rxba_data sc_rxba_data[IWX_MAX_BAID]; uint32_t sc_time_event_uid;