Parse CMD_VERSION TLV found in iwm(4) fw images and add iwm_lookup_cmd_ver().
authorstsp <stsp@openbsd.org>
Wed, 7 Jul 2021 08:52:54 +0000 (08:52 +0000)
committerstsp <stsp@openbsd.org>
Wed, 7 Jul 2021 08:52:54 +0000 (08:52 +0000)
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
sys/dev/pci/if_iwmreg.h
sys/dev/pci/if_iwmvar.h

index c691f19..f7335e2 100644 (file)
@@ -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 <info@genua.de>
@@ -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 */
index dadf372..b5430df 100644 (file)
@@ -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 */
 
index 51d725f..4a9cd4c 100644 (file)
@@ -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 <info@genua.de>
@@ -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;