When enabling Tx queues in iwx_enable_data_tx_queues() the driver computes the Tx queue index as:
int qid = ac + IWX_DQA_AUX_QUEUE + 1; with: #define IWX_DQA_AUX_QUEUE 1 In iwx_tx(), we use a different way of computing the Tx queue index, which is a leftover from iwm(4): ring = &sc->txq[IWX_DQA_MIN_MGMT_QUEUE + ac]; with: #define IWX_DQA_MIN_MGMT_QUEUE 5 This kind of bug would usually have severe consequences. But in this case I got very lucky: 'ac' ranges from 0 to 3, and iwx_tx() always ends up picking Tx queue 5 from the range 5-8 because 'ac' is always passed in as 0 by the caller. iwx_enable_data_tx_queues() enables Tx queues 2-5 inclusive. So from the firmware's point of view, Tx queue 5 is enabled and is used to send frames, and it all just works in spite of the bug. With this fix, iwx_tx() uses Tx queue 2 and would work correctly for values of 'ac' other than 0, as intended. ok? diff 6fed087d6e00a5c30641d2658d09ced7cb1e3090 1e58df09264b5ea64bbe8f02e26da8b4e738c867 blob - 2f41c5a7c8a943e38bbd69a81d46cf432d329607 blob + 831f4d766af8fbf4e00f3fc0ad1624838869d92e --- sys/dev/pci/if_iwx.c +++ sys/dev/pci/if_iwx.c @@ -1674,13 +1674,13 @@ iwx_alloc_tx_ring(struct iwx_softc *sc, struct iwx_tx_ * * In DQA mode we use 1 command queue + 4 DQA mgmt/data queues. * The command is queue 0 (sc->txq[0]), and 4 mgmt/data frame queues - * are sc->tqx[IWX_DQA_MIN_MGMT_QUEUE + ac], i.e. sc->txq[5:8], + * are sc->tqx[ac + IWX_DQA_AUX_QUEUE + 1], i.e. sc->txq[2:5], * in order to provide one queue per EDCA category. * * Tx aggregation will require additional queues (one queue per TID * for which aggregation is enabled) but we do not implement this yet. */ - if (qid > IWX_DQA_MAX_MGMT_QUEUE) + if (qid > IWX_DQA_MIN_MGMT_QUEUE) return 0; err = iwx_dma_contig_alloc(sc->sc_dmat, &ring->bc_tbl, @@ -4246,7 +4246,7 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ie * Tx aggregation will require additional queues (one queue per TID * for which aggregation is enabled) but we do not implement this yet. */ - ring = &sc->txq[IWX_DQA_MIN_MGMT_QUEUE + ac]; + ring = &sc->txq[ac + IWX_DQA_AUX_QUEUE + 1]; desc = &ring->desc[ring->cur]; memset(desc, 0, sizeof(*desc)); data = &ring->data[ring->cur];