Page MenuHomeFreeBSD

D60080.id189944.diff
No OneTemporary

D60080.id189944.diff

diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -1147,10 +1147,25 @@
ring->desc = ring->desc_dma.vaddr;
/*
- * We only use rings 0 through 9 (4 EDCA + cmd) so there is no need
- * to allocate commands space for other rings.
+ * There is no need to allocate DMA buffers for unused rings.
+ * 7k/8k/9k hardware supports up to 31 Tx rings which is more
+ * than we currently need.
+ *
+ * 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[IWM_DQA_MIN_MGMT_QUEUE + ac], i.e. sc->txq[5:8],
+ * in order to provide one queue per EDCA category.
+ * Tx aggregation requires additional queues, one queue per TID for
+ * which aggregation is enabled. We map TID 0-7 to sc->txq[10:17].
+ *
+ * In non-DQA mode, we use rings 0 through 9 (0-3 are EDCA, 9 is cmd),
+ * and Tx aggregation is not supported.
+ *
+ * Unfortunately, we cannot tell if DQA will be used until the
+ * firmware gets loaded later, so just allocate sufficient rings
+ * in order to satisfy both cases.
*/
- if (qid > IWM_CMD_QUEUE)
+ if (qid > IWM_LAST_AGG_TX_QUEUE)
return 0;
size = IWM_TX_RING_COUNT * sizeof(struct iwm_device_cmd);
@@ -1162,8 +1177,13 @@
}
ring->cmd = ring->cmd_dma.vaddr;
- /* FW commands may require more mapped space than packets. */
- if (qid == IWM_CMD_QUEUE) {
+ /*
+ * FW commands may require more mapped space than packets. The
+ * DQA command queue is ring 0 and we can't tell at allocation
+ * time which command queue id will be used, so give both the
+ * command-sized DMA tag.
+ */
+ if (qid == IWM_CMD_QUEUE || qid == IWM_DQA_CMD_QUEUE) {
maxsize = IWM_RBUF_SIZE;
nsegments = 1;
} else {
@@ -1227,7 +1247,7 @@
ring->queued = 0;
ring->cur = 0;
- if (ring->qid == IWM_CMD_QUEUE && sc->cmd_hold_nic_awake)
+ if (ring->qid == sc->cmdqid && sc->cmd_hold_nic_awake)
iwm_pcie_clear_cmd_in_flight(sc);
}
@@ -1692,9 +1712,11 @@
IWM_WRITE(sc, IWM_HBUS_TARG_WRPTR, qid << 8 | 0);
- if (qid == IWM_CMD_QUEUE) {
+ if (qid == sc->cmdqid) {
+#if 0
/* Disable the scheduler. */
iwm_write_prph(sc, IWM_SCD_EN_CTRL, 0);
+#endif
/* Stop the TX queue prior to configuration. */
iwm_write_prph(sc, IWM_SCD_QUEUE_STATUS_BITS(qid),
@@ -1737,7 +1759,8 @@
IWM_SCD_QUEUE_STTS_REG_MSK);
/* Enable the scheduler for this queue. */
- iwm_write_prph(sc, IWM_SCD_EN_CTRL, qmsk);
+ iwm_write_prph(sc, IWM_SCD_EN_CTRL,
+ iwm_read_prph(sc, IWM_SCD_EN_CTRL) | qmsk);
} else {
struct iwm_scd_txq_cfg_cmd cmd;
int error;
@@ -1813,7 +1836,8 @@
iwm_nic_unlock(sc);
/* enable command channel */
- error = iwm_enable_txq(sc, 0 /* unused */, IWM_CMD_QUEUE, 7);
+ error = iwm_enable_txq(sc, 0 /* unused */, sc->cmdqid,
+ IWM_TX_FIFO_CMD);
if (error)
return error;
@@ -2929,6 +2953,11 @@
sc->cur_ucode = ucode_type;
sc->ucode_loaded = FALSE;
+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
+ sc->cmdqid = IWM_DQA_CMD_QUEUE;
+ else
+ sc->cmdqid = IWM_CMD_QUEUE;
+
memset(&alive_data, 0, sizeof(alive_data));
iwm_init_notification_wait(sc->sc_notif_wait, &alive_wait,
alive_cmd, nitems(alive_cmd),
@@ -3672,10 +3701,10 @@
static void
iwm_cmd_done(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
{
- struct iwm_tx_ring *ring = &sc->txq[IWM_CMD_QUEUE];
+ struct iwm_tx_ring *ring = &sc->txq[sc->cmdqid];
struct iwm_tx_data *data;
- if (pkt->hdr.qid != IWM_CMD_QUEUE) {
+ if (pkt->hdr.qid != sc->cmdqid) {
return; /* Not a command ack. */
}
@@ -3851,13 +3880,22 @@
int nsegs;
uint8_t tid, type;
int i, totlen, error, pad;
+ int qid;
wh = mtod(m, struct ieee80211_frame *);
hdrlen = ieee80211_anyhdrsize(wh);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
tid = 0;
- ring = &sc->txq[ac];
+
+ /* Map EDCA categories to Tx data queues. */
+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
+ qid = IWM_DQA_MIN_MGMT_QUEUE + ac;
+ else
+ qid = ac;
+
+ ring = &sc->txq[qid];
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 */
@@ -4767,6 +4805,17 @@
return err;
}
+static int
+iwm_send_dqa_cmd(struct iwm_softc *sc)
+{
+ struct iwm_dqa_enable_cmd dqa_cmd;
+ uint32_t cmd_id;
+
+ dqa_cmd.cmd_queue = htole32(IWM_DQA_CMD_QUEUE);
+ cmd_id = iwm_cmd_id(IWM_DQA_ENABLE_CMD, IWM_DATA_PATH_GROUP, 0);
+ return iwm_send_cmd_pdu(sc, cmd_id, 0, sizeof(dqa_cmd), &dqa_cmd);
+}
+
static int
iwm_send_temp_report_ths_cmd(struct iwm_softc *sc)
{
@@ -4907,7 +4956,7 @@
iwm_init_hw(struct iwm_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- int error, i, ac;
+ int error, i, ac, qid;
sc->sf_state = IWM_SF_UNINIT;
@@ -4973,6 +5022,11 @@
goto error;
}
+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DQA_SUPPORT)) {
+ if ((error = iwm_send_dqa_cmd(sc)) != 0)
+ goto error;
+ }
+
/* Add auxiliary station for scanning */
if ((error = iwm_add_aux_sta(sc)) != 0) {
device_printf(sc->sc_dev, "add_aux_sta failed\n");
@@ -5011,7 +5065,12 @@
/* Enable Tx queues. */
for (ac = 0; ac < WME_NUM_AC; ac++) {
- error = iwm_enable_txq(sc, IWM_STATION_ID, ac,
+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
+ qid = ac + IWM_DQA_MIN_MGMT_QUEUE;
+ else
+ qid = ac;
+
+ error = iwm_enable_txq(sc, IWM_STATION_ID, qid,
iwm_ac_to_tx_fifo[ac]);
if (error)
goto error;
diff --git a/sys/dev/iwm/if_iwm_sta.c b/sys/dev/iwm/if_iwm_sta.c
--- a/sys/dev/iwm/if_iwm_sta.c
+++ b/sys/dev/iwm/if_iwm_sta.c
@@ -162,8 +162,10 @@
if (!update) {
int ac;
for (ac = 0; ac < WME_NUM_AC; ac++) {
- add_sta_cmd.tfd_queue_msk |=
- htole32(1 << iwm_ac_to_tx_fifo[ac]);
+ int qid = ac;
+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
+ qid += IWM_DQA_MIN_MGMT_QUEUE;
+ add_sta_cmd.tfd_queue_msk |= htole32(1 << qid);
}
IEEE80211_ADDR_COPY(&add_sta_cmd.addr, in->in_ni.ni_bssid);
}
@@ -277,7 +279,10 @@
if (ret)
return ret;
for (ac = 0; ac < WME_NUM_AC; ac++) {
- tfd_queue_msk |= htole32(1 << iwm_ac_to_tx_fifo[ac]);
+ int qid = ac;
+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
+ qid += IWM_DQA_MIN_MGMT_QUEUE;
+ tfd_queue_msk |= htole32(1 << qid);
}
ret = iwm_flush_tx_path(sc, tfd_queue_msk, IWM_CMD_SYNC);
if (ret)
@@ -352,13 +357,24 @@
iwm_add_aux_sta(struct iwm_softc *sc)
{
int ret;
+ int qid;
+
+ /*
+ * Note: OpenBSD calls different TXQ setups here;
+ * + DQA calls iwm_enable_txq(), which only sends the cmd_pdu
+ * + non-DQA calls iwm_enable_ac_txq(), which does similar stuff to
+ * command setup but not the command scheduler
+ */
+ if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_DQA_SUPPORT))
+ qid = IWM_DQA_AUX_QUEUE;
+ else
+ qid = IWM_AUX_QUEUE;
sc->sc_aux_sta.sta_id = IWM_AUX_STA_ID;
- sc->sc_aux_sta.tfd_queue_msk = (1 << IWM_AUX_QUEUE);
+ sc->sc_aux_sta.tfd_queue_msk = (1 << qid);
/* Map Aux queue to fifo - needs to happen before adding Aux station */
- ret = iwm_enable_txq(sc, IWM_AUX_STA_ID, IWM_AUX_QUEUE,
- IWM_TX_FIFO_MCAST);
+ ret = iwm_enable_txq(sc, IWM_AUX_STA_ID, qid, IWM_TX_FIFO_MCAST);
if (ret)
return ret;
diff --git a/sys/dev/iwm/if_iwm_util.c b/sys/dev/iwm/if_iwm_util.c
--- a/sys/dev/iwm/if_iwm_util.c
+++ b/sys/dev/iwm/if_iwm_util.c
@@ -167,7 +167,7 @@
int
iwm_send_cmd(struct iwm_softc *sc, struct iwm_host_cmd *hcmd)
{
- struct iwm_tx_ring *ring = &sc->txq[IWM_CMD_QUEUE];
+ struct iwm_tx_ring *ring = &sc->txq[sc->cmdqid];
struct iwm_tfd *desc;
struct iwm_tx_data *txdata = NULL;
struct iwm_device_cmd *cmd;
diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h
--- a/sys/dev/iwm/if_iwmvar.h
+++ b/sys/dev/iwm/if_iwmvar.h
@@ -454,6 +454,7 @@
struct iwm_tx_ring txq[IWM_MAX_QUEUES];
struct iwm_rx_ring rxq;
int qfullmsk;
+ int cmdqid;
/* ICT table. */
struct iwm_dma_info ict_dma;

File Metadata

Mime Type
text/plain
Expires
Sun, Oct 18, 10:09 AM (9 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40819264
Default Alt Text
D60080.id189944.diff (7 KB)

Event Timeline