From bf5c331b7ad2a2bbc5bf3fe34df00a349ace31bf Mon Sep 17 00:00:00 2001 From: stsp Date: Wed, 7 Jul 2021 08:52:54 +0000 Subject: [PATCH] Parse CMD_VERSION TLV found in iwm(4) fw images and add iwm_lookup_cmd_ver(). It seems Intel saw a risk of eventually running out of firmware capability support and API support flags, so yet another such mechanism was added. If you want to know which variant of a command needs to be used there are now at least three places to check for related information. --- sys/dev/pci/if_iwm.c | 36 ++++++++++++++++++++++++++++++++++-- sys/dev/pci/if_iwmreg.h | 19 ++++++++++++++++++- sys/dev/pci/if_iwmvar.h | 5 ++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index c691f19b0e2..f7335e2fa8b 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwm.c,v 1.337 2021/07/07 08:32:00 stsp Exp $ */ +/* $OpenBSD: if_iwm.c,v 1.338 2021/07/07 08:52:54 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh @@ -549,6 +549,21 @@ int iwm_resume(struct iwm_softc *); void iwm_radiotap_attach(struct iwm_softc *); #endif +uint8_t +iwm_lookup_cmd_ver(struct iwm_softc *sc, uint8_t grp, uint8_t cmd) +{ + const struct iwm_fw_cmd_version *entry; + int i; + + for (i = 0; i < sc->n_cmd_versions; i++) { + entry = &sc->cmd_versions[i]; + if (entry->group == grp && entry->cmd == cmd) + return entry->cmd_ver; + } + + return IWM_FW_CMD_VER_UNKNOWN; +} + int iwm_is_mimo_ht_plcp(uint8_t ht_plcp) { @@ -680,6 +695,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type) sc->sc_capaflags = 0; sc->sc_capa_n_scan_channels = IWM_DEFAULT_SCAN_CHANNELS; memset(sc->sc_enabled_capa, 0, sizeof(sc->sc_enabled_capa)); + sc->n_cmd_versions = 0; memset(sc->sc_fw_mcc, 0, sizeof(sc->sc_fw_mcc)); uhdr = (void *)fw->fw_rawdata; @@ -850,7 +866,23 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type) break; } - case 48: /* undocumented TLV */ + case IWM_UCODE_TLV_CMD_VERSIONS: + if (tlv_len % sizeof(struct iwm_fw_cmd_version)) { + tlv_len /= sizeof(struct iwm_fw_cmd_version); + tlv_len *= sizeof(struct iwm_fw_cmd_version); + } + if (sc->n_cmd_versions != 0) { + err = EINVAL; + goto parse_out; + } + if (tlv_len > sizeof(sc->cmd_versions)) { + err = EINVAL; + goto parse_out; + } + memcpy(&sc->cmd_versions[0], tlv_data, tlv_len); + sc->n_cmd_versions = tlv_len / sizeof(struct iwm_fw_cmd_version); + break; + case IWM_UCODE_TLV_SDIO_ADMA_ADDR: case IWM_UCODE_TLV_FW_GSCAN_CAPA: /* ignore, not used by current driver */ diff --git a/sys/dev/pci/if_iwmreg.h b/sys/dev/pci/if_iwmreg.h index dadf372c2c4..b5430df4798 100644 --- a/sys/dev/pci/if_iwmreg.h +++ b/sys/dev/pci/if_iwmreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwmreg.h,v 1.57 2021/07/07 08:32:00 stsp Exp $ */ +/* $OpenBSD: if_iwmreg.h,v 1.58 2021/07/07 08:52:54 stsp Exp $ */ /****************************************************************************** * @@ -1095,6 +1095,7 @@ struct iwm_ucode_header { #define IWM_UCODE_TLV_FW_DBG_DEST 38 #define IWM_UCODE_TLV_FW_DBG_CONF 39 #define IWM_UCODE_TLV_FW_DBG_TRIGGER 40 +#define IWM_UCODE_TLV_CMD_VERSIONS 48 #define IWM_UCODE_TLV_FW_GSCAN_CAPA 50 #define IWM_UCODE_TLV_FW_MEM_SEG 51 #define IWM_UCODE_TLV_UMAC_DEBUG_ADDRS 54 @@ -2547,6 +2548,22 @@ struct iwm_error_resp { uint64_t timestamp; } __packed; +#define IWM_FW_CMD_VER_UNKNOWN 99 + +/** + * struct iwm_fw_cmd_version - firmware command version entry + * @cmd: command ID + * @group: group ID + * @cmd_ver: command version + * @notif_ver: notification version + */ +struct iwm_fw_cmd_version { + uint8_t cmd; + uint8_t group; + uint8_t cmd_ver; + uint8_t notif_ver; +} __packed; + /* Common PHY, MAC and Bindings definitions */ diff --git a/sys/dev/pci/if_iwmvar.h b/sys/dev/pci/if_iwmvar.h index 51d725fa7ce..4a9cd4c35fe 100644 --- a/sys/dev/pci/if_iwmvar.h +++ b/sys/dev/pci/if_iwmvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwmvar.h,v 1.64 2021/06/01 18:03:56 stsp Exp $ */ +/* $OpenBSD: if_iwmvar.h,v 1.65 2021/07/07 08:52:54 stsp Exp $ */ /* * Copyright (c) 2014 genua mbh @@ -545,6 +545,9 @@ struct iwm_softc { int sc_capa_n_scan_channels; uint8_t sc_ucode_api[howmany(IWM_NUM_UCODE_TLV_API, NBBY)]; uint8_t sc_enabled_capa[howmany(IWM_NUM_UCODE_TLV_CAPA, NBBY)]; +#define IWM_MAX_FW_CMD_VERSIONS 64 + struct iwm_fw_cmd_version cmd_versions[IWM_MAX_FW_CMD_VERSIONS]; + int n_cmd_versions; char sc_fw_mcc[3]; int sc_intmask; -- 2.20.1