commit 97d56f38b13cc9e5f6b08359c17794d4b1a2bd12 Author: Mark Johnston Date: Sat Oct 26 01:07:30 2019 -0600 wip diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c index 64d4907b131..f3b95bd012e 100644 --- a/sys/dev/iwm/if_iwm.c +++ b/sys/dev/iwm/if_iwm.c @@ -934,7 +934,7 @@ iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) ring->cur = 0; /* Allocate RX descriptors (256-byte aligned). */ - size = IWM_RX_RING_COUNT * sizeof(uint32_t); + size = IWM_RX_RING_COUNT * sizeof(uint64_t); error = iwm_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma, size, 256); if (error != 0) { device_printf(sc->sc_dev, @@ -953,6 +953,17 @@ iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) } ring->stat = ring->stat_dma.vaddr; + size = IWM_RX_RING_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; + } + /* XXX something needs to go here */ + //ring->desc = ring->desc_dma.vaddr; + /* Create RX buffer DMA tag. */ error = bus_dma_tag_create(sc->sc_dmat, 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, @@ -975,7 +986,7 @@ iwm_alloc_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) /* * Allocate and map RX buffers. */ - for (i = 0; i < IWM_RX_RING_COUNT; i++) { + for (i = 0; i < IWM_RX_RING_COUNT - 1; i++) { struct iwm_rx_data *data = &ring->data[i]; error = bus_dmamap_create(ring->data_dmat, 0, &data->map); if (error != 0) { @@ -1017,6 +1028,7 @@ iwm_free_rx_ring(struct iwm_softc *sc, struct iwm_rx_ring *ring) iwm_dma_contig_free(&ring->desc_dma); iwm_dma_contig_free(&ring->stat_dma); + iwm_dma_contig_free(&ring->used_desc_dma); for (i = 0; i < IWM_RX_RING_COUNT; i++) { struct iwm_rx_data *data = &ring->data[i]; @@ -1382,12 +1394,51 @@ iwm_nic_rx_init(struct iwm_softc *sc) */ memset(sc->rxq.stat, 0, sizeof(*sc->rxq.stat)); +#if 0 /* Stop Rx DMA */ iwm_pcie_rx_stop(sc); +#endif if (!iwm_nic_lock(sc)) return EBUSY; +#if 1 + iwm_write_prph(sc, IWM_RFH_RXF_DMA_CFG, 0); + + iwm_write_prph(sc, IWM_RFH_RXF_RXQ_ACTIVE, 0); + + printf("%lx\n", sc->rxq.desc_dma.paddr); + iwm_write_prph64(sc, IWM_RFH_Q0_FRBDCB_BA_LSB, sc->rxq.desc_dma.paddr); + printf("%lx\n", sc->rxq.used_desc_dma.paddr); + iwm_write_prph64(sc, IWM_RFH_Q0_URBDCB_BA_LSB, sc->rxq.used_desc_dma.paddr); + printf("%lx\n", sc->rxq.stat_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); + + 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); + printf("DMA_CFG: %#x\n", iwm_read_prph(sc, IWM_RFH_RXF_DMA_CFG)); + + iwm_write_prph(sc, IWM_RFH_GEN_CFG, + IWM_RFH_GEN_CFG_RFH_DMA_SNOOP | + 0 /* queue 0 */ | + IWM_RFH_GEN_CFG_SERVICE_DMA_SNOOP | + IWM_RFH_GEN_CFG_RB_CHUNK_SIZE_64); + printf("DMACFG: %#x\n", iwm_read_prph(sc, IWM_RFH_RXF_DMA_CFG)); + + iwm_write_prph(sc, IWM_RFH_RXF_RXQ_ACTIVE, 0x00010001); + + iwm_nic_unlock(sc); + + IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF); +#else /* reset and flush pointers */ IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0); IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0); @@ -1425,15 +1476,10 @@ 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); +#endif + + //IWM_WRITE(sc, IWM_RFH_Q0_FRBDCB_WIDX_TRG, 8); return 0; } @@ -1479,6 +1525,7 @@ iwm_nic_init(struct iwm_softc *sc) int error; iwm_apm_init(sc); + if (sc->cfg->device_family == IWM_DEVICE_FAMILY_7000) iwm_set_pwr(sc); @@ -2831,8 +2878,8 @@ iwm_mvm_load_ucode_wait_alive(struct iwm_softc *sc, iwm_nic_unlock(sc); } device_printf(sc->sc_dev, - "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", - a, b); + "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x, error %d\n", + a, b, error); } sc->cur_ucode = old_type; return error; @@ -3026,7 +3073,7 @@ 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); + ring->desc[idx] = htole64(seg.ds_addr | (idx + 1)); bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, BUS_DMASYNC_PREWRITE); @@ -5423,6 +5470,8 @@ iwm_notif_intr(struct iwm_softc *sc) hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff; + printf("%s %d\n", __func__, hw); + /* * Process responses */ @@ -5447,7 +5496,7 @@ iwm_notif_intr(struct iwm_softc *sc) * 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)); + IWM_WRITE(sc, IWM_RFH_Q0_FRBDCB_WIDX_TRG, rounddown2(hw, 8)); } static void @@ -5499,6 +5548,8 @@ iwm_intr(void *arg) goto out_ena; } + printf("%s %x\n", __func__, r1); + IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask); /* Safely ignore these bits for debug checks below */ @@ -5551,6 +5602,10 @@ iwm_intr(void *arg) goto out; } + if (r1 & IWM_CSR_INT_BIT_ALIVE) { + IWM_WRITE(sc, IWM_RFH_Q0_FRBDCB_WIDX_TRG, 8); + } + /* firmware chunk loaded */ if (r1 & IWM_CSR_INT_BIT_FH_TX) { IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, IWM_CSR_FH_INT_TX_MASK); @@ -5600,6 +5655,7 @@ iwm_intr(void *arg) rv = 1; out_ena: + printf("restoring interrupt mask %x\n", sc->sc_intmask); iwm_restore_interrupts(sc); out: IWM_UNLOCK(sc); @@ -5766,7 +5822,7 @@ iwm_attach(device_t dev) sc->sc_dev = dev; sc->sc_attached = 1; - sc->sc_debug = (sc->sc_debug | IWM_DEBUG_RESET | IWM_DEBUG_INTR | IWM_DEBUG_FW | IWM_DEBUG_FATAL | IWM_DEBUG_CMD); + 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); diff --git a/sys/dev/iwm/if_iwm_pcie_trans.c b/sys/dev/iwm/if_iwm_pcie_trans.c index 2fdb4df96aa..9b2c69ee478 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, addr, val & 0xffffffff); + iwm_write_prph(sc, 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 @@ -615,11 +636,14 @@ iwm_pcie_rx_stop(struct iwm_softc *sc) { int 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); + 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); + printf("polling returned %d\n", ret); +#if 0 + ret = iwm_poll_prph_bit(sc, IWM_RFH_GEN_STATUS, + IWM_RXF_DMA_IDLE, IWM_RXF_DMA_IDLE, 1000); +#endif 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 e04dd52f3fe..bdbd85476af 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_iwmreg.h b/sys/dev/iwm/if_iwmreg.h index 67f1bbff0f0..b73ba559998 100644 --- a/sys/dev/iwm/if_iwmreg.h +++ b/sys/dev/iwm/if_iwmreg.h @@ -1469,6 +1469,43 @@ 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 +/* Write index table */ +#define IWM_RFH_Q0_FRBDCB_WIDX 0xa08080 +/* Write index table - shadow registers */ +#define IWM_RFH_Q0_FRBDCB_WIDX_TRG 0x1c80 +/* Read index table */ +#define IWM_RFH_Q0_FRBDCB_RIDX 0xa080c0 +/* Used list table */ +#define IWM_RFH_Q0_URBDCB_BA_LSB 0xa08100 +/* Write index table */ +#define IWM_RFH_Q0_URBDCB_WIDX 0xa08180 +/* stts */ +#define IWM_RFH_Q0_URBD_STTS_WPTR_LSB 0xa08200 + +#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 + /* 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) diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h index 4f303d1ec8d..45751c8aa8f 100644 --- a/sys/dev/iwm/if_iwmvar.h +++ b/sys/dev/iwm/if_iwmvar.h @@ -299,7 +299,7 @@ struct iwm_tx_ring { int cur; }; -#define IWM_RX_RING_COUNT 256 +#define IWM_RX_RING_COUNT 512 /* Linux driver optionally uses 8k buffer */ #define IWM_RBUF_SIZE 4096 @@ -314,7 +314,8 @@ struct iwm_rx_ring { struct iwm_dma_info desc_dma; struct iwm_dma_info stat_dma; struct iwm_dma_info buf_dma; - uint32_t *desc; + struct iwm_dma_info used_desc_dma; + uint64_t *desc; struct iwm_rb_status *stat; struct iwm_rx_data data[IWM_RX_RING_COUNT]; bus_dmamap_t spare_map; /* for iwm_rx_addbuf() */