From 9787ce4d3465a568f591006de882dc3707357ba7 Mon Sep 17 00:00:00 2001 From: stsp Date: Sat, 16 Apr 2022 16:21:50 +0000 Subject: [PATCH] Make device matching in iwx(4) more similar to Linux iwlwifi. There are a few chips which cannot be recognized by PCI ID alone. Reading device registers is also required to identify such devices. iwx(4) should now detect AX201 devices requiring the following firmware images: iwx-Qu-b0-hr-b0-63 iwx-Qu-b0-jf-b0-63 iwx-Qu-c0-jf-b0-63 iwx-QuZ-a0-hr-b0-67 iwx-QuZ-a0-jf-b0-63 These are already installed in /etc/firmware but have so far been unused. This is obviously going to cover a range of devices which have not actually been tested yet. If you have such a device please test and report back. Tested on previously working AX200/AX201 devices by jmc@ and myself. Sven Wolf has successfully tested a newly supported device. Based on an initial patch by Iraklis Karagkiozoglou, thanks! --- sys/dev/pci/if_iwx.c | 349 ++++++++++++++++++++++++++++++++++------ sys/dev/pci/if_iwxreg.h | 25 ++- sys/dev/pci/if_iwxvar.h | 103 +++++++++++- 3 files changed, 423 insertions(+), 54 deletions(-) diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index 11f582e6732..ba8e3352346 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.141 2022/04/06 18:59:29 naddy Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.142 2022/04/16 16:21:50 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh @@ -491,6 +491,7 @@ int iwx_intr_msix(void *); int iwx_match(struct device *, void *, void *); int iwx_preinit(struct iwx_softc *); void iwx_attach_hook(struct device *); +const struct iwx_device_cfg *iwx_find_device_cfg(struct iwx_softc *); void iwx_attach(struct device *, struct device *, void *); void iwx_init_task(void *); int iwx_activate(struct device *, int); @@ -870,7 +871,7 @@ iwx_ctxt_info_init(struct iwx_softc *sc, const struct iwx_fw_sects *fws) /* size is in DWs */ ctxt_info->version.size = htole16(sizeof(*ctxt_info) / 4); - if (sc->sc_device_family >= IWX_DEVICE_FAMILY_22560) + if (sc->sc_device_family >= IWX_DEVICE_FAMILY_AX210) rb_size = IWX_CTXT_INFO_RB_SIZE_2K; else rb_size = IWX_CTXT_INFO_RB_SIZE_4K; @@ -9392,60 +9393,191 @@ static const struct pci_matchid iwx_devices[] = { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_3 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_4,}, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_5,}, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_6,}, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_7,}, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_22500_8,}, }; -static const struct pci_matchid iwx_subsystem_id_ax201[] = { - { PCI_VENDOR_INTEL, 0x0070 }, - { PCI_VENDOR_INTEL, 0x0074 }, - { PCI_VENDOR_INTEL, 0x0078 }, - { PCI_VENDOR_INTEL, 0x007c }, - { PCI_VENDOR_INTEL, 0x0310 }, - { PCI_VENDOR_INTEL, 0x2074 }, - { PCI_VENDOR_INTEL, 0x4070 }, - /* TODO: There are more ax201 devices with "main" product ID 0x06f0 */ -}; int iwx_match(struct device *parent, iwx_match_t match __unused, void *aux) { struct pci_attach_args *pa = aux; - pcireg_t subid; - pci_vendor_id_t svid; - pci_product_id_t spid; - int i; - - if (!pci_matchbyid(pa, iwx_devices, nitems(iwx_devices))) - return 0; + return pci_matchbyid(pa, iwx_devices, nitems(iwx_devices)); +} - /* - * Some PCI product IDs are shared among devices which use distinct - * chips or firmware. We need to match the subsystem ID as well to - * ensure that we have in fact found a supported device. - */ - subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); - svid = PCI_VENDOR(subid); - spid = PCI_PRODUCT(subid); +/* + * The device info table below contains device-specific config overrides. + * The most important parameter derived from this table is the name of the + * firmware image to load. + * + * The Linux iwlwifi driver uses an "old" and a "new" device info table. + * The "old" table matches devices based on PCI vendor/product IDs only. + * The "new" table extends this with various device parameters derived + * from MAC type, RF type, and PCI subdevice ID. + * + * In iwlwifi "old" and "new" tables share the same array, where "old" + * entries contain dummy values for data defined only for "new" entries. + * As of 2022, Linux developers are still in the process of moving entries + * from "old" to "new" style and it looks like this effort has stalled in + * in some work-in-progress state for quite a while. Linux commits moving + * entries from "old" to "new" have at times been reverted due to regressions. + * Part of this complexity comes from iwlwifi supporting both iwm(4) and iwx(4) + * devices in the same driver. + * + * We try to avoid this mess while still recognizing supported iwx(4) devices + * correctly. Our table below contains only "new" entries declared in iwlwifi + * with the _IWL_DEV_INFO() macro (with a leading underscore). + * Other devices are matched based on PCI vendor/product ID as usual. + */ - switch (PCI_PRODUCT(pa->pa_id)) { - case PCI_PRODUCT_INTEL_WL_22500_1: /* AX200 */ - return 1; /* match any device */ - case PCI_PRODUCT_INTEL_WL_22500_2: /* AX201 */ - case PCI_PRODUCT_INTEL_WL_22500_3: /* AX201 */ - case PCI_PRODUCT_INTEL_WL_22500_4: /* AX201 */ - case PCI_PRODUCT_INTEL_WL_22500_5: /* AX201 */ - for (i = 0; i < nitems(iwx_subsystem_id_ax201); i++) { - if (svid == iwx_subsystem_id_ax201[i].pm_vid && - spid == iwx_subsystem_id_ax201[i].pm_pid) - return 1; +struct iwx_dev_info { + uint16_t device; + uint16_t subdevice; + uint16_t mac_type; + uint16_t rf_type; + uint8_t mac_step; + uint8_t rf_id; + uint8_t no_160; + uint8_t cores; + uint8_t cdb; + uint8_t jacket; + const struct iwx_device_cfg *cfg; +}; - } - break; - default: - break; - } +#define _IWX_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \ + _rf_id, _no_160, _cores, _cdb, _jacket, _cfg) \ + { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \ + .mac_type = _mac_type, .rf_type = _rf_type, \ + .no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, \ + .mac_step = _mac_step, .cdb = _cdb, .jacket = _jacket } - return 0; -} +/* + * When adding entries to this table keep in mind that entries must + * be listed in the same order as in the Linux driver. Code walks this + * table backwards and uses the first matching entry it finds. + * Device firmware must be available in fw_update(8). + */ +static const struct iwx_dev_info iwx_dev_info_table[] = { + /* Qu with Jf, C step */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1, + IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9461_160 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1, + IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* iwl9461 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV, + IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9462_160 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV, + IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9462 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF, + IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9560_160 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF, + IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_qu_c0_jf_b0_cfg), /* 9560 */ + _IWX_DEV_INFO(IWX_CFG_ANY, 0x1551, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF, + IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, + iwx_9560_qu_c0_jf_b0_cfg), /* 9560_killer_1550s */ + _IWX_DEV_INFO(IWX_CFG_ANY, 0x1552, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF, + IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, + iwx_9560_qu_c0_jf_b0_cfg), /* 9560_killer_1550i */ + + /* QuZ with Jf */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY, + IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF, + IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_quz_a0_jf_b0_cfg), /* 9461_160 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY, + IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF, + IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_quz_a0_jf_b0_cfg), /* 9461 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY, + IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV, + IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_quz_a0_jf_b0_cfg), /* 9462_160 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY, + IWX_CFG_RF_TYPE_JF1, IWX_CFG_RF_ID_JF1_DIV, + IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, iwx_9560_quz_a0_jf_b0_cfg), /* 9462 */ + _IWX_DEV_INFO(IWX_CFG_ANY, 0x1551, + IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY, + IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF, + IWX_CFG_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, + iwx_9560_quz_a0_jf_b0_cfg), /* killer_1550s */ + _IWX_DEV_INFO(IWX_CFG_ANY, 0x1552, + IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY, + IWX_CFG_RF_TYPE_JF2, IWX_CFG_RF_ID_JF, + IWX_CFG_NO_160, IWX_CFG_CORES_BT, IWX_CFG_NO_CDB, + IWX_CFG_ANY, + iwx_9560_quz_a0_jf_b0_cfg), /* 9560_killer_1550i */ + + /* Qu with Hr, B step */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP, + IWX_CFG_RF_TYPE_HR1, IWX_CFG_ANY, + IWX_CFG_ANY, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY, + iwx_qu_b0_hr1_b0), /* AX101 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_B_STEP, + IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY, + IWX_CFG_NO_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY, + iwx_qu_b0_hr_b0), /* AX203 */ + + /* Qu with Hr, C step */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_HR1, IWX_CFG_ANY, + IWX_CFG_ANY, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY, + iwx_qu_c0_hr1_b0), /* AX101 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY, + IWX_CFG_NO_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY, + iwx_qu_c0_hr_b0), /* AX203 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QU, IWX_SILICON_C_STEP, + IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY, + IWX_CFG_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY, + iwx_qu_c0_hr_b0), /* AX201 */ + + /* QuZ with Hr */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QUZ, IWX_CFG_ANY, + IWX_CFG_RF_TYPE_HR1, IWX_CFG_ANY, + IWX_CFG_ANY, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY, + iwx_quz_a0_hr1_b0), /* AX101 */ + _IWX_DEV_INFO(IWX_CFG_ANY, IWX_CFG_ANY, + IWX_CFG_MAC_TYPE_QUZ, IWX_SILICON_B_STEP, + IWX_CFG_RF_TYPE_HR2, IWX_CFG_ANY, + IWX_CFG_NO_160, IWX_CFG_ANY, IWX_CFG_NO_CDB, IWX_CFG_ANY, + iwx_cfg_quz_a0_hr_b0), /* AX203 */ +}; int iwx_preinit(struct iwx_softc *sc) @@ -9518,6 +9650,77 @@ iwx_attach_hook(struct device *self) iwx_preinit(sc); } +const struct iwx_device_cfg * +iwx_find_device_cfg(struct iwx_softc *sc) +{ + pcireg_t sreg; + pci_product_id_t sdev_id; + uint16_t mac_type, rf_type; + uint8_t mac_step, cdb, jacket, rf_id, no_160, cores; + int i; + + sreg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_SUBSYS_ID_REG); + sdev_id = PCI_PRODUCT(sreg); + mac_type = IWX_CSR_HW_REV_TYPE(sc->sc_hw_rev); + mac_step = IWX_CSR_HW_REV_STEP(sc->sc_hw_rev << 2); + rf_type = IWX_CSR_HW_RFID_TYPE(sc->sc_hw_rf_id); + cdb = IWX_CSR_HW_RFID_IS_CDB(sc->sc_hw_rf_id); + jacket = IWX_CSR_HW_RFID_IS_JACKET(sc->sc_hw_rf_id); + + rf_id = IWX_SUBDEVICE_RF_ID(sdev_id); + no_160 = IWX_SUBDEVICE_NO_160(sdev_id); + cores = IWX_SUBDEVICE_CORES(sdev_id); + + for (i = nitems(iwx_dev_info_table) - 1; i >= 0; i--) { + const struct iwx_dev_info *dev_info = &iwx_dev_info_table[i]; + + if (dev_info->device != (uint16_t)IWX_CFG_ANY && + dev_info->device != sc->sc_pid) + continue; + + if (dev_info->subdevice != (uint16_t)IWX_CFG_ANY && + dev_info->subdevice != sdev_id) + continue; + + if (dev_info->mac_type != (uint16_t)IWX_CFG_ANY && + dev_info->mac_type != mac_type) + continue; + + if (dev_info->mac_step != (uint8_t)IWX_CFG_ANY && + dev_info->mac_step != mac_step) + continue; + + if (dev_info->rf_type != (uint16_t)IWX_CFG_ANY && + dev_info->rf_type != rf_type) + continue; + + if (dev_info->cdb != (uint8_t)IWX_CFG_ANY && + dev_info->cdb != cdb) + continue; + + if (dev_info->jacket != (uint8_t)IWX_CFG_ANY && + dev_info->jacket != jacket) + continue; + + if (dev_info->rf_id != (uint8_t)IWX_CFG_ANY && + dev_info->rf_id != rf_id) + continue; + + if (dev_info->no_160 != (uint8_t)IWX_CFG_ANY && + dev_info->no_160 != no_160) + continue; + + if (dev_info->cores != (uint8_t)IWX_CFG_ANY && + dev_info->cores != cores) + continue; + + return dev_info->cfg; + } + + return NULL; +} + + void iwx_attach(struct device *parent, struct device *self, void *aux) { @@ -9528,9 +9731,11 @@ iwx_attach(struct device *parent, struct device *self, void *aux) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; const char *intrstr; + const struct iwx_device_cfg *cfg; int err; int txq_i, i, j; + sc->sc_pid = pa->pa_id; sc->sc_pct = pa->pa_pc; sc->sc_pcitag = pa->pa_tag; sc->sc_dmat = pa->pa_dmat; @@ -9600,6 +9805,7 @@ iwx_attach(struct device *parent, struct device *self, void *aux) IWX_WRITE(sc, IWX_CSR_FH_INT_STATUS, ~0); sc->sc_hw_rev = IWX_READ(sc, IWX_CSR_HW_REV); + sc->sc_hw_rf_id = IWX_READ(sc, IWX_CSR_HW_RF_ID); /* * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have @@ -9612,7 +9818,7 @@ iwx_attach(struct device *parent, struct device *self, void *aux) switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_INTEL_WL_22500_1: - sc->sc_fwname = "iwx-cc-a0-67"; + sc->sc_fwname = IWX_CC_A_FW; sc->sc_device_family = IWX_DEVICE_FAMILY_22000; sc->sc_integrated = 0; sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_NONE; @@ -9622,14 +9828,28 @@ iwx_attach(struct device *parent, struct device *self, void *aux) sc->sc_uhb_supported = 0; break; case PCI_PRODUCT_INTEL_WL_22500_2: - case PCI_PRODUCT_INTEL_WL_22500_3: case PCI_PRODUCT_INTEL_WL_22500_5: + /* These devices should be QuZ only. */ if (sc->sc_hw_rev != IWX_CSR_HW_REV_TYPE_QUZ) { printf("%s: unsupported AX201 adapter\n", DEVNAME(sc)); return; } - - sc->sc_fwname = "iwx-QuZ-a0-hr-b0-67"; + sc->sc_fwname = IWX_QUZ_A_HR_B_FW; + sc->sc_device_family = IWX_DEVICE_FAMILY_22000; + sc->sc_integrated = 1; + sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_200; + sc->sc_low_latency_xtal = 0; + sc->sc_xtal_latency = 500; + sc->sc_tx_with_siso_diversity = 0; + sc->sc_uhb_supported = 0; + break; + case PCI_PRODUCT_INTEL_WL_22500_3: + if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QU_C0) + sc->sc_fwname = IWX_QU_C_HR_B_FW; + else if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QUZ) + sc->sc_fwname = IWX_QUZ_A_HR_B_FW; + else + sc->sc_fwname = IWX_QU_B_HR_B_FW; sc->sc_device_family = IWX_DEVICE_FAMILY_22000; sc->sc_integrated = 1; sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_200; @@ -9639,7 +9859,14 @@ iwx_attach(struct device *parent, struct device *self, void *aux) sc->sc_uhb_supported = 0; break; case PCI_PRODUCT_INTEL_WL_22500_4: - sc->sc_fwname = "iwx-Qu-c0-hr-b0-63"; + case PCI_PRODUCT_INTEL_WL_22500_7: + case PCI_PRODUCT_INTEL_WL_22500_8: + if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QU_C0) + sc->sc_fwname = IWX_QU_C_HR_B_FW; + else if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QUZ) + sc->sc_fwname = IWX_QUZ_A_HR_B_FW; + else + sc->sc_fwname = IWX_QU_B_HR_B_FW; sc->sc_device_family = IWX_DEVICE_FAMILY_22000; sc->sc_integrated = 1; sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_1820; @@ -9648,11 +9875,33 @@ iwx_attach(struct device *parent, struct device *self, void *aux) sc->sc_tx_with_siso_diversity = 0; sc->sc_uhb_supported = 0; break; + case PCI_PRODUCT_INTEL_WL_22500_6: + if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QU_C0) + sc->sc_fwname = IWX_QU_C_HR_B_FW; + else if (sc->sc_hw_rev == IWX_CSR_HW_REV_TYPE_QUZ) + sc->sc_fwname = IWX_QUZ_A_HR_B_FW; + else + sc->sc_fwname = IWX_QU_B_HR_B_FW; + sc->sc_device_family = IWX_DEVICE_FAMILY_22000; + sc->sc_integrated = 1; + sc->sc_ltr_delay = IWX_SOC_FLAGS_LTR_APPLY_DELAY_2500; + sc->sc_low_latency_xtal = 1; + sc->sc_xtal_latency = 12000; + sc->sc_tx_with_siso_diversity = 0; + sc->sc_uhb_supported = 0; + break; default: printf("%s: unknown adapter type\n", DEVNAME(sc)); return; } + cfg = iwx_find_device_cfg(sc); + if (cfg) { + sc->sc_fwname = cfg->fw_name; + sc->sc_tx_with_siso_diversity = cfg->tx_with_siso_diversity; + sc->sc_uhb_supported = cfg->uhb_supported; + } + /* Allocate DMA memory for loading firmware. */ err = iwx_dma_contig_alloc(sc->sc_dmat, &sc->ctxt_info_dma, sizeof(struct iwx_context_info), 0); diff --git a/sys/dev/pci/if_iwxreg.h b/sys/dev/pci/if_iwxreg.h index 1c62d03463c..5581e8f942a 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.36 2022/03/14 15:08:50 stsp Exp $ */ +/* $OpenBSD: if_iwxreg.h,v 1.37 2022/04/16 16:21:50 stsp Exp $ */ /*- * Based on BSD-licensed source modules in the Linux iwlwifi driver, @@ -271,6 +271,18 @@ struct iwx_context_info { */ #define IWX_CSR_HW_REV (0x028) +/* + * RF ID revision info + * Bit fields: + * 31:24: Reserved (set to 0x0) + * 23:12: Type + * 11:8: Step (A - 0x0, B - 0x1, etc) + * 7:4: Dash + * 3:0: Flavor + */ +#define IWX_CSR_HW_RF_ID (0x09c) + + #define IWX_CSR_GIO_REG (0x03C) /* @@ -423,10 +435,21 @@ struct iwx_context_info { /* HW REV */ #define IWX_CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0) #define IWX_CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2) +#define IWX_CSR_HW_REV_TYPE(_val) (((_val) & 0x000FFF0) >> 4) #define IWX_CSR_HW_REV_TYPE_MSK (0x000FFF0) +#define IWX_CSR_HW_REV_TYPE_QU_B0 (0x0000334) +#define IWX_CSR_HW_REV_TYPE_QU_C0 (0x0000338) #define IWX_CSR_HW_REV_TYPE_QUZ (0x0000354) +/* HW RFID */ +#define IWX_CSR_HW_RFID_FLAVOR(_val) (((_val) & 0x000000F) >> 0) +#define IWX_CSR_HW_RFID_DASH(_val) (((_val) & 0x00000F0) >> 4) +#define IWX_CSR_HW_RFID_STEP(_val) (((_val) & 0x0000F00) >> 8) +#define IWX_CSR_HW_RFID_TYPE(_val) (((_val) & 0x0FFF000) >> 12) +#define IWX_CSR_HW_RFID_IS_CDB(_val) (((_val) & 0x10000000) >> 28) +#define IWX_CSR_HW_RFID_IS_JACKET(_val) (((_val) & 0x20000000) >> 29) + /* CSR GIO */ #define IWX_CSR_GIO_REG_VAL_L0S_DISABLED (0x00000002) diff --git a/sys/dev/pci/if_iwxvar.h b/sys/dev/pci/if_iwxvar.h index e78c9fe6fb4..aaf09c2c606 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.31 2022/03/19 14:50:01 stsp Exp $ */ +/* $OpenBSD: if_iwxvar.h,v 1.32 2022/04/16 16:21:50 stsp Exp $ */ /* * Copyright (c) 2014 genua mbh @@ -451,6 +451,101 @@ struct iwx_ba_task_data { uint32_t stop_tidmask; }; + +/* + * Device configuration parameters which cannot be detected based on + * PCI vendor/product ID alone. + */ +struct iwx_device_cfg { + const char *fw_name; + int tx_with_siso_diversity; + int uhb_supported; +}; + +/* Firmware listed here must be available in fw_update(8). */ +#define IWX_CC_A_FW "iwx-cc-a0-67" +#define IWX_QU_B_HR_B_FW "iwx-Qu-b0-hr-b0-63" +#define IWX_QU_B_JF_B_FW "iwx-Qu-b0-jf-b0-63" +#define IWX_QU_C_HR_B_FW "iwx-Qu-c0-hr-b0-63" +#define IWX_QU_C_JF_B_FW "iwx-Qu-c0-jf-b0-63" +#define IWX_QUZ_A_HR_B_FW "iwx-QuZ-a0-hr-b0-67" +#define IWX_QUZ_A_JF_B_FW "iwx-QuZ-a0-jf-b0-63" + +const struct iwx_device_cfg iwx_9560_quz_a0_jf_b0_cfg = { + .fw_name = IWX_QUZ_A_JF_B_FW, +}; + +const struct iwx_device_cfg iwx_9560_qu_c0_jf_b0_cfg = { + .fw_name = IWX_QU_C_JF_B_FW, +}; + +const struct iwx_device_cfg iwx_qu_b0_hr1_b0 = { + .fw_name = IWX_QU_B_HR_B_FW, + .tx_with_siso_diversity = true, +}; + +const struct iwx_device_cfg iwx_qu_b0_hr_b0 = { + .fw_name = IWX_QU_B_HR_B_FW, +}; + +const struct iwx_device_cfg iwx_ax201_cfg_qu_hr = { + .fw_name = IWX_QU_B_HR_B_FW, +}; + +const struct iwx_device_cfg iwx_qu_c0_hr1_b0 = { + .fw_name = IWX_QU_C_HR_B_FW, + .tx_with_siso_diversity = true, +}; + +const struct iwx_device_cfg iwx_qu_c0_hr_b0 = { + .fw_name = IWX_QU_C_HR_B_FW, +}; + +const struct iwx_device_cfg iwx_ax201_cfg_qu_c0_hr_b0 = { + .fw_name = IWX_QU_C_HR_B_FW, +}; + +const struct iwx_device_cfg iwx_quz_a0_hr1_b0 = { + .fw_name = IWX_QUZ_A_HR_B_FW, +}; + +const struct iwx_device_cfg iwx_ax201_cfg_quz_hr = { + .fw_name = IWX_QUZ_A_HR_B_FW, +}; + +const struct iwx_device_cfg iwx_cfg_quz_a0_hr_b0 = { + .fw_name = IWX_QUZ_A_HR_B_FW, +}; + +#define IWX_CFG_ANY (~0) + +#define IWX_CFG_MAC_TYPE_QU 0x33 +#define IWX_CFG_MAC_TYPE_QUZ 0x35 +#define IWX_CFG_MAC_TYPE_QNJ 0x36 +#define IWX_CFG_MAC_TYPE_SO 0x37 +#define IWX_CFG_MAC_TYPE_SNJ 0x42 +#define IWX_CFG_MAC_TYPE_SOF 0x43 + +#define IWX_CFG_RF_TYPE_JF2 0x105 +#define IWX_CFG_RF_TYPE_JF1 0x108 +#define IWX_CFG_RF_TYPE_HR2 0x10a +#define IWX_CFG_RF_TYPE_HR1 0x10c + +#define IWX_CFG_RF_ID_JF 0x3 +#define IWX_CFG_RF_ID_JF1 0x6 +#define IWX_CFG_RF_ID_JF1_DIV 0xa + +#define IWX_CFG_NO_160 0x1 +#define IWX_CFG_160 0x0 + +#define IWX_CFG_CORES_BT 0x0 + +#define IWX_CFG_NO_CDB 0x0 + +#define IWX_SUBDEVICE_RF_ID(subdevice) ((uint16_t)((subdevice) & 0x00f0) >> 4) +#define IWX_SUBDEVICE_NO_160(subdevice) ((uint16_t)((subdevice) & 0x0200) >> 9) +#define IWX_SUBDEVICE_CORES(subdevice) ((uint16_t)((subdevice) & 0x1c00) >> 10) + struct iwx_softc { struct device sc_dev; struct ieee80211com sc_ic; @@ -493,6 +588,7 @@ struct iwx_softc { bus_space_handle_t sc_sh; bus_size_t sc_sz; bus_dma_tag_t sc_dmat; + pci_product_id_t sc_pid; pci_chipset_tag_t sc_pct; pcitag_t sc_pcitag; const void *sc_ih; @@ -516,11 +612,12 @@ struct iwx_softc { #define IWX_SILICON_A_STEP 0 #define IWX_SILICON_B_STEP 1 #define IWX_SILICON_C_STEP 2 -#define IWX_SILICON_D_STEP 3 +#define IWX_SILICON_Z_STEP 0xf int sc_hw_id; + int sc_hw_rf_id; int sc_device_family; #define IWX_DEVICE_FAMILY_22000 1 -#define IWX_DEVICE_FAMILY_22560 2 +#define IWX_DEVICE_FAMILY_AX210 2 struct iwx_dma_info ctxt_info_dma; struct iwx_self_init_dram init_dram; -- 2.20.1