git: b15ec53784f3 - main - iwm: Intel 9000 series bits from OpenBSD

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Mon, 12 Oct 2026 02:51:35 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=b15ec53784f3be913d6b4711f8eb166584a7d791

commit b15ec53784f3be913d6b4711f8eb166584a7d791
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2026-10-12 02:50:40 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2026-10-12 02:50:40 +0000

    iwm: Intel 9000 series bits from OpenBSD
    
    * Add basic SOC conf firmware command
    * Configured with the same xtal latency as used by openbsd
    
    Currently untested; will need to find a device.
    
    Obtained from: OpenBSD a6e25c727a2214219715b51ba6af2221d7e0d674
    
    Differential Revision:  https://reviews.freebsd.org/D60076
---
 sys/dev/iwm/if_iwm.c        | 45 +++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/iwm/if_iwm_9000.c   |  1 +
 sys/dev/iwm/if_iwm_config.h |  3 +++
 3 files changed, 49 insertions(+)

diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
index 642c8fbd44f2..3a2804242319 100644
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -4687,6 +4687,46 @@ iwm_send_bt_init_conf(struct iwm_softc *sc)
 	    &bt_cmd);
 }
 
+static int
+iwm_send_soc_conf(struct iwm_softc *sc)
+{
+	struct iwm_soc_configuration_cmd cmd;
+	int err;
+	uint32_t cmd_id, flags = 0;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	/*
+	 * In VER_1 of this command, the discrete value is considered
+	 * an integer; In VER_2, it's a bitmask.  Since we have only 2
+	 * values in VER_1, this is backwards-compatible with VER_2,
+	 * as long as we don't set any other flag bits.
+	 */
+	if (!sc->cfg->integrated) { /* VER_1 */
+		flags = IWM_SOC_CONFIG_CMD_FLAGS_DISCRETE;
+	} else { /* VER_2 */
+		uint8_t scan_cmd_ver;
+		if (sc->cfg->ltr_delay != IWM_SOC_FLAGS_LTR_APPLY_DELAY_NONE)
+			flags |= (sc->cfg->ltr_delay &
+			    IWM_SOC_FLAGS_LTR_APPLY_DELAY_MASK);
+		scan_cmd_ver = iwm_lookup_cmd_ver(sc, IWM_LONG_GROUP,
+		    IWM_SCAN_REQ_UMAC);
+		if (scan_cmd_ver != IWM_FW_CMD_VER_UNKNOWN &&
+		    scan_cmd_ver >= 2 && sc->cfg->low_latency_xtal)
+			flags |= IWM_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY;
+	}
+	cmd.flags = htole32(flags);
+
+	cmd.latency = htole32(sc->cfg->xtal_latency);
+
+	cmd_id = iwm_cmd_id(IWM_SOC_CONFIGURATION_CMD, IWM_SYSTEM_GROUP, 0);
+	err = iwm_send_cmd_pdu(sc, cmd_id, 0, sizeof(cmd), &cmd);
+	if (err)
+		device_printf(sc->sc_dev, "failed to set soc latency: %d\n",
+		    err);
+	return err;
+}
+
 static boolean_t
 iwm_is_lar_supported(struct iwm_softc *sc)
 {
@@ -4845,6 +4885,11 @@ iwm_init_hw(struct iwm_softc *sc)
 		goto error;
 	}
 
+	if (iwm_fw_has_capa(sc, IWM_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT)) {
+		if ((error = iwm_send_soc_conf(sc)) != 0)
+			goto error;
+	}
+
 	error = iwm_send_tx_ant_cfg(sc, iwm_get_valid_tx_ant(sc));
 	if (error != 0) {
 		device_printf(sc->sc_dev, "antenna config failed\n");
diff --git a/sys/dev/iwm/if_iwm_9000.c b/sys/dev/iwm/if_iwm_9000.c
index be86478c74c1..0f3f11ca0c12 100644
--- a/sys/dev/iwm/if_iwm_9000.c
+++ b/sys/dev/iwm/if_iwm_9000.c
@@ -92,4 +92,5 @@ const struct iwm_cfg iwm9560_cfg = {
 	.host_interrupt_operation_mode = 0,
 	.mqrx_supported = 1,
 	.integrated = 1,
+	.xtal_latency = 650,
 };
diff --git a/sys/dev/iwm/if_iwm_config.h b/sys/dev/iwm/if_iwm_config.h
index 5d869cffe432..b638a2f1661a 100644
--- a/sys/dev/iwm/if_iwm_config.h
+++ b/sys/dev/iwm/if_iwm_config.h
@@ -139,6 +139,9 @@ struct iwm_cfg {
 	uint8_t nvm_hw_section_num;
 	int apmg_wake_up_wa;
 	enum iwm_nvm_type nvm_type;
+	int xtal_latency;
+	int ltr_delay;
+	int low_latency_xtal;
 };
 
 /*