Handle iwx(4) firmware alive response version 5.
authorstsp <stsp@openbsd.org>
Thu, 29 Jul 2021 11:52:11 +0000 (11:52 +0000)
committerstsp <stsp@openbsd.org>
Thu, 29 Jul 2021 11:52:11 +0000 (11:52 +0000)
ok kevlo@

sys/dev/pci/if_iwx.c
sys/dev/pci/if_iwxreg.h

index b90d49d..a9dfc74 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwx.c,v 1.74 2021/07/29 11:51:39 stsp Exp $        */
+/*     $OpenBSD: if_iwx.c,v 1.75 2021/07/29 11:52:11 stsp Exp $        */
 
 /*
  * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -232,6 +232,7 @@ const int iwx_mcs2ridx[] = {
 };
 
 uint8_t        iwx_lookup_cmd_ver(struct iwx_softc *, uint8_t, uint8_t);
+uint8_t        iwx_lookup_notif_ver(struct iwx_softc *, uint8_t, uint8_t);
 int    iwx_is_mimo_ht_plcp(uint8_t);
 int    iwx_is_mimo_mcs(int);
 int    iwx_store_cscheme(struct iwx_softc *, uint8_t *, size_t);
@@ -490,6 +491,21 @@ iwx_lookup_cmd_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd)
        return IWX_FW_CMD_VER_UNKNOWN;
 }
 
+uint8_t
+iwx_lookup_notif_ver(struct iwx_softc *sc, uint8_t grp, uint8_t cmd)
+{
+       const struct iwx_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->notif_ver;
+       }
+
+       return IWX_FW_CMD_VER_UNKNOWN;
+}
+
 int
 iwx_is_mimo_ht_plcp(uint8_t ht_plcp)
 {
@@ -8146,9 +8162,37 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml)
 
                case IWX_ALIVE: {
                        struct iwx_alive_resp_v4 *resp4;
+                       struct iwx_alive_resp_v5 *resp5;
 
                        DPRINTF(("%s: firmware alive\n", __func__));
-                       if (iwx_rx_packet_payload_len(pkt) == sizeof(*resp4)) {
+                       sc->sc_uc.uc_ok = 0;
+
+                       /*
+                        * For v5 and above, we can check the version, for older
+                        * versions we need to check the size.
+                        */
+                        if (iwx_lookup_notif_ver(sc, IWX_LEGACY_GROUP,
+                           IWX_ALIVE) == 5) {
+                               SYNC_RESP_STRUCT(resp5, pkt);
+                               if (iwx_rx_packet_payload_len(pkt) !=
+                                   sizeof(*resp5)) {
+                                       sc->sc_uc.uc_intr = 1;
+                                       wakeup(&sc->sc_uc);
+                                       break;
+                               }
+                               sc->sc_uc.uc_lmac_error_event_table[0] = le32toh(
+                                   resp5->lmac_data[0].dbg_ptrs.error_event_table_ptr);
+                               sc->sc_uc.uc_lmac_error_event_table[1] = le32toh(
+                                   resp5->lmac_data[1].dbg_ptrs.error_event_table_ptr);
+                               sc->sc_uc.uc_log_event_table = le32toh(
+                                   resp5->lmac_data[0].dbg_ptrs.log_event_table_ptr);
+                               sc->sched_base = le32toh(
+                                   resp5->lmac_data[0].dbg_ptrs.scd_base_ptr);
+                               sc->sc_uc.uc_umac_error_event_table = le32toh(
+                                   resp5->umac_data.dbg_ptrs.error_info_addr);
+                               if (resp5->status == IWX_ALIVE_STATUS_OK)
+                                       sc->sc_uc.uc_ok = 1;
+                       } else if (iwx_rx_packet_payload_len(pkt) == sizeof(*resp4)) {
                                SYNC_RESP_STRUCT(resp4, pkt);
                                sc->sc_uc.uc_lmac_error_event_table[0] = le32toh(
                                    resp4->lmac_data[0].dbg_ptrs.error_event_table_ptr);
@@ -8162,8 +8206,6 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf_list *ml)
                                    resp4->umac_data.dbg_ptrs.error_info_addr);
                                if (resp4->status == IWX_ALIVE_STATUS_OK)
                                        sc->sc_uc.uc_ok = 1;
-                               else
-                                       sc->sc_uc.uc_ok = 0;
                        }
 
                        sc->sc_uc.uc_intr = 1;
index e3215b1..3b8073a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwxreg.h,v 1.21 2021/07/29 11:51:39 stsp Exp $     */
+/*     $OpenBSD: if_iwxreg.h,v 1.22 2021/07/29 11:52:11 stsp Exp $     */
 
 /*-
  * Based on BSD-licensed source modules in the Linux iwlwifi driver,
@@ -1972,6 +1972,19 @@ struct iwx_alive_resp_v4 {
        struct iwx_umac_alive umac_data;
 } __packed; /* ALIVE_RES_API_S_VER_4 */
 
+struct iwx_sku_id {
+       uint32_t data[3];
+} __packed; /* SKU_ID_API_S_VER_1 */
+
+struct iwx_alive_resp_v5 {
+       uint16_t status;
+       uint16_t flags;
+       struct iwx_lmac_alive lmac_data[2];
+       struct iwx_umac_alive umac_data;
+       struct iwx_sku_id sku_id;
+} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */
+
+
 #define IWX_SOC_CONFIG_CMD_FLAGS_DISCRETE      (1 << 0)
 #define IWX_SOC_CONFIG_CMD_FLAGS_LOW_LATENCY   (1 << 1)