FreeBSD Bugzilla – Attachment 208925 Details for
Bug 227044
Add support for Intel 9260 and 5165 (iwm) wireless devices
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
https://people.freebsd.org/~markj/patches/iwm_9000/v1.diff
v1.diff (text/plain), 86.44 KB, created by
Ben Woods
on 2019-11-06 23:33:15 UTC
(
hide
)
Description:
https://people.freebsd.org/~markj/patches/iwm_9000/v1.diff
Filename:
MIME Type:
Creator:
Ben Woods
Created:
2019-11-06 23:33:15 UTC
Size:
86.44 KB
patch
obsolete
>diff --git a/share/man/man4/iwmfw.4 b/share/man/man4/iwmfw.4 >index 01829ac75dd8..92e6ba9630bf 100644 >--- a/share/man/man4/iwmfw.4 >+++ b/share/man/man4/iwmfw.4 >@@ -22,7 +22,7 @@ > .\" > .\" $FreeBSD$ > .\" >-.Dd October 29, 2017 >+.Dd November 1, 2019 > .Dt IWMFW 4 > .Os > .Sh NAME >@@ -48,10 +48,12 @@ of the following: > .Cd "device iwm7265fw" > .Cd "device iwm8000Cfw" > .Cd "device iwm8265fw" >+.Cd "device iwm9000fw" >+.Cd "device iwm9260fw" > .Ed > .Pp > Alternatively, to load the driver as a >-module at boot time, place the following line in >+module at boot time, place one of the following lines in > .Xr loader.conf 5 : > .Bd -literal -offset indent > iwm3160fw_load="YES" >@@ -61,13 +63,14 @@ iwm7265fw_load="YES" > iwm7265Dfw_load="YES" > iwm8000Cfw_load="YES" > iwm8265fw_load="YES" >+iwm9000fw_load="YES" >+iwm9260fw_load="YES" > .Ed > .Sh DESCRIPTION > This module provides access to firmware sets for the >-Intel Dual Band Wireless WiFi 3160, 3165, 3168, 7260, 7265, 8000, and 8260 series of >-IEEE 802.11n/11ac adapters. >-It may be >-statically linked into the kernel, or loaded as a module. >+Intel Dual Band Wireless WiFi 3160, 3165, 3168, 7260, 7265, 8000, 8260, >+9000 and 9260 series of IEEE 802.11n/11ac adapters. >+It may be statically linked into the kernel, or loaded as a module. > .Sh SEE ALSO > .Xr iwm 4 , > .Xr firmware 9 >diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c >index 067768dcd0f8..53118b046d5f 100644 >--- a/sys/dev/iwm/if_iwm.c >+++ b/sys/dev/iwm/if_iwm.c >@@ -322,16 +322,14 @@ static int iwm_mvm_load_ucode_wait_alive(struct iwm_softc *, > static int iwm_run_init_mvm_ucode(struct iwm_softc *, int); > static int iwm_mvm_config_ltr(struct iwm_softc *sc); > static int iwm_rx_addbuf(struct iwm_softc *, int, int); >-static int iwm_mvm_get_signal_strength(struct iwm_softc *, >- struct iwm_rx_phy_info *); > static void iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *, > struct iwm_rx_packet *); > static int iwm_get_noise(struct iwm_softc *, > const struct iwm_mvm_statistics_rx_non_phy *); > static void iwm_mvm_handle_rx_statistics(struct iwm_softc *, > struct iwm_rx_packet *); >-static boolean_t iwm_mvm_rx_rx_mpdu(struct iwm_softc *, struct mbuf *, >- uint32_t, boolean_t); >+static bool iwm_mvm_rx_mpdu(struct iwm_softc *, struct mbuf *, >+ uint32_t, bool); > static int iwm_mvm_rx_tx_cmd_single(struct iwm_softc *, > struct iwm_rx_packet *, > struct iwm_node *); >@@ -793,7 +791,7 @@ iwm_read_firmware(struct iwm_softc *sc) > break; > } > >- case 48: /* undocumented TLV */ >+ case IWM_UCODE_TLV_CMD_VERSIONS: > case IWM_UCODE_TLV_SDIO_ADMA_ADDR: > case IWM_UCODE_TLV_FW_GSCAN_CAPA: > /* ignore, not used by current driver */ >@@ -864,10 +862,9 @@ iwm_read_firmware(struct iwm_softc *sc) > > default: > device_printf(sc->sc_dev, >- "%s: unknown firmware section %d, abort\n", >+ "%s: unknown firmware section %d\n", > __func__, tlv_type); >- error = EINVAL; >- goto parse_out; >+ break; > } > } > >@@ -929,19 +926,28 @@ static int > iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) > { > bus_size_t size; >- int i, error; >+ size_t descsz; >+ int count, i, error; > > ring->cur = 0; >+ if (sc->cfg->mqrx_supported) { >+ count = IWM_RX_MQ_RING_COUNT; >+ descsz = sizeof(uint64_t); >+ } else { >+ count = IWM_RX_LEGACY_RING_COUNT; >+ descsz = sizeof(uint32_t); >+ } > > /* Allocate RX descriptors (256-byte aligned). */ >- size = IWM_RX_RING_COUNT * sizeof(uint32_t); >- error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256); >+ size = count * descsz; >+ error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->free_desc_dma, size, >+ 256); > if (error != 0) { > device_printf(sc->sc_dev, > "could not allocate RX ring DMA memory\n"); > goto fail; > } >- ring->desc = ring->desc_dma.vaddr; >+ ring->desc = ring->free_desc_dma.vaddr; > > /* Allocate RX status area (16-byte aligned). */ > error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->stat_dma, >@@ -953,6 +959,17 @@ iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) > } > ring->stat = ring->stat_dma.vaddr; > >+ if (sc->cfg->mqrx_supported) { >+ size = count * sizeof(uint32_t); >+ error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->used_desc_dma, >+ size, 256); >+ if (error != 0) { >+ device_printf(sc->sc_dev, >+ "could not allocate RX ring DMA memory\n"); >+ goto fail; >+ } >+ } >+ > /* Create RX buffer DMA tag. */ > error = bus_dma_tag_create(sc->sc_dmat, 1, 0, > BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, >@@ -972,10 +989,11 @@ iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) > __func__, error); > goto fail; > } >+ > /* > * Allocate and map RX buffers. > */ >- for (i = 0; i < IWM_RX_RING_COUNT; i++) { >+ for (i = 0; i < count; i++) { > struct iwm_rx_data *data = &ring->data[i]; > error = bus_dmamap_create(ring->data_dmat, 0, &data->map); > if (error != 0) { >@@ -1013,12 +1031,16 @@ iwm_reset_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) > static void > iwm_free_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) > { >- int i; >+ int count, i; > >- iwm_dma_contig_free(&ring->desc_dma); >+ iwm_dma_contig_free(&ring->free_desc_dma); > iwm_dma_contig_free(&ring->stat_dma); >+ iwm_dma_contig_free(&ring->used_desc_dma); >+ >+ count = sc->cfg->mqrx_supported ? IWM_RX_MQ_RING_COUNT : >+ IWM_RX_LEGACY_RING_COUNT; > >- for (i = 0; i < IWM_RX_RING_COUNT; i++) { >+ for (i = 0; i < count; i++) { > struct iwm_rx_data *data = &ring->data[i]; > > if (data->m != NULL) { >@@ -1315,12 +1337,14 @@ iwm_stop_device(struct iwm_softc *sc) > /* Stop the device, and put it in low power state */ > iwm_apm_stop(sc); > >- /* Upon stop, the APM issues an interrupt if HW RF kill is set. >- * Clean again the interrupt here >+ /* stop and reset the on-board processor */ >+ IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET); >+ DELAY(5000); >+ >+ /* >+ * Upon stop, the APM issues an interrupt if HW RF kill is set. > */ > iwm_disable_interrupts(sc); >- /* stop and reset the on-board processor */ >- IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET); > > /* > * Even if we stop the HW, we still want the RF kill >@@ -1328,6 +1352,8 @@ iwm_stop_device(struct iwm_softc *sc) > */ > iwm_enable_rfkill_int(sc); > iwm_check_rfkill(sc); >+ >+ iwm_prepare_card_hw(sc); > } > > /* iwlwifi: mvm/ops.c */ >@@ -1356,7 +1382,15 @@ iwm_mvm_nic_config(struct iwm_softc *sc) > reg_val |= radio_cfg_step << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_STEP; > reg_val |= radio_cfg_dash << IWM_CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; > >- IWM_WRITE(sc, IWM_CSR_HW_IF_CONFIG_REG, reg_val); >+ IWM_WRITE(sc, IWM_CSR_HW_IF_CONFIG_REG, >+ IWM_CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | >+ IWM_CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP | >+ IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP | >+ IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH | >+ IWM_CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE | >+ IWM_CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | >+ IWM_CSR_HW_IF_CONFIG_REG_BIT_MAC_SI | >+ reg_val); > > IWM_DPRINTF(sc, IWM_DEBUG_RESET, > "Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type, >@@ -1375,12 +1409,61 @@ iwm_mvm_nic_config(struct iwm_softc *sc) > } > > static int >-iwm_nic_rx_init(struct iwm_softc *sc) >+iwm_nic_rx_mq_init(struct iwm_softc *sc) >+{ >+ int enabled; >+ >+ if (!iwm_nic_lock(sc)) >+ return EBUSY; >+ >+ /* Stop RX DMA. */ >+ iwm_write_prph(sc, IWM_RFH_RXF_DMA_CFG, 0); >+ /* Disable RX used and free queue operation. */ >+ iwm_write_prph(sc, IWM_RFH_RXF_RXQ_ACTIVE, 0); >+ >+ iwm_write_prph64(sc, IWM_RFH_Q0_FRBDCB_BA_LSB, >+ sc->rxq.free_desc_dma.paddr); >+ iwm_write_prph64(sc, IWM_RFH_Q0_URBDCB_BA_LSB, >+ sc->rxq.used_desc_dma.paddr); >+ iwm_write_prph64(sc, IWM_RFH_Q0_URBD_STTS_WPTR_LSB, >+ sc->rxq.stat_dma.paddr); >+ iwm_write_prph(sc, IWM_RFH_Q0_FRBDCB_WIDX, 0); >+ iwm_write_prph(sc, IWM_RFH_Q0_FRBDCB_RIDX, 0); >+ iwm_write_prph(sc, IWM_RFH_Q0_URBDCB_WIDX, 0); >+ >+ /* We configure only queue 0 for now. */ >+ enabled = ((1 << 0) << 16) | (1 << 0); >+ >+ /* Enable RX DMA, 4KB buffer size. */ >+ iwm_write_prph(sc, IWM_RFH_RXF_DMA_CFG, >+ IWM_RFH_DMA_EN_ENABLE_VAL | >+ IWM_RFH_RXF_DMA_RB_SIZE_4K | >+ IWM_RFH_RXF_DMA_MIN_RB_4_8 | >+ IWM_RFH_RXF_DMA_DROP_TOO_LARGE_MASK | >+ IWM_RFH_RXF_DMA_RBDCB_SIZE_512); >+ >+ /* Enable RX DMA snooping. */ >+ iwm_write_prph(sc, IWM_RFH_GEN_CFG, >+ IWM_RFH_GEN_CFG_RFH_DMA_SNOOP | >+ IWM_RFH_GEN_CFG_SERVICE_DMA_SNOOP | >+ (sc->cfg->integrated ? IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_64 : >+ IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_128)); >+ >+ /* Enable the configured queue(s). */ >+ iwm_write_prph(sc, IWM_RFH_RXF_RXQ_ACTIVE, enabled); >+ >+ iwm_nic_unlock(sc); >+ >+ IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF); >+ >+ IWM_WRITE(sc, IWM_RFH_Q0_FRBDCB_WIDX_TRG, 8); >+ >+ return (0); >+} >+ >+static int >+iwm_nic_rx_legacy_init(struct iwm_softc *sc) > { >- /* >- * Initialize RX ring. This is from the iwn driver. >- */ >- memset(sc->rxq.stat, 0, sizeof(*sc->rxq.stat)); > > /* Stop Rx DMA */ > iwm_pcie_rx_stop(sc); >@@ -1396,7 +1479,8 @@ iwm_nic_rx_init(struct iwm_softc *sc) > > /* Set physical address of RX ring (256-byte aligned). */ > IWM_WRITE(sc, >- IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG, sc->rxq.desc_dma.paddr >> 8); >+ IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG, >+ sc->rxq.free_desc_dma.paddr >> 8); > > /* Set physical address of RX status (16-byte aligned). */ > IWM_WRITE(sc, >@@ -1425,19 +1509,22 @@ iwm_nic_rx_init(struct iwm_softc *sc) > if (sc->cfg->host_interrupt_operation_mode) > IWM_SETBITS(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_OPER_MODE); > >- /* >- * Thus sayeth el jefe (iwlwifi) via a comment: >- * >- * This value should initially be 0 (before preparing any >- * RBs), should be 8 after preparing the first 8 RBs (for example) >- */ >- IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, 8); >- > iwm_nic_unlock(sc); > >+ IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, 8); >+ > return 0; > } > >+static int >+iwm_nic_rx_init(struct iwm_softc *sc) >+{ >+ if (sc->cfg->mqrx_supported) >+ return iwm_nic_rx_mq_init(sc); >+ else >+ return iwm_nic_rx_legacy_init(sc); >+} >+ > static int > iwm_nic_tx_init(struct iwm_softc *sc) > { >@@ -1466,7 +1553,9 @@ iwm_nic_tx_init(struct iwm_softc *sc) > (unsigned long) (txq->desc_dma.paddr >> 8)); > } > >- iwm_write_prph(sc, IWM_SCD_GP_CTRL, IWM_SCD_GP_CTRL_AUTO_ACTIVE_MODE); >+ iwm_set_bits_prph(sc, IWM_SCD_GP_CTRL, >+ IWM_SCD_GP_CTRL_AUTO_ACTIVE_MODE | >+ IWM_SCD_GP_CTRL_ENABLE_31_QUEUES); > > iwm_nic_unlock(sc); > >@@ -1503,25 +1592,31 @@ iwm_nic_init(struct iwm_softc *sc) > int > iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo) > { >+ int qmsk; >+ >+ qmsk = 1 << qid; >+ > if (!iwm_nic_lock(sc)) { >- device_printf(sc->sc_dev, >- "%s: cannot enable txq %d\n", >- __func__, >- qid); >+ device_printf(sc->sc_dev, "%s: cannot enable txq %d\n", >+ __func__, qid); > return EBUSY; > } > > IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, qid << 8 | 0); > > if (qid == IWM_MVM_CMD_QUEUE) { >- /* unactivate before configuration */ >+ /* Disable the scheduler. */ >+ iwm_write_prph(sc, IWM_SCD_EN_CTRL, 0); >+ >+ /* Stop the TX queue prior to configuration. */ > iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid), >- (0 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) >- | (1 << IWM_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); >+ (0 << IWM_SCD_QUEUE_STTS_REG_POS_ACTIVE) | >+ (1 << IWM_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); > > iwm_nic_unlock(sc); > >- iwm_clear_bits_prph(sc, IWM_SCD_AGGR_SEL, (1 << qid)); >+ /* Disable aggregations for this queue. */ >+ iwm_clear_bits_prph(sc, IWM_SCD_AGGR_SEL, qmsk); > > if (!iwm_nic_lock(sc)) { > device_printf(sc->sc_dev, >@@ -1531,7 +1626,8 @@ iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo) > iwm_write_prph(sc, IWM_SCD_QUEUE_RDPTR(qid), 0); > iwm_nic_unlock(sc); > >- iwm_write_mem32(sc, sc->scd_base_addr + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0); >+ iwm_write_mem32(sc, >+ sc->scd_base_addr + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid), 0); > /* Set scheduler window size and frame limit. */ > iwm_write_mem32(sc, > sc->scd_base_addr + IWM_SCD_CONTEXT_QUEUE_OFFSET(qid) + >@@ -1551,6 +1647,9 @@ iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo) > (fifo << IWM_SCD_QUEUE_STTS_REG_POS_TXF) | > (1 << IWM_SCD_QUEUE_STTS_REG_POS_WSL) | > IWM_SCD_QUEUE_STTS_REG_MSK); >+ >+ /* Enable the scheduler for this queue. */ >+ iwm_write_prph(sc, IWM_SCD_EN_CTRL, qmsk); > } else { > struct iwm_scd_txq_cfg_cmd cmd; > int error; >@@ -1577,9 +1676,6 @@ iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo) > return EBUSY; > } > >- iwm_write_prph(sc, IWM_SCD_EN_CTRL, >- iwm_read_prph(sc, IWM_SCD_EN_CTRL) | qid); >- > iwm_nic_unlock(sc); > > IWM_DPRINTF(sc, IWM_DEBUG_XMIT, "%s: enabled txq %d FIFO %d\n", >@@ -1651,7 +1747,7 @@ iwm_trans_pcie_fw_alive(struct iwm_softc *sc, uint32_t scd_base_addr) > iwm_nic_unlock(sc); > > /* Enable L1-Active */ >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) { >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) { > iwm_clear_bits_prph(sc, IWM_APMG_PCIDEV_STT_REG, > IWM_APMG_PCIDEV_STT_VAL_L1_ACT_DIS); > } >@@ -2069,7 +2165,7 @@ static int > iwm_get_sku(const struct iwm_softc *sc, const uint16_t *nvm_sw, > const uint16_t *phy_sku) > { >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) > return le16_to_cpup(nvm_sw + IWM_SKU); > > return le32_to_cpup((const uint32_t *)(phy_sku + IWM_SKU_8000)); >@@ -2078,7 +2174,7 @@ iwm_get_sku(const struct iwm_softc *sc, const uint16_t *nvm_sw, > static int > iwm_get_nvm_version(const struct iwm_softc *sc, const uint16_t *nvm_sw) > { >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) > return le16_to_cpup(nvm_sw + IWM_NVM_VERSION); > else > return le32_to_cpup((const uint32_t *)(nvm_sw + >@@ -2089,7 +2185,7 @@ static int > iwm_get_radio_cfg(const struct iwm_softc *sc, const uint16_t *nvm_sw, > const uint16_t *phy_sku) > { >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) > return le16_to_cpup(nvm_sw + IWM_RADIO_CFG); > > return le32_to_cpup((const uint32_t *)(phy_sku + IWM_RADIO_CFG_8000)); >@@ -2100,7 +2196,7 @@ iwm_get_n_hw_addrs(const struct iwm_softc *sc, const uint16_t *nvm_sw) > { > int n_hw_addr; > >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) > return le16_to_cpup(nvm_sw + IWM_N_HW_ADDRS); > > n_hw_addr = le32_to_cpup((const uint32_t *)(nvm_sw + IWM_N_HW_ADDRS_8000)); >@@ -2112,7 +2208,7 @@ static void > iwm_set_radio_cfg(const struct iwm_softc *sc, struct iwm_nvm_data *data, > uint32_t radio_cfg) > { >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) { >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) { > data->radio_cfg_type = IWM_NVM_RF_CFG_TYPE_MSK(radio_cfg); > data->radio_cfg_step = IWM_NVM_RF_CFG_STEP_MSK(radio_cfg); > data->radio_cfg_dash = IWM_NVM_RF_CFG_DASH_MSK(radio_cfg); >@@ -2138,7 +2234,7 @@ iwm_set_hw_address(struct iwm_softc *sc, struct iwm_nvm_data *data, > iwm_set_hw_address_from_csr(sc, data); > } else > #endif >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) { >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) { > const uint8_t *hw_addr = (const uint8_t *)(nvm_hw + IWM_HW_ADDR); > > /* The byte order is little endian 16 bit, meaning 214365 */ >@@ -2170,7 +2266,7 @@ iwm_parse_nvm_data(struct iwm_softc *sc, > uint32_t sku, radio_cfg; > uint16_t lar_config; > >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) { >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) { > data = malloc(sizeof(*data) + > IWM_NUM_CHANNELS * sizeof(uint16_t), > M_DEVBUF, M_NOWAIT | M_ZERO); >@@ -2194,7 +2290,8 @@ iwm_parse_nvm_data(struct iwm_softc *sc, > > data->n_hw_addrs = iwm_get_n_hw_addrs(sc, nvm_sw); > >- if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) { >+ if (sc->cfg->device_family >= IWM_DEVICE_FAMILY_8000) { >+ /* TODO: use IWL_NVM_EXT */ > uint16_t lar_offset = data->nvm_version < 0xE39 ? > IWM_NVM_LAR_OFFSET_8000_OLD : > IWM_NVM_LAR_OFFSET_8000; >@@ -2242,7 +2339,7 @@ iwm_parse_nvm_sections(struct iwm_softc *sc, struct iwm_nvm_section *sections) > "Can't parse empty OTP/NVM sections\n"); > return NULL; > } >- } else if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) { >+ } else if (sc->cfg->device_family >= IWM_DEVICE_FAMILY_8000) { > /* SW and REGULATORY sections are mandatory */ > if (!sections[IWM_NVM_SECTION_TYPE_SW].data || > !sections[IWM_NVM_SECTION_TYPE_REGULATORY].data) { >@@ -2672,7 +2769,7 @@ iwm_start_fw(struct iwm_softc *sc, const struct iwm_fw_img *fw) > IWM_WRITE(sc, IWM_CSR_UCODE_DRV_GP1_CLR, IWM_CSR_UCODE_SW_BIT_RFKILL); > > /* Load the given image to the HW */ >- if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) >+ if (sc->cfg->device_family >= IWM_DEVICE_FAMILY_8000) > ret = iwm_pcie_load_given_ucode_8000(sc, fw); > else > ret = iwm_pcie_load_given_ucode(sc, fw); >@@ -2823,7 +2920,7 @@ iwm_mvm_load_ucode_wait_alive(struct iwm_softc *sc, > IWM_MVM_UCODE_ALIVE_TIMEOUT); > IWM_LOCK(sc); > if (error) { >- if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) { >+ if (sc->cfg->device_family >= IWM_DEVICE_FAMILY_8000) { > uint32_t a = 0x5a5a5a5a, b = 0x5a5a5a5a; > if (iwm_nic_lock(sc)) { > a = iwm_read_prph(sc, IWM_SB_CPU_1_STATUS); >@@ -2914,6 +3011,15 @@ iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm) > goto error; > } > >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) { >+ ret = iwm_send_bt_init_conf(sc); >+ if (ret) { >+ device_printf(sc->sc_dev, >+ "failed to send bt coex configuration: %d\n", ret); >+ goto error; >+ } >+ } >+ > if (justnvm) { > /* Read nvm */ > ret = iwm_nvm_init(sc); >@@ -2925,13 +3031,6 @@ iwm_run_init_mvm_ucode(struct iwm_softc *sc, int justnvm) > goto error; > } > >- ret = iwm_send_bt_init_conf(sc); >- if (ret) { >- device_printf(sc->sc_dev, >- "failed to send bt coex configuration: %d\n", ret); >- goto error; >- } >- > /* Send TX valid antennas before triggering calibrations */ > ret = iwm_send_tx_ant_cfg(sc, iwm_mvm_get_valid_tx_ant(sc)); > if (ret) { >@@ -3025,46 +3124,17 @@ iwm_rx_addbuf(struct iwm_softc *sc, int size, int idx) > > /* Update RX descriptor. */ > KASSERT((seg.ds_addr & 255) == 0, ("seg.ds_addr not aligned")); >- ring->desc[idx] = htole32(seg.ds_addr >> 8); >- bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, >+ if (sc->cfg->mqrx_supported) >+ ((uint64_t *)ring->desc)[idx] = >+ htole64(seg.ds_addr | (idx + 1)); >+ else >+ ((uint32_t *)ring->desc)[idx] = htole32(seg.ds_addr >> 8); >+ bus_dmamap_sync(ring->free_desc_dma.tag, ring->free_desc_dma.map, > BUS_DMASYNC_PREWRITE); > > return 0; > } > >-/* iwlwifi: mvm/rx.c */ >-/* >- * iwm_mvm_get_signal_strength - use new rx PHY INFO API >- * values are reported by the fw as positive values - need to negate >- * to obtain their dBM. Account for missing antennas by replacing 0 >- * values by -256dBm: practically 0 power and a non-feasible 8 bit value. >- */ >-static int >-iwm_mvm_get_signal_strength(struct iwm_softc *sc, struct iwm_rx_phy_info *phy_info) >-{ >- int energy_a, energy_b, energy_c, max_energy; >- uint32_t val; >- >- val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_ENERGY_ANT_ABC_IDX]); >- energy_a = (val & IWM_RX_INFO_ENERGY_ANT_A_MSK) >> >- IWM_RX_INFO_ENERGY_ANT_A_POS; >- energy_a = energy_a ? -energy_a : -256; >- energy_b = (val & IWM_RX_INFO_ENERGY_ANT_B_MSK) >> >- IWM_RX_INFO_ENERGY_ANT_B_POS; >- energy_b = energy_b ? -energy_b : -256; >- energy_c = (val & IWM_RX_INFO_ENERGY_ANT_C_MSK) >> >- IWM_RX_INFO_ENERGY_ANT_C_POS; >- energy_c = energy_c ? -energy_c : -256; >- max_energy = MAX(energy_a, energy_b); >- max_energy = MAX(max_energy, energy_c); >- >- IWM_DPRINTF(sc, IWM_DEBUG_RECV, >- "energy In A %d B %d C %d , and max %d\n", >- energy_a, energy_b, energy_c, max_energy); >- >- return max_energy; >-} >- > static void > iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt) > { >@@ -3118,19 +3188,65 @@ iwm_mvm_handle_rx_statistics(struct iwm_softc *sc, struct iwm_rx_packet *pkt) > sc->sc_noise = iwm_get_noise(sc, &stats->rx.general); > } > >+/* iwlwifi: mvm/rx.c */ >+/* >+ * iwm_mvm_get_signal_strength - use new rx PHY INFO API >+ * values are reported by the fw as positive values - need to negate >+ * to obtain their dBM. Account for missing antennas by replacing 0 >+ * values by -256dBm: practically 0 power and a non-feasible 8 bit value. >+ */ >+static int >+iwm_mvm_rx_get_signal_strength(struct iwm_softc *sc, >+ struct iwm_rx_phy_info *phy_info) >+{ >+ int energy_a, energy_b, energy_c, max_energy; >+ uint32_t val; >+ >+ val = le32toh(phy_info->non_cfg_phy[IWM_RX_INFO_ENERGY_ANT_ABC_IDX]); >+ energy_a = (val & IWM_RX_INFO_ENERGY_ANT_A_MSK) >> >+ IWM_RX_INFO_ENERGY_ANT_A_POS; >+ energy_a = energy_a ? -energy_a : -256; >+ energy_b = (val & IWM_RX_INFO_ENERGY_ANT_B_MSK) >> >+ IWM_RX_INFO_ENERGY_ANT_B_POS; >+ energy_b = energy_b ? -energy_b : -256; >+ energy_c = (val & IWM_RX_INFO_ENERGY_ANT_C_MSK) >> >+ IWM_RX_INFO_ENERGY_ANT_C_POS; >+ energy_c = energy_c ? -energy_c : -256; >+ max_energy = MAX(energy_a, energy_b); >+ max_energy = MAX(max_energy, energy_c); >+ >+ IWM_DPRINTF(sc, IWM_DEBUG_RECV, >+ "energy In A %d B %d C %d , and max %d\n", >+ energy_a, energy_b, energy_c, max_energy); >+ >+ return max_energy; >+} >+ >+static int >+iwm_mvm_rxmq_get_signal_strength(struct iwm_softc *sc, >+ struct iwm_rx_mpdu_desc *desc) >+{ >+ int energy_a, energy_b; >+ >+ energy_a = desc->v1.energy_a; >+ energy_b = desc->v1.energy_b; >+ energy_a = energy_a ? -energy_a : -256; >+ energy_b = energy_b ? -energy_b : -256; >+ return MAX(energy_a, energy_b); >+} >+ > /* > * iwm_mvm_rx_rx_mpdu - IWM_REPLY_RX_MPDU_CMD handler > * > * Handles the actual data of the Rx packet from the fw > */ >-static boolean_t >+static bool > iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, >- boolean_t stolen) >+ bool stolen) > { > struct ieee80211com *ic = &sc->sc_ic; > struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); > struct ieee80211_frame *wh; >- struct ieee80211_node *ni; > struct ieee80211_rx_stats rxs; > struct iwm_rx_phy_info *phy_info; > struct iwm_rx_mpdu_res_start *rx_res; >@@ -3149,17 +3265,17 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, > device_printf(sc->sc_dev, > "dsp size out of range [0,20]: %d\n", > phy_info->cfg_phy_cnt); >- goto fail; >+ return false; > } > > if (!(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_CRC_OK) || > !(rx_pkt_status & IWM_RX_MPDU_RES_STATUS_OVERRUN_OK)) { > IWM_DPRINTF(sc, IWM_DEBUG_RECV, > "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status); >- goto fail; >+ return false; > } > >- rssi = iwm_mvm_get_signal_strength(sc, phy_info); >+ rssi = iwm_mvm_rx_get_signal_strength(sc, phy_info); > > /* Map it to relative value */ > rssi = rssi - sc->sc_noise; >@@ -3168,7 +3284,7 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, > if (!stolen && iwm_rx_addbuf(sc, IWM_RBUF_SIZE, sc->rxq.cur) != 0) { > device_printf(sc->sc_dev, "%s: unable to add more buffers\n", > __func__); >- goto fail; >+ return false; > } > > m->m_data = pkt->data + sizeof(*rx_res); >@@ -3177,8 +3293,6 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, > IWM_DPRINTF(sc, IWM_DEBUG_RECV, > "%s: rssi=%d, noise=%d\n", __func__, rssi, sc->sc_noise); > >- ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); >- > IWM_DPRINTF(sc, IWM_DEBUG_RECV, > "%s: phy_info: channel=%d, flags=0x%08x\n", > __func__, >@@ -3201,11 +3315,8 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, > /* rssi is in 1/2db units */ > rxs.c_rssi = rssi * 2; > rxs.c_nf = sc->sc_noise; >- if (ieee80211_add_rx_params(m, &rxs) == 0) { >- if (ni) >- ieee80211_free_node(ni); >- goto fail; >- } >+ if (ieee80211_add_rx_params(m, &rxs) == 0) >+ return false; > > if (ieee80211_radiotap_active_vap(vap)) { > struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap; >@@ -3239,6 +3350,139 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, > } > } > >+ return true; >+} >+ >+static bool >+iwm_mvm_rx_mpdu_mq(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, >+ bool stolen) >+{ >+ struct ieee80211com *ic = &sc->sc_ic; >+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); >+ struct ieee80211_frame *wh; >+ struct ieee80211_rx_stats rxs; >+ struct iwm_rx_mpdu_desc *desc; >+ struct iwm_rx_packet *pkt; >+ int rssi; >+ uint32_t hdrlen, len, rate_n_flags; >+ uint16_t phy_info; >+ uint8_t channel; >+ >+ pkt = mtodo(m, offset); >+ desc = (void *)pkt->data; >+ >+ if (!(desc->status & htole16(IWM_RX_MPDU_RES_STATUS_CRC_OK)) || >+ !(desc->status & htole16(IWM_RX_MPDU_RES_STATUS_OVERRUN_OK))) { >+ IWM_DPRINTF(sc, IWM_DEBUG_RECV, >+ "Bad CRC or FIFO: 0x%08X.\n", desc->status); >+ return false; >+ } >+ >+ channel = desc->v1.channel; >+ len = le16toh(desc->mpdu_len); >+ phy_info = le16toh(desc->phy_info); >+ rate_n_flags = desc->v1.rate_n_flags; >+ >+ wh = mtodo(m, sizeof(*desc)); >+ m->m_data = pkt->data + sizeof(*desc); >+ m->m_pkthdr.len = m->m_len = len; >+ m->m_len = len; >+ >+ /* Account for padding following the frame header. */ >+ if ((desc->mac_flags2 & IWM_RX_MPDU_MFLG2_PAD)) { >+ hdrlen = ieee80211_anyhdrsize(wh); >+ memmove(mtodo(m, 2), mtodo(m, 0), hdrlen); >+ m->m_data = mtodo(m, 2); >+ wh = mtod(m, struct ieee80211_frame *); >+ } >+ >+ /* Map it to relative value */ >+ rssi = iwm_mvm_rxmq_get_signal_strength(sc, desc); >+ rssi = rssi - sc->sc_noise; >+ >+ /* replenish ring for the buffer we're going to feed to the sharks */ >+ if (!stolen && iwm_rx_addbuf(sc, IWM_RBUF_SIZE, sc->rxq.cur) != 0) { >+ device_printf(sc->sc_dev, "%s: unable to add more buffers\n", >+ __func__); >+ return false; >+ } >+ >+ IWM_DPRINTF(sc, IWM_DEBUG_RECV, >+ "%s: rssi=%d, noise=%d\n", __func__, rssi, sc->sc_noise); >+ >+ /* >+ * Populate an RX state struct with the provided information. >+ */ >+ bzero(&rxs, sizeof(rxs)); >+ rxs.r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ; >+ rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI; >+ rxs.c_ieee = channel; >+ rxs.c_freq = ieee80211_ieee2mhz(rxs.c_ieee, >+ channel <= 14 ? IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ); >+ >+ /* rssi is in 1/2db units */ >+ rxs.c_rssi = rssi * 2; >+ rxs.c_nf = sc->sc_noise; >+ if (ieee80211_add_rx_params(m, &rxs) == 0) >+ return false; >+ >+ if (ieee80211_radiotap_active_vap(vap)) { >+ struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap; >+ >+ tap->wr_flags = 0; >+ if ((phy_info & IWM_RX_MPDU_PHY_SHORT_PREAMBLE) != 0) >+ tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; >+ tap->wr_chan_freq = htole16(rxs.c_freq); >+ /* XXX only if ic->ic_curchan->ic_ieee == rxs.c_ieee */ >+ tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); >+ tap->wr_dbm_antsignal = (int8_t)rssi; >+ tap->wr_dbm_antnoise = (int8_t)sc->sc_noise; >+ tap->wr_tsft = desc->v1.gp2_on_air_rise; >+ switch ((rate_n_flags & 0xff)) { >+ /* CCK rates. */ >+ case 10: tap->wr_rate = 2; break; >+ case 20: tap->wr_rate = 4; break; >+ case 55: tap->wr_rate = 11; break; >+ case 110: tap->wr_rate = 22; break; >+ /* OFDM rates. */ >+ case 0xd: tap->wr_rate = 12; break; >+ case 0xf: tap->wr_rate = 18; break; >+ case 0x5: tap->wr_rate = 24; break; >+ case 0x7: tap->wr_rate = 36; break; >+ case 0x9: tap->wr_rate = 48; break; >+ case 0xb: tap->wr_rate = 72; break; >+ case 0x1: tap->wr_rate = 96; break; >+ case 0x3: tap->wr_rate = 108; break; >+ /* Unknown rate: should not happen. */ >+ default: tap->wr_rate = 0; >+ } >+ } >+ >+ return true; >+} >+ >+static bool >+iwm_mvm_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, >+ bool stolen) >+{ >+ struct ieee80211com *ic; >+ struct ieee80211_frame *wh; >+ struct ieee80211_node *ni; >+ bool ret; >+ >+ ic = &sc->sc_ic; >+ >+ ret = sc->cfg->mqrx_supported ? >+ iwm_mvm_rx_mpdu_mq(sc, m, offset, stolen) : >+ iwm_mvm_rx_rx_mpdu(sc, m, offset, stolen); >+ if (!ret) { >+ counter_u64_add(ic->ic_ierrors, 1); >+ return (ret); >+ } >+ >+ wh = mtod(m, struct ieee80211_frame *); >+ ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); >+ > IWM_UNLOCK(sc); > if (ni != NULL) { > IWM_DPRINTF(sc, IWM_DEBUG_RECV, "input m %p\n", m); >@@ -3250,11 +3494,7 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset, > } > IWM_LOCK(sc); > >- return TRUE; >- >-fail: >- counter_u64_add(ic->ic_ierrors, 1); >- return FALSE; >+ return true; > } > > static int >@@ -3338,13 +3578,20 @@ static void > iwm_mvm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt) > { > struct iwm_cmd_header *cmd_hdr = &pkt->hdr; >- int idx = cmd_hdr->idx; >- int qid = cmd_hdr->qid; >- struct iwm_tx_ring *ring = &sc->txq[qid]; >- struct iwm_tx_data *txd = &ring->data[idx]; >- struct iwm_node *in = txd->in; >- struct mbuf *m = txd->m; >- int status; >+ struct iwm_tx_ring *ring; >+ struct iwm_tx_data *txd; >+ struct iwm_node *in; >+ struct mbuf *m; >+ int idx, qid, qmsk, status; >+ >+ idx = cmd_hdr->idx; >+ qid = cmd_hdr->qid; >+ qmsk = 1 << qid; >+ >+ ring = &sc->txq[qid]; >+ txd = &ring->data[idx]; >+ in = txd->in; >+ m = txd->m; > > KASSERT(txd->done == 0, ("txd not done")); > KASSERT(txd->in != NULL, ("txd without node")); >@@ -3366,11 +3613,10 @@ iwm_mvm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt) > > ieee80211_tx_complete(&in->in_ni, m, status); > >- if (--ring->queued < IWM_TX_RING_LOMARK) { >- sc->qfullmsk &= ~(1 << ring->qid); >- if (sc->qfullmsk == 0) { >+ if (--ring->queued < IWM_TX_RING_LOMARK && (sc->qfullmsk & qmsk) != 0) { >+ sc->qfullmsk &= ~qmsk; >+ if (sc->qfullmsk == 0) > iwm_start(sc); >- } > } > } > >@@ -3531,7 +3777,10 @@ iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in, > ); > > /* XXX TODO: hard-coded TX antenna? */ >- rate_flags = 1 << IWM_RATE_MCS_ANT_POS; >+ if (sc->cfg->device_family == IWM_DEVICE_FAMILY_9000) >+ rate_flags = IWM_RATE_MCS_ANT_B_MSK; >+ else >+ rate_flags = IWM_RATE_MCS_ANT_A_MSK; > if (IWM_RIDX_IS_CCK(ridx)) > rate_flags |= IWM_RATE_MCS_CCK_MSK; > tx->rate_n_flags = htole32(rate_flags | rinfo->plcp); >@@ -3568,7 +3817,6 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) > tid = 0; > ring = &sc->txq[ac]; > desc = &ring->desc[ring->cur]; >- memset(desc, 0, sizeof(*desc)); > data = &ring->data[ring->cur]; > > /* Fill out iwm_tx_cmd to send to the firmware */ >@@ -3607,25 +3855,19 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) > ieee80211_radiotap_tx(vap, m); > } > >- >- totlen = m->m_pkthdr.len; >- > flags = 0; >+ totlen = m->m_pkthdr.len; > if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { > flags |= IWM_TX_CMD_FLG_ACK; > } > >- if (type == IEEE80211_FC0_TYPE_DATA >- && (totlen + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) >- && !IEEE80211_IS_MULTICAST(wh->i_addr1)) { >+ if (type == IEEE80211_FC0_TYPE_DATA && >+ totlen + IEEE80211_CRC_LEN > vap->iv_rtsthreshold && >+ !IEEE80211_IS_MULTICAST(wh->i_addr1)) { > flags |= IWM_TX_CMD_FLG_PROT_REQUIRE; > } > >- if (IEEE80211_IS_MULTICAST(wh->i_addr1) || >- type != IEEE80211_FC0_TYPE_DATA) >- tx->sta_id = sc->sc_aux_sta.sta_id; >- else >- tx->sta_id = IWM_STATION_ID; >+ tx->sta_id = IWM_STATION_ID; > > if (type == IEEE80211_FC0_TYPE_MGT) { > uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; >@@ -3645,12 +3887,12 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) > if (hdrlen & 3) { > /* First segment length must be a multiple of 4. */ > flags |= IWM_TX_CMD_FLG_MH_PAD; >+ tx->offload_assist |= htole16(1 << IWM_TX_CMD_OFFLD_PAD); > pad = 4 - (hdrlen & 3); >- } else >+ } else { >+ tx->offload_assist = 0; > pad = 0; >- >- tx->driver_txop = 0; >- tx->next_frame_len = 0; >+ } > > tx->len = htole16(totlen); > tx->tid_tspec = tid; >@@ -3661,7 +3903,7 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) > tx->dram_msb_ptr = iwm_get_dma_hi_addr(data->scratch_paddr); > > /* Copy 802.11 header in TX command. */ >- memcpy(((uint8_t *)tx) + sizeof(*tx), wh, hdrlen); >+ memcpy((uint8_t *)tx + sizeof(*tx), wh, hdrlen); > > flags |= IWM_TX_CMD_FLG_BT_DIS | IWM_TX_CMD_FLG_SEQ_CTL; > >@@ -3715,23 +3957,24 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) > ); > > /* Fill TX descriptor. */ >+ memset(desc, 0, sizeof(*desc)); > desc->num_tbs = 2 + nsegs; > > desc->tbs[0].lo = htole32(data->cmd_paddr); >- desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr)) | >- (TB0_SIZE << 4); >+ desc->tbs[0].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr) | >+ (TB0_SIZE << 4)); > desc->tbs[1].lo = htole32(data->cmd_paddr + TB0_SIZE); >- desc->tbs[1].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr)) | >- ((sizeof(struct iwm_cmd_header) + sizeof(*tx) >- + hdrlen + pad - TB0_SIZE) << 4); >+ desc->tbs[1].hi_n_len = htole16(iwm_get_dma_hi_addr(data->cmd_paddr) | >+ ((sizeof(struct iwm_cmd_header) + sizeof(*tx) + >+ hdrlen + pad - TB0_SIZE) << 4)); > > /* Other DMA segments are for data payload. */ > for (i = 0; i < nsegs; i++) { > seg = &segs[i]; >- desc->tbs[i+2].lo = htole32(seg->ds_addr); >- desc->tbs[i+2].hi_n_len = \ >- htole16(iwm_get_dma_hi_addr(seg->ds_addr)) >- | ((seg->ds_len) << 4); >+ desc->tbs[i + 2].lo = htole32(seg->ds_addr); >+ desc->tbs[i + 2].hi_n_len = >+ htole16(iwm_get_dma_hi_addr(seg->ds_addr)) | >+ (seg->ds_len << 4); > } > > bus_dmamap_sync(ring->data_dmat, data->map, >@@ -4444,8 +4687,7 @@ static boolean_t > iwm_mvm_is_lar_supported(struct iwm_softc *sc) > { > boolean_t nvm_lar = sc->nvm_data->lar_enabled; >- boolean_t tlv_lar = fw_has_capa(&sc->sc_fw.ucode_capa, >- IWM_UCODE_TLV_CAPA_LAR_SUPPORT); >+ boolean_t tlv_lar = iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_LAR_SUPPORT); > > if (iwm_lar_disable) > return FALSE; >@@ -4454,7 +4696,7 @@ iwm_mvm_is_lar_supported(struct iwm_softc *sc) > * Enable LAR only if it is supported by the FW (TLV) && > * enabled in the NVM > */ >- if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) >+ if (sc->cfg->device_family >= IWM_DEVICE_FAMILY_8000) > return nvm_lar && tlv_lar; > else > return tlv_lar; >@@ -4463,10 +4705,8 @@ iwm_mvm_is_lar_supported(struct iwm_softc *sc) > static boolean_t > iwm_mvm_is_wifi_mcc_supported(struct iwm_softc *sc) > { >- return fw_has_api(&sc->sc_fw.ucode_capa, >- IWM_UCODE_TLV_API_WIFI_MCC_UPDATE) || >- fw_has_capa(&sc->sc_fw.ucode_capa, >- IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC); >+ return iwm_fw_has_api(sc, IWM_UCODE_TLV_API_WIFI_MCC_UPDATE) || >+ iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC); > } > > static int >@@ -4486,8 +4726,7 @@ iwm_send_update_mcc_cmd(struct iwm_softc *sc, const char *alpha2) > int n_channels; > uint16_t mcc; > #endif >- int resp_v2 = fw_has_capa(&sc->sc_fw.ucode_capa, >- IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V2); >+ int resp_v2 = iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V2); > > if (!iwm_mvm_is_lar_supported(sc)) { > IWM_DPRINTF(sc, IWM_DEBUG_LAR, "%s: no LAR support\n", >@@ -4648,7 +4887,7 @@ iwm_init_hw(struct iwm_softc *sc) > if ((error = iwm_send_update_mcc_cmd(sc, "ZZ")) != 0) > goto error; > >- if (fw_has_capa(&sc->sc_fw.ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) { >+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) { > if ((error = iwm_mvm_config_umac_scan(sc)) != 0) > goto error; > } >@@ -5148,7 +5387,7 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m) > nextpkt->hdr.idx == 0) || > (nextpkt->len_n_flags == > htole32(IWM_FH_RSCSR_FRAME_INVALID))) { >- if (iwm_mvm_rx_rx_mpdu(sc, m, offset, stolen)) { >+ if (iwm_mvm_rx_mpdu(sc, m, offset, stolen)) { > stolen = FALSE; > /* Make sure we abort the loop */ > nextoff = maxoff; >@@ -5159,14 +5398,14 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m) > /* > * Use m_copym instead of m_split, because that > * makes it easier to keep a valid rx buffer in >- * the ring, when iwm_mvm_rx_rx_mpdu() fails. >+ * the ring, when iwm_mvm_rx_mpdu() fails. > * > * We need to start m_copym() at offset 0, to get the > * M_PKTHDR flag preserved. > */ > m1 = m_copym(m, 0, M_COPYALL, M_NOWAIT); > if (m1) { >- if (iwm_mvm_rx_rx_mpdu(sc, m1, offset, stolen)) >+ if (iwm_mvm_rx_mpdu(sc, m1, offset, stolen)) > stolen = TRUE; > else > m_freem(m1); >@@ -5415,11 +5654,21 @@ iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m) > static void > iwm_notif_intr(struct iwm_softc *sc) > { >+ int count; >+ uint32_t wreg; > uint16_t hw; > > bus_dmamap_sync(sc->rxq.stat_dma.tag, sc->rxq.stat_dma.map, > BUS_DMASYNC_POSTREAD); > >+ if (sc->cfg->mqrx_supported) { >+ count = IWM_RX_MQ_RING_COUNT; >+ wreg = IWM_RFH_Q0_FRBDCB_WIDX_TRG; >+ } else { >+ count = IWM_RX_LEGACY_RING_COUNT; >+ wreg = IWM_FH_RSCSR_CHNL0_WPTR; >+ } >+ > hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff; > > /* >@@ -5436,7 +5685,7 @@ iwm_notif_intr(struct iwm_softc *sc) > "%s: hw = %d cur = %d\n", __func__, hw, ring->cur); > iwm_handle_rxb(sc, data->m); > >- ring->cur = (ring->cur + 1) % IWM_RX_RING_COUNT; >+ ring->cur = (ring->cur + 1) % count; > } > > /* >@@ -5445,8 +5694,8 @@ iwm_notif_intr(struct iwm_softc *sc) > * Seems like the hardware gets upset unless we align > * the write by 8?? > */ >- hw = (hw == 0) ? IWM_RX_RING_COUNT - 1 : hw - 1; >- IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, rounddown2(hw, 8)); >+ hw = (hw == 0) ? count - 1 : hw - 1; >+ IWM_WRITE(sc, wreg, rounddown2(hw, 8)); > } > > static void >@@ -5621,6 +5870,8 @@ iwm_intr(void *arg) > #define PCI_PRODUCT_INTEL_WL_8260_1 0x24f3 > #define PCI_PRODUCT_INTEL_WL_8260_2 0x24f4 > #define PCI_PRODUCT_INTEL_WL_8265_1 0x24fd >+#define PCI_PRODUCT_INTEL_WL_9560_1 0x9df0 >+#define PCI_PRODUCT_INTEL_WL_9260_1 0x2526 > > static const struct iwm_devices { > uint16_t device; >@@ -5638,6 +5889,8 @@ static const struct iwm_devices { > { PCI_PRODUCT_INTEL_WL_8260_1, &iwm8260_cfg }, > { PCI_PRODUCT_INTEL_WL_8260_2, &iwm8260_cfg }, > { PCI_PRODUCT_INTEL_WL_8265_1, &iwm8265_cfg }, >+ { PCI_PRODUCT_INTEL_WL_9560_1, &iwm9560_cfg }, >+ { PCI_PRODUCT_INTEL_WL_9260_1, &iwm9260_cfg }, > }; > > static int >@@ -5749,8 +6002,6 @@ iwm_pci_detach(device_t dev) > rman_get_rid(sc->sc_mem), sc->sc_mem); > } > >- >- > static int > iwm_attach(device_t dev) > { >@@ -5761,12 +6012,17 @@ iwm_attach(device_t dev) > > sc->sc_dev = dev; > sc->sc_attached = 1; >+ sc->sc_debug = (sc->sc_debug | IWM_DEBUG_ANY); > IWM_LOCK_INIT(sc); > mbufq_init(&sc->sc_snd, ifqmaxlen); > callout_init_mtx(&sc->sc_watchdog_to, &sc->sc_mtx, 0); > callout_init_mtx(&sc->sc_led_blink_to, &sc->sc_mtx, 0); > TASK_INIT(&sc->sc_es_task, 0, iwm_endscan_cb, sc); > >+ error = iwm_dev_check(dev); >+ if (error != 0) >+ goto fail; >+ > sc->sc_notif_wait = iwm_notification_wait_init(sc); > if (sc->sc_notif_wait == NULL) { > device_printf(dev, "failed to init notification wait struct\n"); >@@ -5792,11 +6048,6 @@ iwm_attach(device_t dev) > > sc->sc_wantresp = -1; > >- /* Match device id */ >- error = iwm_dev_check(dev); >- if (error != 0) >- goto fail; >- > sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV); > /* > * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have >@@ -5804,7 +6055,7 @@ iwm_attach(device_t dev) > * "dash" value). To keep hw_rev backwards compatible - we'll store it > * in the old format. > */ >- if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) { >+ if (sc->cfg->device_family >= IWM_DEVICE_FAMILY_8000) { > int ret; > uint32_t hw_step; > >@@ -6185,7 +6436,7 @@ iwm_scan_start(struct ieee80211com *ic) > device_printf(sc->sc_dev, > "%s: Previous scan not completed yet\n", __func__); > } >- if (fw_has_capa(&sc->sc_fw.ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) >+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) > error = iwm_mvm_umac_scan(sc); > else > error = iwm_mvm_lmac_scan(sc); >diff --git a/sys/dev/iwm/if_iwm_9000.c b/sys/dev/iwm/if_iwm_9000.c >new file mode 100644 >index 000000000000..fe7898c5b483 >--- /dev/null >+++ b/sys/dev/iwm/if_iwm_9000.c >@@ -0,0 +1,97 @@ >+/*- >+ * Based on BSD-licensed source modules in the Linux iwlwifi driver, >+ * which were used as the reference documentation for this implementation. >+ * >+ ****************************************************************************** >+ * >+ * This file is provided under a dual BSD/GPLv2 license. When using or >+ * redistributing this file, you may do so under either license. >+ * >+ * GPL LICENSE SUMMARY >+ * >+ * Copyright(c) 2014 Intel Corporation. All rights reserved. >+ * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH >+ * Copyright(c) 2016 Intel Deutschland GmbH >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of version 2 of the GNU General Public License as >+ * published by the Free Software Foundation. >+ * >+ * This program is distributed in the hope that it will be useful, but >+ * WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, >+ * USA >+ * >+ * The full GNU General Public License is included in this distribution >+ * in the file called COPYING. >+ * >+ * Contact Information: >+ * Intel Linux Wireless <linuxwifi@intel.com> >+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 >+ * >+ * BSD LICENSE >+ * >+ * Copyright(c) 2014 Intel Corporation. All rights reserved. >+ * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH >+ * All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * * Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * * Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in >+ * the documentation and/or other materials provided with the >+ * distribution. >+ * * Neither the name Intel Corporation nor the names of its >+ * contributors may be used to endorse or promote products derived >+ * from this software without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT >+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR >+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT >+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, >+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT >+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ * >+ *****************************************************************************/ >+ >+#include <sys/cdefs.h> >+__FBSDID("$FreeBSD$"); >+ >+#include "opt_wlan.h" >+#include "opt_iwm.h" >+ >+#include <sys/param.h> >+ >+#include "if_iwm_config.h" >+ >+#define IWM9000_FW "iwm9000fw" >+ >+#define IWM_NVM_HW_SECTION_NUM_FAMILY_9000 10 >+ >+#define IWM_DEVICE_9000_COMMON \ >+ .device_family = IWM_DEVICE_FAMILY_9000, \ >+ .eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_9000, \ >+ .nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_9000 >+ >+const struct iwm_cfg iwm9560_cfg = { >+ .name = "Intel(R) Dual Band Wireless AC 9560", >+ .fw_name = IWM9000_FW, >+ IWM_DEVICE_9000_COMMON, >+ .host_interrupt_operation_mode = 0, >+ .mqrx_supported = 1, >+ .integrated = 1, >+}; >diff --git a/sys/dev/iwm/if_iwm_9260.c b/sys/dev/iwm/if_iwm_9260.c >new file mode 100644 >index 000000000000..a92ba9ebbe35 >--- /dev/null >+++ b/sys/dev/iwm/if_iwm_9260.c >@@ -0,0 +1,96 @@ >+/*- >+ * Based on BSD-licensed source modules in the Linux iwlwifi driver, >+ * which were used as the reference documentation for this implementation. >+ * >+ ****************************************************************************** >+ * >+ * This file is provided under a dual BSD/GPLv2 license. When using or >+ * redistributing this file, you may do so under either license. >+ * >+ * GPL LICENSE SUMMARY >+ * >+ * Copyright(c) 2014 Intel Corporation. All rights reserved. >+ * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH >+ * Copyright(c) 2016 Intel Deutschland GmbH >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of version 2 of the GNU General Public License as >+ * published by the Free Software Foundation. >+ * >+ * This program is distributed in the hope that it will be useful, but >+ * WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program; if not, write to the Free Software >+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, >+ * USA >+ * >+ * The full GNU General Public License is included in this distribution >+ * in the file called COPYING. >+ * >+ * Contact Information: >+ * Intel Linux Wireless <linuxwifi@intel.com> >+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 >+ * >+ * BSD LICENSE >+ * >+ * Copyright(c) 2014 Intel Corporation. All rights reserved. >+ * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH >+ * All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * * Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * * Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in >+ * the documentation and/or other materials provided with the >+ * distribution. >+ * * Neither the name Intel Corporation nor the names of its >+ * contributors may be used to endorse or promote products derived >+ * from this software without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT >+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR >+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT >+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, >+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT >+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ * >+ *****************************************************************************/ >+ >+#include <sys/cdefs.h> >+__FBSDID("$FreeBSD$"); >+ >+#include "opt_wlan.h" >+#include "opt_iwm.h" >+ >+#include <sys/param.h> >+ >+#include "if_iwm_config.h" >+ >+#define IWM9260_FW "iwm9260fw" >+ >+#define IWM_NVM_HW_SECTION_NUM_FAMILY_9260 10 >+ >+#define IWM_DEVICE_9260_COMMON \ >+ .device_family = IWM_DEVICE_FAMILY_9000, \ >+ .eeprom_size = IWM_OTP_LOW_IMAGE_SIZE_FAMILY_9000, \ >+ .nvm_hw_section_num = IWM_NVM_HW_SECTION_NUM_FAMILY_9260 >+ >+const struct iwm_cfg iwm9260_cfg = { >+ .name = "Intel(R) Dual Band Wireless AC 9260", >+ .fw_name = IWM9260_FW, >+ IWM_DEVICE_9260_COMMON, >+ .host_interrupt_operation_mode = 0, >+ .mqrx_supported = 1, >+}; >diff --git a/sys/dev/iwm/if_iwm_config.h b/sys/dev/iwm/if_iwm_config.h >index 4768a16f5261..fabcfaa75184 100644 >--- a/sys/dev/iwm/if_iwm_config.h >+++ b/sys/dev/iwm/if_iwm_config.h >@@ -78,6 +78,7 @@ enum iwm_device_family { > IWM_DEVICE_FAMILY_UNDEFINED, > IWM_DEVICE_FAMILY_7000, > IWM_DEVICE_FAMILY_8000, >+ IWM_DEVICE_FAMILY_9000, > }; > > #define IWM_DEFAULT_MAX_TX_POWER 22 >@@ -130,13 +131,15 @@ enum iwm_nvm_type { > */ > struct iwm_cfg { > const char *name; >- const char *fw_name; >- uint16_t eeprom_size; >- enum iwm_device_family device_family; >- int host_interrupt_operation_mode; >- uint8_t nvm_hw_section_num; >- int apmg_wake_up_wa; >- enum iwm_nvm_type nvm_type; >+ const char *fw_name; >+ uint16_t eeprom_size; >+ enum iwm_device_family device_family; >+ int host_interrupt_operation_mode; >+ int mqrx_supported; >+ int integrated; >+ uint8_t nvm_hw_section_num; >+ int apmg_wake_up_wa; >+ enum iwm_nvm_type nvm_type; > }; > > /* >@@ -150,5 +153,7 @@ extern const struct iwm_cfg iwm7265_cfg; > extern const struct iwm_cfg iwm7265d_cfg; > extern const struct iwm_cfg iwm8260_cfg; > extern const struct iwm_cfg iwm8265_cfg; >+extern const struct iwm_cfg iwm9560_cfg; >+extern const struct iwm_cfg iwm9260_cfg; > > #endif /* __IWM_CONFIG_H__ */ >diff --git a/sys/dev/iwm/if_iwm_pcie_trans.c b/sys/dev/iwm/if_iwm_pcie_trans.c >index a50e47945812..9178a1d2982f 100644 >--- a/sys/dev/iwm/if_iwm_pcie_trans.c >+++ b/sys/dev/iwm/if_iwm_pcie_trans.c >@@ -185,6 +185,27 @@ iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val) > IWM_WRITE(sc, IWM_HBUS_TARG_PRPH_WDAT, val); > } > >+void >+iwm_write_prph64(struct iwm_softc *sc, uint64_t addr, uint64_t val) >+{ >+ iwm_write_prph(sc, (uint32_t)addr, val & 0xffffffff); >+ iwm_write_prph(sc, (uint32_t)addr + 4, val >> 32); >+} >+ >+int >+iwm_poll_prph(struct iwm_softc *sc, uint32_t addr, uint32_t bits, uint32_t mask, >+ int timeout) >+{ >+ do { >+ if ((iwm_read_prph(sc, addr) & mask) == (bits & mask)) >+ return (0); >+ DELAY(10); >+ timeout -= 10; >+ } while (timeout > 0); >+ >+ return (ETIMEDOUT); >+} >+ > #ifdef IWM_DEBUG > /* iwlwifi: pcie/trans.c */ > int >@@ -261,7 +282,7 @@ iwm_nic_lock(struct iwm_softc *sc) > IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, > IWM_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); > >- if (sc->cfg->device_family == IWM_DEVICE_FAMILY_8000) >+ if (sc->cfg->device_family >= IWM_DEVICE_FAMILY_8000) > DELAY(2); > > if (iwm_poll_bit(sc, IWM_CSR_GP_CNTRL, >@@ -325,6 +346,8 @@ iwm_enable_rfkill_int(struct iwm_softc *sc) > { > sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL; > IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask); >+ IWM_SETBITS(sc, IWM_CSR_GP_CNTRL, >+ IWM_CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN); > } > > int >@@ -383,7 +406,9 @@ iwm_prepare_card_hw(struct iwm_softc *sc) > if (iwm_set_hw_ready(sc)) > goto out; > >- DELAY(100); >+ IWM_SETBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG, >+ IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED); >+ DELAY(1000); > > /* If HW is not ready, prepare the conditions to check again */ > IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG, >@@ -454,7 +479,7 @@ iwm_apm_init(struct iwm_softc *sc) > IWM_DPRINTF(sc, IWM_DEBUG_RESET, "iwm apm start\n"); > > /* Disable L0S exit timer (platform NMI Work/Around) */ >- if (sc->cfg->device_family != IWM_DEVICE_FAMILY_8000) { >+ if (sc->cfg->device_family < IWM_DEVICE_FAMILY_8000) { > IWM_SETBITS(sc, IWM_CSR_GIO_CHICKEN_BITS, > IWM_CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); > } >@@ -569,6 +594,16 @@ iwm_apm_init(struct iwm_softc *sc) > void > iwm_apm_stop(struct iwm_softc *sc) > { >+ IWM_SETBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG, >+ IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED); >+ IWM_SETBITS(sc, IWM_CSR_HW_IF_CONFIG_REG, >+ IWM_CSR_HW_IF_CONFIG_REG_PREPARE | >+ IWM_CSR_HW_IF_CONFIG_REG_ENABLE_PME); >+ DELAY(1000); >+ IWM_CLRBITS(sc, IWM_CSR_DBG_LINK_PWR_MGMT_REG, >+ IWM_CSR_RESET_LINK_PWR_MGMT_DISABLED); >+ DELAY(5000); >+ > /* stop device's busmaster DMA activity */ > IWM_SETBITS(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_STOP_MASTER); > >@@ -576,6 +611,14 @@ iwm_apm_stop(struct iwm_softc *sc) > IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, > IWM_CSR_RESET_REG_FLAG_MASTER_DISABLED, 100)) > device_printf(sc->sc_dev, "timeout waiting for master\n"); >+ >+ /* >+ * Clear "initialization complete" bit to move adapter from >+ * D0A* (powered-up Active) --> D0U* (Uninitialized) state. >+ */ >+ IWM_CLRBITS(sc, IWM_CSR_GP_CNTRL, >+ IWM_CSR_GP_CNTRL_REG_FLAG_INIT_DONE); >+ > IWM_DPRINTF(sc, IWM_DEBUG_TRANS, "%s: iwm apm stop\n", __func__); > } > >@@ -590,11 +633,15 @@ iwm_start_hw(struct iwm_softc *sc) > > /* Reset the entire device */ > IWM_WRITE(sc, IWM_CSR_RESET, IWM_CSR_RESET_REG_FLAG_SW_RESET); >- DELAY(10); >+ DELAY(5000); > > if ((error = iwm_apm_init(sc)) != 0) > return error; > >+ /* On newer chipsets MSI is disabled by default. */ >+ if (sc->cfg->mqrx_supported) >+ iwm_write_prph(sc, IWM_UREG_CHICK, IWM_UREG_CHICK_MSI_ENABLE); >+ > iwm_enable_rfkill_int(sc); > iwm_check_rfkill(sc); > >@@ -613,13 +660,21 @@ iwm_set_pwr(struct iwm_softc *sc) > int > iwm_pcie_rx_stop(struct iwm_softc *sc) > { >- int ret = 0; >+ int ret; >+ >+ ret = 0; > if (iwm_nic_lock(sc)) { >- IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); >- ret = iwm_poll_bit(sc, IWM_FH_MEM_RSSR_RX_STATUS_REG, >- IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, >- IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, >- 1000); >+ if (sc->cfg->mqrx_supported) { >+ iwm_write_prph(sc, IWM_RFH_RXF_DMA_CFG, 0); >+ ret = iwm_poll_prph(sc, IWM_RFH_GEN_STATUS, >+ IWM_RXF_DMA_IDLE, IWM_RXF_DMA_IDLE, 1000); >+ } else { >+ IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); >+ ret = iwm_poll_bit(sc, IWM_FH_MEM_RSSR_RX_STATUS_REG, >+ IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, >+ IWM_FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, >+ 1000); >+ } > iwm_nic_unlock(sc); > } > return ret; >diff --git a/sys/dev/iwm/if_iwm_pcie_trans.h b/sys/dev/iwm/if_iwm_pcie_trans.h >index e04dd52f3fe3..bdbd85476af3 100644 >--- a/sys/dev/iwm/if_iwm_pcie_trans.h >+++ b/sys/dev/iwm/if_iwm_pcie_trans.h >@@ -106,6 +106,10 @@ > > extern uint32_t iwm_read_prph(struct iwm_softc *sc, uint32_t addr); > extern void iwm_write_prph(struct iwm_softc *sc, uint32_t addr, uint32_t val); >+extern void iwm_write_prph64(struct iwm_softc *sc, uint64_t addr, >+ uint64_t val); >+extern int iwm_poll_prph(struct iwm_softc *sc, uint32_t addr, uint32_t bits, >+ uint32_t mask, int timeout); > extern int iwm_read_mem(struct iwm_softc *sc, uint32_t addr, void *buf, int dwords); > extern int iwm_write_mem(struct iwm_softc *sc, uint32_t addr, const void *buf, > int dwords); >diff --git a/sys/dev/iwm/if_iwm_scan.c b/sys/dev/iwm/if_iwm_scan.c >index 84948cc27829..5a4331b67d07 100644 >--- a/sys/dev/iwm/if_iwm_scan.c >+++ b/sys/dev/iwm/if_iwm_scan.c >@@ -215,8 +215,7 @@ static inline boolean_t > iwm_mvm_rrm_scan_needed(struct iwm_softc *sc) > { > /* require rrm scan whenever the fw supports it */ >- return fw_has_capa(&sc->sc_fw.ucode_capa, >- IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT); >+ return iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT); > } > > #ifdef IWM_DEBUG >@@ -251,7 +250,7 @@ iwm_mvm_rx_lmac_scan_complete_notif(struct iwm_softc *sc, > /* If this happens, the firmware has mistakenly sent an LMAC > * notification during UMAC scans -- warn and ignore it. > */ >- if (fw_has_capa(&sc->sc_fw.ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) { >+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) { > device_printf(sc->sc_dev, > "%s: Mistakenly got LMAC notification during UMAC scan\n", > __func__); >@@ -581,6 +580,29 @@ iwm_mvm_scan_use_ebs(struct iwm_softc *sc) > sc->last_ebs_successful); > } > >+static int >+iwm_mvm_scan_size(struct iwm_softc *sc) >+{ >+ int base_size; >+ >+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) { >+ if (iwm_fw_has_api(sc, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) >+ base_size = IWM_SCAN_REQ_UMAC_SIZE_V7; >+ else >+ base_size = IWM_SCAN_REQ_UMAC_SIZE_V1; >+ >+ return base_size + >+ sizeof(struct iwm_scan_channel_cfg_umac) * >+ sc->sc_fw.ucode_capa.n_scan_channels + >+ sizeof(struct iwm_scan_req_umac_tail); >+ } else { >+ return sizeof(struct iwm_scan_req_lmac) + >+ sizeof(struct iwm_scan_channel_cfg_lmac) * >+ sc->sc_fw.ucode_capa.n_scan_channels + >+ sizeof(struct iwm_scan_probe_req); >+ } >+} >+ > int > iwm_mvm_umac_scan(struct iwm_softc *sc) > { >@@ -594,13 +616,11 @@ iwm_mvm_umac_scan(struct iwm_softc *sc) > struct iwm_scan_req_umac *req; > struct iwm_scan_req_umac_tail *tail; > size_t req_len; >- uint8_t i, nssid; >+ uint16_t general_flags; >+ uint8_t channel_flags, i, nssid; > int ret; > >- req_len = sizeof(struct iwm_scan_req_umac) + >- (sizeof(struct iwm_scan_channel_cfg_umac) * >- sc->sc_fw.ucode_capa.n_scan_channels) + >- sizeof(struct iwm_scan_req_umac_tail); >+ req_len = iwm_mvm_scan_size(sc); > if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE) > return ENOMEM; > req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO); >@@ -612,28 +632,58 @@ iwm_mvm_umac_scan(struct iwm_softc *sc) > > IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Handling ieee80211 scan request\n"); > >- /* These timings correspond to iwlwifi's UNASSOC scan. */ >- req->active_dwell = 10; >- req->passive_dwell = 110; >- req->fragmented_dwell = 44; >- req->extended_dwell = 90; >- req->max_out_time = 0; >- req->suspend_time = 0; >+ nssid = MIN(ss->ss_nssid, IWM_PROBE_OPTION_MAX); > >- req->scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH); >- req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH); >+ general_flags = IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL | >+ IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; >+ if (!iwm_fw_has_api(sc, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) >+ general_flags |= IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL; >+ if (iwm_mvm_rrm_scan_needed(sc)) >+ general_flags |= IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED; >+ if (nssid != 0) >+ general_flags |= IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT; >+ else >+ general_flags |= IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE; > >- nssid = MIN(ss->ss_nssid, IWM_PROBE_OPTION_MAX); >- req->n_channels = iwm_mvm_umac_scan_fill_channels(sc, >- (struct iwm_scan_channel_cfg_umac *)req->data, nssid); >+ channel_flags = 0; >+ if (iwm_mvm_scan_use_ebs(sc)) >+ channel_flags = IWM_SCAN_CHANNEL_FLAG_EBS | >+ IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE | >+ IWM_SCAN_CHANNEL_FLAG_CACHE_ADD; > >- req->general_flags = htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL | >- IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE | >- IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL); >+ req->general_flags = htole16(general_flags); >+ req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH); > >- tail = (void *)((char *)&req->data + >- sizeof(struct iwm_scan_channel_cfg_umac) * >- sc->sc_fw.ucode_capa.n_scan_channels); >+ /* These timings correspond to iwlwifi's UNASSOC scan. */ >+ if (iwm_fw_has_api(sc, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) { >+ req->v7.active_dwell = 10; >+ req->v7.passive_dwell = 110; >+ req->v7.fragmented_dwell = 44; >+ req->v7.adwell_default_n_aps_social = 10; >+ req->v7.adwell_default_n_aps = 2; >+ req->v7.adwell_max_budget = htole16(300); >+ req->v7.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH); >+ req->v7.channel.flags = channel_flags; >+ req->v7.channel.count = iwm_mvm_umac_scan_fill_channels(sc, >+ (struct iwm_scan_channel_cfg_umac *)req->v7.data, nssid); >+ >+ tail = (void *)((char *)&req->v7.data + >+ sizeof(struct iwm_scan_channel_cfg_umac) * >+ sc->sc_fw.ucode_capa.n_scan_channels); >+ } else { >+ req->v1.active_dwell = 10; >+ req->v1.passive_dwell = 110; >+ req->v1.fragmented_dwell = 44; >+ req->v1.extended_dwell = 90; >+ req->v1.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH); >+ req->v1.channel.flags = channel_flags; >+ req->v1.channel.count = iwm_mvm_umac_scan_fill_channels(sc, >+ (struct iwm_scan_channel_cfg_umac *)req->v1.data, nssid); >+ >+ tail = (void *)((char *)&req->v1.data + >+ sizeof(struct iwm_scan_channel_cfg_umac) * >+ sc->sc_fw.ucode_capa.n_scan_channels); >+ } > > /* Check if we're doing an active directed scan. */ > for (i = 0; i < nssid; i++) { >@@ -644,20 +694,6 @@ iwm_mvm_umac_scan(struct iwm_softc *sc) > tail->direct_scan[i].len); > /* XXX debug */ > } >- if (nssid != 0) { >- req->general_flags |= >- htole32(IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT); >- } else >- req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE); >- >- if (iwm_mvm_scan_use_ebs(sc)) >- req->channel_flags = IWM_SCAN_CHANNEL_FLAG_EBS | >- IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE | >- IWM_SCAN_CHANNEL_FLAG_CACHE_ADD; >- >- if (iwm_mvm_rrm_scan_needed(sc)) >- req->general_flags |= >- htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED); > > ret = iwm_mvm_fill_probe_req(sc, &tail->preq); > if (ret) { >@@ -695,9 +731,7 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc) > IWM_DPRINTF(sc, IWM_DEBUG_SCAN, > "Handling ieee80211 scan request\n"); > >- req_len = sizeof(struct iwm_scan_req_lmac) + >- (sizeof(struct iwm_scan_channel_cfg_lmac) * >- sc->sc_fw.ucode_capa.n_scan_channels) + sizeof(struct iwm_scan_probe_req); >+ req_len = iwm_mvm_scan_size(sc); > if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE) > return ENOMEM; > req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO); >@@ -866,7 +900,7 @@ iwm_mvm_scan_stop_wait(struct iwm_softc *sc) > > IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Preparing to stop scan\n"); > >- if (fw_has_capa(&sc->sc_fw.ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) >+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) > ret = iwm_mvm_umac_scan_abort(sc); > else > ret = iwm_mvm_lmac_scan_abort(sc); >diff --git a/sys/dev/iwm/if_iwm_sta.c b/sys/dev/iwm/if_iwm_sta.c >index 507176710c8c..bfbe5b554868 100644 >--- a/sys/dev/iwm/if_iwm_sta.c >+++ b/sys/dev/iwm/if_iwm_sta.c >@@ -138,13 +138,8 @@ __FBSDID("$FreeBSD$"); > static inline int > iwm_mvm_add_sta_cmd_size(struct iwm_softc *sc) > { >-#ifdef notyet >- return iwm_mvm_has_new_rx_api(mvm) ? >- sizeof(struct iwm_mvm_add_sta_cmd) : >- sizeof(struct iwm_mvm_add_sta_cmd_v7); >-#else >- return sizeof(struct iwm_mvm_add_sta_cmd); >-#endif >+ return sc->cfg->mqrx_supported ? sizeof(struct iwm_mvm_add_sta_cmd) : >+ sizeof(struct iwm_mvm_add_sta_cmd_v7); > } > > /* send station add/update command to firmware */ >@@ -318,7 +313,7 @@ iwm_mvm_rm_sta_id(struct iwm_softc *sc, struct ieee80211vap *vap) > > static int > iwm_mvm_add_int_sta_common(struct iwm_softc *sc, struct iwm_int_sta *sta, >- const uint8_t *addr, uint16_t mac_id, uint16_t color) >+ const uint8_t *addr, uint16_t mac_id, uint16_t color) > { > struct iwm_mvm_add_sta_cmd cmd; > int ret; >@@ -327,6 +322,8 @@ iwm_mvm_add_int_sta_common(struct iwm_softc *sc, struct iwm_int_sta *sta, > memset(&cmd, 0, sizeof(cmd)); > cmd.sta_id = sta->sta_id; > cmd.mac_id_n_color = htole32(IWM_FW_CMD_ID_AND_COLOR(mac_id, color)); >+ if (sta->sta_id == IWM_AUX_STA_ID && sc->cfg->mqrx_supported) >+ cmd.station_type = IWM_STA_AUX_ACTIVITY; > > cmd.tfd_queue_msk = htole32(sta->tfd_queue_msk); > cmd.tid_disable_tx = htole16(0xffff); >@@ -362,7 +359,8 @@ iwm_mvm_add_aux_sta(struct iwm_softc *sc) > sc->sc_aux_sta.tfd_queue_msk = (1 << IWM_MVM_AUX_QUEUE); > > /* Map Aux queue to fifo - needs to happen before adding Aux station */ >- ret = iwm_enable_txq(sc, 0, IWM_MVM_AUX_QUEUE, IWM_MVM_TX_FIFO_MCAST); >+ ret = iwm_enable_txq(sc, IWM_AUX_STA_ID, IWM_MVM_AUX_QUEUE, >+ IWM_MVM_TX_FIFO_MCAST); > if (ret) > return ret; > >diff --git a/sys/dev/iwm/if_iwmreg.h b/sys/dev/iwm/if_iwmreg.h >index 67f1bbff0f07..950b7da03d4a 100644 >--- a/sys/dev/iwm/if_iwmreg.h >+++ b/sys/dev/iwm/if_iwmreg.h >@@ -289,7 +289,7 @@ > #define IWM_CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) > > #define IWM_CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) >-#define IWM_CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000) >+#define IWM_CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN (0x04000000) > #define IWM_CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) > > >@@ -457,6 +457,10 @@ enum iwm_secure_boot_status_reg { > #define IWM_LMPM_CHICK 0xa01ff8 > #define IWM_LMPM_CHICK_EXTENDED_ADDR_SPACE 0x01 > >+#define IWM_UREG_CHICK 0xa05c00 >+#define IWM_UREG_CHICK_MSI_ENABLE 0x01000000 >+#define IWM_UREG_CHICK_MSIX_ENABLE 0x02000000 >+ > #define IWM_FH_TCSR_0_REG0 (0x1D00) > > /* >@@ -635,6 +639,40 @@ P2P_PS_SCM\31UAPSD_SUPPORT\32EBS\33P2P_PS_UAPSD\36BCAST_FILTERING\37GO_UAPSD\40L > * longer than the passive one, which is essential for fragmented scan. > * @IWM_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. > * @IWM_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params >+ * @IWM_UCODE_TLV_API_NEW_VERSION: new versioning format >+ * @IWM_UCODE_TLV_API_SCAN_TSF_REPORT: Scan start time reported in scan >+ * iteration complete notification, and the timestamp reported for RX >+ * received during scan, are reported in TSF of the mac specified in the >+ * scan request. >+ * @IWM_UCODE_TLV_API_TKIP_MIC_KEYS: This ucode supports version 2 of >+ * ADD_MODIFY_STA_KEY_API_S_VER_2. >+ * @IWM_UCODE_TLV_API_STA_TYPE: This ucode supports station type assignement. >+ * @IWM_UCODE_TLV_API_NAN2_VER2: This ucode supports NAN API version 2 >+ * @IWM_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used >+ * @IWM_UCODE_TLV_API_QUOTA_LOW_LATENCY: Quota command includes a field >+ * indicating low latency direction. >+ * @IWM_UCODE_TLV_API_DEPRECATE_TTAK: RX status flag TTAK ok (bit 7) is >+ * deprecated. >+ * @IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2: This ucode supports version 8 >+ * of scan request: SCAN_REQUEST_CMD_UMAC_API_S_VER_8 >+ * @IWM_UCODE_TLV_API_FRAG_EBS: This ucode supports fragmented EBS >+ * @IWM_UCODE_TLV_API_REDUCE_TX_POWER: This ucode supports v5 of >+ * the REDUCE_TX_POWER_CMD. >+ * @IWM_UCODE_TLV_API_SHORT_BEACON_NOTIF: This ucode supports the short >+ * version of the beacon notification. >+ * @IWM_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of >+ * BEACON_FILTER_CONFIG_API_S_VER_4. >+ * @IWM_UCODE_TLV_API_REGULATORY_NVM_INFO: This ucode supports v4 of >+ * REGULATORY_NVM_GET_INFO_RSP_API_S. >+ * @IWM_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of >+ * LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S. >+ * @IWM_UCODE_TLV_API_SCAN_OFFLOAD_CHANS: This ucode supports v2 of >+ * SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S and v3 of >+ * SCAN_OFFLOAD_PROFILES_QUERY_RSP_S. >+ * @IWM_UCODE_TLV_API_MBSSID_HE: This ucode supports v2 of >+ * STA_CONTEXT_DOT11AX_API_S >+ * @IWM_UCODE_TLV_CAPA_SAR_TABLE_VER: This ucode supports different sar >+ * version tables. > * > * @IWM_NUM_UCODE_TLV_API: number of bits used > */ >@@ -642,13 +680,36 @@ enum iwm_ucode_tlv_api { > IWM_UCODE_TLV_API_FRAGMENTED_SCAN = 8, > IWM_UCODE_TLV_API_WIFI_MCC_UPDATE = 9, > IWM_UCODE_TLV_API_LQ_SS_PARAMS = 18, >- >- IWM_NUM_UCODE_TLV_API = 32 >+ IWM_UCODE_TLV_API_NEW_VERSION = 20, >+ IWM_UCODE_TLV_API_SCAN_TSF_REPORT = 28, >+ IWM_UCODE_TLV_API_TKIP_MIC_KEYS = 29, >+ IWM_UCODE_TLV_API_STA_TYPE = 30, >+ IWM_UCODE_TLV_API_NAN2_VER2 = 31, >+ IWM_UCODE_TLV_API_ADAPTIVE_DWELL = 32, >+ IWM_UCODE_TLV_API_OCE = 33, >+ IWM_UCODE_TLV_API_NEW_BEACON_TEMPLATE = 34, >+ IWM_UCODE_TLV_API_NEW_RX_STATS = 35, >+ IWM_UCODE_TLV_API_WOWLAN_KEY_MATERIAL = 36, >+ IWM_UCODE_TLV_API_QUOTA_LOW_LATENCY = 38, >+ IWM_UCODE_TLV_API_DEPRECATE_TTAK = 41, >+ IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2 = 42, >+ IWM_UCODE_TLV_API_FRAG_EBS = 44, >+ IWM_UCODE_TLV_API_REDUCE_TX_POWER = 45, >+ IWM_UCODE_TLV_API_SHORT_BEACON_NOTIF = 46, >+ IWM_UCODE_TLV_API_BEACON_FILTER_V4 = 47, >+ IWM_UCODE_TLV_API_REGULATORY_NVM_INFO = 48, >+ IWM_UCODE_TLV_API_FTM_NEW_RANGE_REQ = 49, >+ IWM_UCODE_TLV_API_SCAN_OFFLOAD_CHANS = 50, >+ IWM_UCODE_TLV_API_MBSSID_HE = 52, >+ IWM_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE = 53, >+ IWM_UCODE_TLV_API_FTM_RTT_ACCURACY = 54, >+ IWM_UCODE_TLV_API_SAR_TABLE_VER = 55, >+ IWM_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = 57, >+ IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER = 58, >+ >+ IWM_NUM_UCODE_TLV_API = 128, > }; > >-#define IWM_UCODE_TLV_API_BITS \ >- "\020\10FRAGMENTED_SCAN\11WIFI_MCC_UPDATE\16WIDE_CMD_HDR\22LQ_SS_PARAMS\30EXT_SCAN_PRIO\33TX_POWER_CHAIN" >- > /** > * enum iwm_ucode_tlv_capa - ucode capabilities > * @IWM_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 >@@ -933,6 +994,7 @@ enum iwm_ucode_tlv_type { > IWM_UCODE_TLV_FW_DBG_DEST = 38, > IWM_UCODE_TLV_FW_DBG_CONF = 39, > IWM_UCODE_TLV_FW_DBG_TRIGGER = 40, >+ IWM_UCODE_TLV_CMD_VERSIONS = 48, > IWM_UCODE_TLV_FW_GSCAN_CAPA = 50, > IWM_UCODE_TLV_FW_MEM_SEG = 51, > }; >@@ -1469,6 +1531,52 @@ static inline unsigned int IWM_FH_MEM_CBBC_QUEUE(unsigned int chnl) > > #define IWM_FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 > >+/* 9000 rx series registers */ >+ >+#define IWM_RFH_Q0_FRBDCB_BA_LSB 0xa08000 >+#define IWM_RFH_Q_FRBDCB_BA_LSB (IWM_RFH_Q0_FRBDCB_BA_LSB + (q) * 8) >+/* Write index table */ >+#define IWM_RFH_Q0_FRBDCB_WIDX 0xa08080 >+#define IWM_RFH_Q_FRBDCB_WIDX (IWM_RFH_Q0_FRBDCB_WIDX + (q) * 4) >+/* Write index table - shadow registers */ >+#define IWM_RFH_Q0_FRBDCB_WIDX_TRG 0x1c80 >+#define IWM_RFH_Q_FRBDCB_WIDX_TRG (IWM_RFH_Q0_FRBDCB_WIDX_TRG + (q) * 4) >+/* Read index table */ >+#define IWM_RFH_Q0_FRBDCB_RIDX 0xa080c0 >+#define IWM_RFH_Q_FRBDCB_RIDX (IWM_RFH_Q0_FRBDCB_RIDX + (q) * 4) >+/* Used list table */ >+#define IWM_RFH_Q0_URBDCB_BA_LSB 0xa08100 >+#define IWM_RFH_Q_URBDCB_BA_LSB (IWM_RFH_Q0_URBDCB_BA_LSB + (q) * 8) >+/* Write index table */ >+#define IWM_RFH_Q0_URBDCB_WIDX 0xa08180 >+#define IWM_RFH_Q_URBDCB_WIDX (IWM_RFH_Q0_URBDCB_WIDX + (q) * 4) >+/* stts */ >+#define IWM_RFH_Q0_URBD_STTS_WPTR_LSB 0xa08200 >+#define IWM_RFH_Q_URBD_STTS_WPTR_LSB (IWM_RFH_Q0_URBD_STTS_WPTR_LSB + (q) * 8) >+ >+#define IWM_RFH_GEN_STATUS 0xa09808 >+#define IWM_RXF_DMA_IDLE 0x80000000 >+ >+/* DMA configuration */ >+#define IWM_RFH_RXF_DMA_CFG 0xa09820 >+#define IWM_RFH_RXF_DMA_RB_SIZE_1K 0x00010000 >+#define IWM_RFH_RXF_DMA_RB_SIZE_2K 0x00020000 >+#define IWM_RFH_RXF_DMA_RB_SIZE_4K 0x00040000 >+#define IWM_RFH_RXF_DMA_RBDCB_SIZE_512 0x00900000 >+#define IWM_RFH_RXF_DMA_MIN_RB_4_8 0x03000000 >+#define IWM_RFH_RXF_DMA_DROP_TOO_LARGE_MASK 0x04000000 >+#define IWM_RFH_DMA_EN_ENABLE_VAL 0x80000000 >+ >+#define IWM_RFH_GEN_CFG 0xa09800 >+#define IWM_RFH_GEN_CFG_SERVICE_DMA_SNOOP 0x00000001 >+#define IWM_RFH_GEN_CFG_RFH_DMA_SNOOP 0x00000002 >+#define IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_128 0x00000010 >+#define IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_64 0x00000000 >+ >+#define IWM_RFH_RXF_RXQ_ACTIVE 0xa0980c >+ >+/* end of 9000 rx series registers */ >+ > /* TFDB Area - TFDs buffer table */ > #define IWM_FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) > #define IWM_FH_TFDIB_LOWER_BOUND (IWM_FH_MEM_LOWER_BOUND + 0x900) >@@ -2799,6 +2907,69 @@ enum iwm_mvm_rx_status { > IWM_RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000), > }; > >+enum iwm_rx_mpdu_mac_flags1 { >+ IWM_RX_MPDU_MFLG1_ADDRTYPE_MASK = 0x03, >+ IWM_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK = 0xf0, >+ IWM_RX_MPDU_MFLG1_MIC_CRC_LEN_SHIFT = 3, >+}; >+ >+enum iwm_rx_mpdu_mac_flags2 { >+ IWM_RX_MPDU_MFLG2_HDR_LEN_MASK = 0x1f, >+ IWM_RX_MPDU_MFLG2_PAD = 0x20, >+ IWM_RX_MPDU_MFLG2_AMSDU = 0x40, >+}; >+ >+enum iwm_rx_mpdu_phy_info { >+ IWM_RX_MPDU_PHY_AMPDU = (1 << 5), >+ IWM_RX_MPDU_PHY_AMPDU_TOGGLE = (1 << 6), >+ IWM_RX_MPDU_PHY_SHORT_PREAMBLE = (1 << 7), >+ IWM_RX_MPDU_PHY_NCCK_ADDTL_NTFY = (1 << 7), >+ IWM_RX_MPDU_PHY_TSF_OVERLOAD = (1 << 8), >+}; >+ >+struct iwm_rx_mpdu_desc_v1 { >+ union { >+ uint32_t rss_hash; >+ uint32_t phy_data2; >+ }; >+ union { >+ uint32_t filter_match; >+ uint32_t phy_data3; >+ }; >+ uint32_t rate_n_flags; >+ uint8_t energy_a; >+ uint8_t energy_b; >+ uint8_t channel; >+ uint8_t mac_context; >+ uint32_t gp2_on_air_rise; >+ union { >+ uint64_t tsf_on_air_rise; >+ struct { >+ uint32_t phy_data0; >+ uint32_t phy_data1; >+ }; >+ }; >+} __packed; >+ >+struct iwm_rx_mpdu_desc { >+ uint16_t mpdu_len; >+ uint8_t mac_flags1; >+ uint8_t mac_flags2; >+ uint8_t amsdu_info; >+ uint16_t phy_info; >+ uint8_t mac_phy_idx; >+ uint16_t raw_csum; >+ union { >+ uint16_t l3l4_flags; >+ uint16_t phy_data4; >+ }; >+ uint16_t status; >+ uint8_t hash_filter; >+ uint8_t sta_id_flags; >+ uint32_t reorder_data; >+ struct iwm_rx_mpdu_desc_v1 v1; >+} __packed; >+ > /** > * struct iwm_radio_version_notif - information on the radio version > * ( IWM_RADIO_VERSION_NOTIFICATION = 0x68 ) >@@ -4306,13 +4477,41 @@ enum iwm_tx_pm_timeouts { > #define IWM_BAR_DFAULT_RETRY_LIMIT 60 > #define IWM_LOW_RETRY_LIMIT 7 > >+/** >+ * enum iwm_tx_offload_assist_flags_pos - set %iwm_tx_cmd offload_assist values >+ * @IWM_TX_CMD_OFFLD_IP_HDR: offset to start of IP header (in words) >+ * from mac header end. For normal case it is 4 words for SNAP. >+ * note: tx_cmd, mac header and pad are not counted in the offset. >+ * This is used to help the offload in case there is tunneling such as >+ * IPv6 in IPv4, in such case the ip header offset should point to the >+ * inner ip header and IPv4 checksum of the external header should be >+ * calculated by driver. >+ * @IWM_TX_CMD_OFFLD_L4_EN: enable TCP/UDP checksum >+ * @IWM_TX_CMD_OFFLD_L3_EN: enable IP header checksum >+ * @IWM_TX_CMD_OFFLD_MH_SIZE: size of the mac header in words. Includes the IV >+ * field. Doesn't include the pad. >+ * @IWM_TX_CMD_OFFLD_PAD: mark 2-byte pad was inserted after the mac header for >+ * alignment >+ * @IWM_TX_CMD_OFFLD_AMSDU: mark TX command is A-MSDU >+ */ >+enum iwm_tx_offload_assist_flags_pos { >+ IWM_TX_CMD_OFFLD_IP_HDR = 0, >+ IWM_TX_CMD_OFFLD_L4_EN = 6, >+ IWM_TX_CMD_OFFLD_L3_EN = 7, >+ IWM_TX_CMD_OFFLD_MH_SIZE = 8, >+ IWM_TX_CMD_OFFLD_PAD = 13, >+ IWM_TX_CMD_OFFLD_AMSDU = 14, >+}; >+ >+#define IWM_TX_CMD_OFFLD_MH_MASK 0x1f >+#define IWM_TX_CMD_OFFLD_IP_HDR_MASK 0x3f >+ > /* TODO: complete documentation for try_cnt and btkill_cnt */ > /** > * struct iwm_tx_cmd - TX command struct to FW > * ( IWM_TX_CMD = 0x1c ) > * @len: in bytes of the payload, see below for details >- * @next_frame_len: same as len, but for next frame (0 if not applicable) >- * Used for fragmentation and bursting, but not in 11n aggregation. >+ * @offload_assist: TX offload configuration > * @tx_flags: combination of IWM_TX_CMD_FLG_* > * @rate_n_flags: rate for *all* Tx attempts, if IWM_TX_CMD_FLG_STA_RATE_MSK is > * cleared. Combination of IWM_RATE_MCS_* >@@ -4348,7 +4547,7 @@ enum iwm_tx_pm_timeouts { > */ > struct iwm_tx_cmd { > uint16_t len; >- uint16_t next_frame_len; >+ uint16_t offload_assist; > uint32_t tx_flags; > struct { > uint8_t try_cnt; >@@ -4361,8 +4560,7 @@ struct iwm_tx_cmd { > uint8_t initial_rate_index; > uint8_t reserved2; > uint8_t key[16]; >- uint16_t next_frame_flags; >- uint16_t reserved3; >+ uint32_t reserved3; > uint32_t life_time; > uint32_t dram_lsb_ptr; > uint8_t dram_msb_ptr; >@@ -4370,7 +4568,7 @@ struct iwm_tx_cmd { > uint8_t data_retry_limit; > uint8_t tid_tspec; > uint16_t pm_frame_timeout; >- uint16_t driver_txop; >+ uint16_t reserved4; > uint8_t payload[0]; > struct ieee80211_frame hdr[0]; > } __packed; /* IWM_TX_CMD_API_S_VER_3 */ >@@ -5289,22 +5487,45 @@ struct iwm_scan_req_umac_tail { > struct iwm_ssid_ie direct_scan[IWM_PROBE_OPTION_MAX]; > } __packed; > >+/** >+ * struct iwm_scan_uma_chan_param >+ * @flags: channel flags &enum iwm_scan_channel_flags >+ * @count: num of channels in scan request >+ * @reserved: for future use and alignment >+ */ >+struct iwm_scan_umac_chan_param { >+ uint8_t flags; >+ uint8_t count; >+ uint16_t reserved; >+} __packed; >+ > /** > * struct iwm_scan_req_umac > * @flags: &enum iwm_umac_scan_flags > * @uid: scan id, &enum iwm_umac_scan_uid_offsets > * @ooc_priority: out of channel priority - &enum iwm_scan_priority > * @general_flags: &enum iwm_umac_scan_general_flags >+ * @scan_start_mac_id: report the scan start TSF time according to this mac TSF > * @extended_dwell: dwell time for channels 1, 6 and 11 >- * @active_dwell: dwell time for active scan >- * @passive_dwell: dwell time for passive scan >+ * @active_dwell: dwell time for active scan per LMAC >+ * @passive_dwell: dwell time for passive scan per LMAC > * @fragmented_dwell: dwell time for fragmented passive scan >- * @max_out_time: max out of serving channel time >- * @suspend_time: max suspend time >- * @scan_priority: scan internal prioritization &enum iwm_scan_priority >- * @channel_flags: &enum iwm_scan_channel_flags >- * @n_channels: num of channels in scan request >+ * @adwell_default_n_aps: for adaptive dwell the default number of APs >+ * per channel >+ * @adwell_default_n_aps_social: for adaptive dwell the default >+ * number of APs per social (1,6,11) channel >+ * @general_flags2: &enum iwl_umac_scan_general_flags2 >+ * @adwell_max_budget: for adaptive dwell the maximal budget of TU to be added >+ * to total scan time >+ * @max_out_time: max out of serving channel time, per LMAC - for CDB there >+ * are 2 LMACs >+ * @suspend_time: max suspend time, per LMAC - for CDB there are 2 LMACs >+ * @scan_priority: scan internal prioritization &enum iwl_scan_priority >+ * @num_of_fragments: Number of fragments needed for full coverage per band. >+ * Relevant only for fragmented scan. >+ * @channel: &struct iwl_scan_umac_chan_param > * @reserved: for future use and alignment >+ * @reserved3: for future use and alignment > * @data: &struct iwm_scan_channel_cfg_umac and > * &struct iwm_scan_req_umac_tail > */ >@@ -5312,21 +5533,40 @@ struct iwm_scan_req_umac { > uint32_t flags; > uint32_t uid; > uint32_t ooc_priority; >- /* SCAN_GENERAL_PARAMS_API_S_VER_1 */ >- uint32_t general_flags; >- uint8_t extended_dwell; >- uint8_t active_dwell; >- uint8_t passive_dwell; >- uint8_t fragmented_dwell; >- uint32_t max_out_time; >- uint32_t suspend_time; >- uint32_t scan_priority; >- /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */ >- uint8_t channel_flags; >- uint8_t n_channels; >- uint16_t reserved; >- uint8_t data[]; >-} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */ >+ uint16_t general_flags; >+ uint8_t reserved; >+ uint8_t scan_start_mac_id; >+ union { >+ struct { >+ uint8_t extended_dwell; >+ uint8_t active_dwell; >+ uint8_t passive_dwell; >+ uint8_t fragmented_dwell; >+ uint32_t max_out_time; >+ uint32_t suspend_time; >+ uint32_t scan_priority; >+ struct iwm_scan_umac_chan_param channel; >+ uint8_t data[]; >+ } v1; >+ struct { >+ uint8_t active_dwell; >+ uint8_t passive_dwell; >+ uint8_t fragmented_dwell; >+ uint8_t adwell_default_n_aps; >+ uint8_t adwell_default_n_aps_social; >+ uint8_t reserved3; >+ uint16_t adwell_max_budget; >+ uint32_t max_out_time[2]; >+ uint32_t suspend_time[2]; >+ uint32_t scan_priority; >+ struct iwm_scan_umac_chan_param channel; >+ uint8_t data[]; >+ } v7; >+ }; >+} __packed; >+ >+#define IWM_SCAN_REQ_UMAC_SIZE_V7 48 >+#define IWM_SCAN_REQ_UMAC_SIZE_V1 36 > > /** > * struct iwm_umac_scan_abort >@@ -5636,30 +5876,34 @@ struct iwm_mvm_keyinfo { > #define IWM_ADD_STA_BAID_SHIFT 8 > > /** >- * struct iwm_mvm_add_sta_cmd - Add/modify a station in the fw's sta table. >+ * struct iwl_mvm_add_sta_cmd_v7 - Add/modify a station in the fw's sta table. > * ( REPLY_ADD_STA = 0x18 ) >- * @add_modify: 1: modify existing, 0: add new station >- * @awake_acs: >+ * @add_modify: see &enum iwl_sta_mode >+ * @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD) > * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable >- * AMPDU for tid x. Set %IWM_STA_MODIFY_TID_DISABLE_TX to change this field. >- * @mac_id_n_color: the Mac context this station belongs to >- * @addr[IEEE80211_ADDR_LEN]: station's MAC address >+ * AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field. >+ * @mac_id_n_color: the Mac context this station belongs to, >+ * see &enum iwl_ctxt_id_and_color >+ * @addr: station's MAC address >+ * @reserved2: reserved > * @sta_id: index of station in uCode's station table >- * @modify_mask: IWM_STA_MODIFY_*, selects which parameters to modify vs. leave >+ * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave > * alone. 1 - modify, 0 - don't change. >- * @station_flags: look at %iwm_sta_flags >- * @station_flags_msk: what of %station_flags have changed >+ * @reserved3: reserved >+ * @station_flags: look at &enum iwl_sta_flags >+ * @station_flags_msk: what of %station_flags have changed, >+ * also &enum iwl_sta_flags > * @add_immediate_ba_tid: tid for which to add block-ack support (Rx) >- * Set %IWM_STA_MODIFY_ADD_BA_TID to use this field, and also set >+ * Set %STA_MODIFY_ADD_BA_TID to use this field, and also set > * add_immediate_ba_ssn. > * @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx) >- * Set %IWM_STA_MODIFY_REMOVE_BA_TID to use this field >+ * Set %STA_MODIFY_REMOVE_BA_TID to use this field > * @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with > * add_immediate_ba_tid. > * @sleep_tx_count: number of packets to transmit to station even though it is > * asleep. Used to synchronise PS-poll and u-APSD responses while ucode > * keeps track of STA sleep state. >- * @sleep_state_flags: Look at %iwm_sta_sleep_flag. >+ * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag. > * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP > * mac-addr. > * @beamform_flags: beam forming controls >@@ -5667,12 +5911,12 @@ struct iwm_mvm_keyinfo { > * > * The device contains an internal table of per-station information, with info > * on security keys, aggregation parameters, and Tx rates for initial Tx >- * attempt and any retries (set by IWM_REPLY_TX_LINK_QUALITY_CMD). >+ * attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD). > * > * ADD_STA sets up the table entry for one station, either creating a new > * entry, or modifying a pre-existing one. > */ >-struct iwm_mvm_add_sta_cmd { >+struct iwm_mvm_add_sta_cmd_v7 { > uint8_t add_modify; > uint8_t awake_acs; > uint16_t tid_disable_tx; >@@ -5691,9 +5935,100 @@ struct iwm_mvm_add_sta_cmd { > uint16_t sleep_state_flags; > uint16_t assoc_id; > uint16_t beamform_flags; >- uint32_t tfd_queue_msk; >+ uint16_t tfd_queue_msk; > } __packed; /* ADD_STA_CMD_API_S_VER_7 */ > >+/** >+ * enum iwm_sta_type - FW station types >+ * ( REPLY_ADD_STA = 0x18 ) >+ * @IWM_STA_LINK: Link station - normal RX and TX traffic. >+ * @IWM_STA_GENERAL_PURPOSE: General purpose. In AP mode used for beacons >+ * and probe responses. >+ * @IWM_STA_MULTICAST: multicast traffic, >+ * @IWM_STA_TDLS_LINK: TDLS link station >+ * @IWM_STA_AUX_ACTIVITY: auxilary station (scan, ROC and so on). >+ */ >+enum iwm_sta_type { >+ IWM_STA_LINK, >+ IWM_STA_GENERAL_PURPOSE, >+ IWM_STA_MULTICAST, >+ IWM_STA_TDLS_LINK, >+ IWM_STA_AUX_ACTIVITY, >+}; >+ >+/** >+ * struct iwm_mvm_add_sta_cmd - Add/modify a station in the fw's sta table. >+ * ( REPLY_ADD_STA = 0x18 ) >+ * @add_modify: see &enum iwm_sta_mode >+ * @awake_acs: ACs to transmit data on while station is sleeping (for U-APSD) >+ * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable >+ * AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field. >+ * @mac_id_n_color: the Mac context this station belongs to, >+ * see &enum iwl_ctxt_id_and_color >+ * @addr: station's MAC address >+ * @reserved2: reserved >+ * @sta_id: index of station in uCode's station table >+ * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave >+ * alone. 1 - modify, 0 - don't change. >+ * @reserved3: reserved >+ * @station_flags: look at &enum iwm_sta_flags >+ * @station_flags_msk: what of %station_flags have changed, >+ * also &enum iwm_sta_flags >+ * @add_immediate_ba_tid: tid for which to add block-ack support (Rx) >+ * Set %STA_MODIFY_ADD_BA_TID to use this field, and also set >+ * add_immediate_ba_ssn. >+ * @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx) >+ * Set %STA_MODIFY_REMOVE_BA_TID to use this field >+ * @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with >+ * add_immediate_ba_tid. >+ * @sleep_tx_count: number of packets to transmit to station even though it is >+ * asleep. Used to synchronise PS-poll and u-APSD responses while ucode >+ * keeps track of STA sleep state. >+ * @station_type: type of this station. See &enum iwl_sta_type. >+ * @sleep_state_flags: Look at &enum iwl_sta_sleep_flag. >+ * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP >+ * mac-addr. >+ * @beamform_flags: beam forming controls >+ * @tfd_queue_msk: tfd queues used by this station. >+ * Obselete for new TX API (9 and above). >+ * @rx_ba_window: aggregation window size >+ * @sp_length: the size of the SP in actual number of frames >+ * @uapsd_acs: 4 LS bits are trigger enabled ACs, 4 MS bits are the deliver >+ * enabled ACs. >+ * >+ * The device contains an internal table of per-station information, with info >+ * on security keys, aggregation parameters, and Tx rates for initial Tx >+ * attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD). >+ * >+ * ADD_STA sets up the table entry for one station, either creating a new >+ * entry, or modifying a pre-existing one. >+ */ >+struct iwm_mvm_add_sta_cmd { >+ uint8_t add_modify; >+ uint8_t awake_acs; >+ uint16_t tid_disable_tx; >+ uint32_t mac_id_n_color; >+ uint8_t addr[IEEE80211_ADDR_LEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */ >+ uint16_t reserved2; >+ uint8_t sta_id; >+ uint8_t modify_mask; >+ uint16_t reserved3; >+ uint32_t station_flags; >+ uint32_t station_flags_msk; >+ uint8_t add_immediate_ba_tid; >+ uint8_t remove_immediate_ba_tid; >+ uint16_t add_immediate_ba_ssn; >+ uint16_t sleep_tx_count; >+ uint8_t sleep_state_flags; >+ uint8_t station_type; >+ uint16_t assoc_id; >+ uint16_t beamform_flags; >+ uint32_t tfd_queue_msk; >+ uint16_t rx_ba_window; >+ uint8_t sp_length; >+ uint8_t uapsd_acs; >+} __packed; /* ADD_STA_CMD_API_S_VER_10 */ >+ > /** > * struct iwm_mvm_add_sta_key_cmd - add/modify sta key > * ( IWM_REPLY_ADD_STA_KEY = 0x17 ) >diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h >index 4f303d1ec8de..353d5e921a26 100644 >--- a/sys/dev/iwm/if_iwmvar.h >+++ b/sys/dev/iwm/if_iwmvar.h >@@ -165,20 +165,6 @@ struct iwm_ucode_capabilities { > uint8_t enabled_capa[howmany(IWM_NUM_UCODE_TLV_CAPA, NBBY)]; > }; > >-static inline int >-fw_has_api(const struct iwm_ucode_capabilities *capabilities, >- unsigned int api) >-{ >- return isset(capabilities->enabled_api, api); >-} >- >-static inline int >-fw_has_capa(const struct iwm_ucode_capabilities *capabilities, >- unsigned int capa) >-{ >- return isset(capabilities->enabled_capa, capa); >-} >- > /* one for each uCode image (inst/data, init/runtime/wowlan) */ > struct iwm_fw_desc { > const void *data; /* vmalloc'ed data */ >@@ -299,11 +285,12 @@ struct iwm_tx_ring { > int cur; > }; > >-#define IWM_RX_RING_COUNT 256 >-/* Linux driver optionally uses 8k buffer */ >+#define IWM_RX_LEGACY_RING_COUNT 256 >+#define IWM_RX_MQ_RING_COUNT 512 >+ > #define IWM_RBUF_SIZE 4096 > >-#define IWM_MAX_SCATTER 20 >+#define IWM_MAX_SCATTER 20 > > struct iwm_rx_data { > struct mbuf *m; >@@ -311,12 +298,13 @@ struct iwm_rx_data { > }; > > struct iwm_rx_ring { >- struct iwm_dma_info desc_dma; >+ struct iwm_dma_info free_desc_dma; >+ struct iwm_dma_info used_desc_dma; > struct iwm_dma_info stat_dma; > struct iwm_dma_info buf_dma; >- uint32_t *desc; >+ void *desc; > struct iwm_rb_status *stat; >- struct iwm_rx_data data[IWM_RX_RING_COUNT]; >+ struct iwm_rx_data data[512]; > bus_dmamap_t spare_map; /* for iwm_rx_addbuf() */ > bus_dma_tag_t data_dmat; > int cur; >@@ -459,8 +447,6 @@ struct iwm_softc { > struct iwm_rx_ring rxq; > int qfullmsk; > >- int sc_sf_state; >- > /* ICT table. */ > struct iwm_dma_info ict_dma; > int ict_cur; >@@ -526,8 +512,6 @@ struct iwm_softc { > struct iwm_notif_statistics_v10 sc_stats; > int sc_noise; > >- caddr_t sc_drvbpf; >- > struct iwm_rx_radiotap_header sc_rxtap; > struct iwm_tx_radiotap_header sc_txtap; > >@@ -580,3 +564,15 @@ struct iwm_softc { > #define IWM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) > #define IWM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) > #define IWM_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) >+ >+static inline bool >+iwm_fw_has_api(struct iwm_softc *sc, unsigned int api) >+{ >+ return isset(sc->sc_fw.ucode_capa.enabled_api, api); >+} >+ >+static inline bool >+iwm_fw_has_capa(struct iwm_softc *sc, unsigned int capa) >+{ >+ return isset(sc->sc_fw.ucode_capa.enabled_capa, capa); >+} >diff --git a/sys/modules/iwm/Makefile b/sys/modules/iwm/Makefile >index 58153c84662e..809cb4b3e85b 100644 >--- a/sys/modules/iwm/Makefile >+++ b/sys/modules/iwm/Makefile >@@ -7,7 +7,8 @@ KMOD= if_iwm > SRCS= if_iwm.c if_iwm_binding.c if_iwm_util.c if_iwm_phy_db.c > SRCS+= if_iwm_mac_ctxt.c if_iwm_phy_ctxt.c if_iwm_time_event.c > SRCS+= if_iwm_power.c if_iwm_scan.c if_iwm_led.c if_iwm_notif_wait.c >-SRCS+= if_iwm_7000.c if_iwm_8000.c if_iwm_fw.c if_iwm_sta.c if_iwm_sf.c >+SRCS+= if_iwm_7000.c if_iwm_8000.c if_iwm_9000.c if_iwm_fw.c if_iwm_9260.c >+SRCS+= if_iwm_sta.c if_iwm_sf.c > # bus layer > SRCS+= if_iwm_pcie_trans.c > SRCS+= device_if.h bus_if.h pci_if.h opt_wlan.h opt_iwm.h
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 227044
:
202728
| 208925 |
208985
|
208986