From f8f0b499ac0a3cc3f92f3ae95518da6bd02160db Mon Sep 17 00:00:00 2001 From: stsp Date: Tue, 10 May 2022 09:11:44 +0000 Subject: [PATCH] Fix reading of the MAC address on AX210 devices. wrong MAC address issue spotted by jsg@ and kevlo@ ok kevlo@ --- sys/dev/pci/if_iwx.c | 55 ++++++++++++++++++++++++++++------------- sys/dev/pci/if_iwxreg.h | 8 +++++- sys/dev/pci/if_iwxvar.h | 3 ++- 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index b3ea3675ae9..e99b1ead069 100644 --- a/sys/dev/pci/if_iwx.c +++ b/sys/dev/pci/if_iwx.c @@ -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 @@ -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; diff --git a/sys/dev/pci/if_iwxreg.h b/sys/dev/pci/if_iwxreg.h index 6ddfb14e5eb..732c6f18f61 100644 --- a/sys/dev/pci/if_iwxreg.h +++ b/sys/dev/pci/if_iwxreg.h @@ -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 diff --git a/sys/dev/pci/if_iwxvar.h b/sys/dev/pci/if_iwxvar.h index bec0758d890..c60140a9586 100644 --- a/sys/dev/pci/if_iwxvar.h +++ b/sys/dev/pci/if_iwxvar.h @@ -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 @@ -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; -- 2.20.1