On 2025/07/18 03:33, Prateek Kumar wrote:
> iwx0: using firmware iwx-QuZ-a0-hr-b0-77
> [ 3.571806] iwlwifi 0000:00:14.3: PCI dev a0f0/0264, rev=0x351,
> rfid=0x108110
> [ 3.571813] iwlwifi 0000:00:14.3: Detected Intel(R) Wireless-AC 9461
> [ 3.577698] iwlwifi 0000:00:14.3: TLV_FW_FSEQ_VERSION: FSEQ Version:
> 89.3.35.37
> [ 3.578120] iwlwifi 0000:00:14.3: loaded firmware version
> 77.f31a351f.0 QuZ-a0-jf-b0-77.ucode op_mode iwlmvm
so decoding from the fw name, the MAC is QuZ, stepping a0, RF chip
is jf (but we misdetect as hr) stepping b0.
linux iwlwifi builds up the firmware filename piece by piece.
iwx does not but instead has hardcoded filenames. There's one match
table (which does look at rf though doesn't include any QuZ jf) and
also does some other detection mostly(?) based on the MAC id/revision
and currently not looking at rf id.
> >Fix:
> The iwx driver code configures the device and sets the fwname
> based on its pci id and hardware parameters. For this particular
> wireless device, the rest of the configuration is fine but the
> fwname is set incorrectly (i.e. different from what iwlwifi sets).
>
> As a workaround to gain connectivity initially, the QuZ-a0-hr-b0-77
> firmware file in /etc/firmware can be replaced with the correct one
> under the same name:
> # cd /etc/firmware
> # mv iwx-QuZ-a0-hr-b0-77 iwx-QuZ-a0-hr-b0-77.bak
> # ln iwx-QuZ-a0-jf-b0-77 iwx-QuZ-a0-hr-b0-77
>
> The patch given below fixes the logic that sets the correct fwname
> for this wireless device. The driver with this patch applied works
> as expected:
> iwx0 at pci0 dev 20 function 3 "Intel Wi-Fi 6 AX201" rev 0x20, msix
> iwx0: hw rev 0x350, fw 77.206b0184.0, address 80:b6:55:ce:45:6e
> iwx0: using firmware iwx-QuZ-a0-jf-b0-77
> Index: if_iwx.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_iwx.c,v
> retrieving revision 1.191
> diff -u -p -u -p -r1.191 if_iwx.c
> --- if_iwx.c 29 Jun 2025 19:32:08 -0000 1.191
> +++ if_iwx.c 17 Jul 2025 15:22:57 -0000
> @@ -11487,12 +11487,7 @@ iwx_attach(struct device *parent, struct
> 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_fwname = IWX_QUZ_A_JF_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;
That doesn't seem like a commitable fix, it's likely to fix some
devices at the expense of breaking others.
Wonder if this might do the trick, though a bigger change of building
up the firmware filename from pieces would seem likely to give correct
results more often, and probably end up less complicated.
Index: if_iwx.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwx.c,v
diff -u -p -r1.191 if_iwx.c
--- if_iwx.c 29 Jun 2025 19:32:08 -0000 1.191
+++ if_iwx.c 18 Jul 2025 13:49:59 -0000
@@ -11247,15 +11247,16 @@ iwx_preinit(struct iwx_softc *sc)
/* Print version info and MAC address on first successful fw load. */
sc->attached = 1;
if (sc->sc_pnvm_ver) {
- printf("%s: hw rev 0x%x, fw %s, pnvm %08x, "
+ printf("%s: hw rev 0x%x, rf 0x%x, fw %s, pnvm %08x, "
"address %s\n",
DEVNAME(sc), sc->sc_hw_rev & IWX_CSR_HW_REV_TYPE_MSK,
- sc->sc_fwver, sc->sc_pnvm_ver,
+ sc->sc_hw_rf_id, sc->sc_fwver, sc->sc_pnvm_ver,
ether_sprintf(sc->sc_nvm.hw_addr));
} else {
- printf("%s: hw rev 0x%x, fw %s, address %s\n",
+ printf("%s: hw rev 0x%x, rf 0x%x, fw %s, address %s\n",
DEVNAME(sc), sc->sc_hw_rev & IWX_CSR_HW_REV_TYPE_MSK,
- sc->sc_fwver, ether_sprintf(sc->sc_nvm.hw_addr));
+ sc->sc_hw_rf_id, sc->sc_fwver,
+ ether_sprintf(sc->sc_nvm.hw_addr));
}
if (sc->sc_nvm.sku_cap_11n_enable)
@@ -11477,7 +11478,10 @@ iwx_attach(struct device *parent, struct
printf("%s: unsupported AX201 adapter\n", DEVNAME(sc));
return;
}
- sc->sc_fwname = IWX_QUZ_A_HR_B_FW;
+ if (sc->sc_hw_rf_id == IWX_CFG_RF_ID_JF)
+ sc->sc_fwname = IWX_QUZ_A_JF_B_FW;
+ else
+ 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;
@@ -11490,7 +11494,10 @@ iwx_attach(struct device *parent, struct
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;
+ if (sc->sc_hw_rf_id == IWX_CFG_RF_ID_JF)
+ sc->sc_fwname = IWX_QUZ_A_JF_B_FW;
+ else
+ 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;
@@ -11507,7 +11514,10 @@ iwx_attach(struct device *parent, struct
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;
+ if (sc->sc_hw_rf_id == IWX_CFG_RF_ID_JF)
+ sc->sc_fwname = IWX_QUZ_A_JF_B_FW;
+ else
+ 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;
@@ -11522,7 +11532,10 @@ iwx_attach(struct device *parent, struct
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;
+ if (sc->sc_hw_rf_id == IWX_CFG_RF_ID_JF)
+ sc->sc_fwname = IWX_QUZ_A_JF_B_FW;
+ else
+ 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;