Fix reading of the MAC address on AX210 devices.
authorstsp <stsp@openbsd.org>
Tue, 10 May 2022 09:11:44 +0000 (09:11 +0000)
committerstsp <stsp@openbsd.org>
Tue, 10 May 2022 09:11:44 +0000 (09:11 +0000)
wrong MAC address issue spotted by jsg@ and kevlo@
ok kevlo@

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

index b3ea367..e99b1ea 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwx.c,v 1.143 2022/05/09 21:57:26 stsp Exp $       */
+/*     $OpenBSD: if_iwx.c,v 1.144 2022/05/10 09:11:44 stsp Exp $       */
 
 /*
  * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@@ -341,8 +341,9 @@ void        iwx_sta_tx_agg_start(struct iwx_softc *, struct ieee80211_node *,
            uint8_t);
 void   iwx_ba_task(void *);
 
-int    iwx_set_mac_addr_from_csr(struct iwx_softc *, struct iwx_nvm_data *);
+void   iwx_set_mac_addr_from_csr(struct iwx_softc *, struct iwx_nvm_data *);
 int    iwx_is_valid_mac_addr(const uint8_t *);
+void   iwx_flip_hw_address(uint32_t, uint32_t, uint8_t *);
 int    iwx_nvm_get(struct iwx_softc *);
 int    iwx_load_firmware(struct iwx_softc *);
 int    iwx_start_fw(struct iwx_softc *);
@@ -3688,31 +3689,33 @@ iwx_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
        return EBUSY;
 }
 
-/* Read the mac address from WFMP registers. */
-int
+void
 iwx_set_mac_addr_from_csr(struct iwx_softc *sc, struct iwx_nvm_data *data)
 {
-       const uint8_t *hw_addr;
        uint32_t mac_addr0, mac_addr1;
 
+       memset(data->hw_addr, 0, sizeof(data->hw_addr));
+
        if (!iwx_nic_lock(sc))
-               return EBUSY;
+               return;
 
-       mac_addr0 = htole32(iwx_read_prph(sc, IWX_WFMP_MAC_ADDR_0));
-       mac_addr1 = htole32(iwx_read_prph(sc, IWX_WFMP_MAC_ADDR_1));
+       mac_addr0 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR0_STRAP(sc)));
+       mac_addr1 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR1_STRAP(sc)));
 
-       hw_addr = (const uint8_t *)&mac_addr0;
-       data->hw_addr[0] = hw_addr[3];
-       data->hw_addr[1] = hw_addr[2];
-       data->hw_addr[2] = hw_addr[1];
-       data->hw_addr[3] = hw_addr[0];
+       iwx_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
 
-       hw_addr = (const uint8_t *)&mac_addr1;
-       data->hw_addr[4] = hw_addr[1];
-       data->hw_addr[5] = hw_addr[0];
+       /* If OEM fused a valid address, use it instead of the one in OTP. */
+       if (iwx_is_valid_mac_addr(data->hw_addr)) {
+               iwx_nic_unlock(sc);
+               return;
+       }
+
+       mac_addr0 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR0_OTP(sc)));
+       mac_addr1 = htole32(IWX_READ(sc, IWX_CSR_MAC_ADDR1_OTP(sc)));
+
+       iwx_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
 
        iwx_nic_unlock(sc);
-       return 0;
 }
 
 int
@@ -3728,6 +3731,22 @@ iwx_is_valid_mac_addr(const uint8_t *addr)
            !ETHER_IS_MULTICAST(addr));
 }
 
+void
+iwx_flip_hw_address(uint32_t mac_addr0, uint32_t mac_addr1, uint8_t *dest)
+{
+       const uint8_t *hw_addr;
+
+       hw_addr = (const uint8_t *)&mac_addr0;
+       dest[0] = hw_addr[3];
+       dest[1] = hw_addr[2];
+       dest[2] = hw_addr[1];
+       dest[3] = hw_addr[0];
+
+       hw_addr = (const uint8_t *)&mac_addr1;
+       dest[4] = hw_addr[1];
+       dest[5] = hw_addr[0];
+}
+
 int
 iwx_nvm_get(struct iwx_softc *sc)
 {
@@ -10654,6 +10673,8 @@ iwx_attach(struct device *parent, struct device *self, void *aux)
                }
        }
 
+       sc->mac_addr_from_csr = 0x380; /* differs on BZ hw generation */
+
        if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) {
                sc->sc_umac_prph_offset = 0x300000;
                sc->max_tfd_queue_size = IWX_TFD_QUEUE_SIZE_MAX_GEN3;
index 6ddfb14..732c6f1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwxreg.h,v 1.38 2022/05/09 21:57:26 stsp Exp $     */
+/*     $OpenBSD: if_iwxreg.h,v 1.39 2022/05/10 09:11:44 stsp Exp $     */
 
 /*-
  * Based on BSD-licensed source modules in the Linux iwlwifi driver,
@@ -1160,6 +1160,12 @@ enum msix_ivar_for_cause {
 #define IWX_MSIX_AUTO_CLEAR_CAUSE              (0 << 7)
 #define IWX_MSIX_NON_AUTO_CLEAR_CAUSE          (1 << 7)
 
+#define IWX_CSR_ADDR_BASE(sc)                  ((sc)->mac_addr_from_csr)
+#define IWX_CSR_MAC_ADDR0_OTP(sc)              (IWX_CSR_ADDR_BASE(sc) + 0x00)
+#define IWX_CSR_MAC_ADDR1_OTP(sc)              (IWX_CSR_ADDR_BASE(sc) + 0x04)
+#define IWX_CSR_MAC_ADDR0_STRAP(sc)            (IWX_CSR_ADDR_BASE(sc) + 0x08)
+#define IWX_CSR_MAC_ADDR1_STRAP(sc)            (IWX_CSR_ADDR_BASE(sc) + 0x0c)
+
 /**
  * uCode API flags
  * @IWX_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
index bec0758..c60140a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwxvar.h,v 1.33 2022/05/09 21:57:26 stsp Exp $     */
+/*     $OpenBSD: if_iwxvar.h,v 1.34 2022/05/10 09:11:44 stsp Exp $     */
 
 /*
  * Copyright (c) 2014 genua mbh <info@genua.de>
@@ -681,6 +681,7 @@ struct iwx_softc {
 #define IWX_DEVICE_FAMILY_22000        1
 #define IWX_DEVICE_FAMILY_AX210        2
        uint32_t sc_sku_id[3];
+       uint32_t mac_addr_from_csr;
 
        struct iwx_dma_info ctxt_info_dma;
        struct iwx_self_init_dram init_dram;