Download raw body.
iwx: support MCC update response version 4
> Date: Mon, 2 Mar 2026 14:59:32 +0100
> From: Stefan Sperling <stsp@stsp.name>
>
> Add support for MCC update response version 4.
> We receive this version on firmware for BZ devices.
>
> This notification provides an updated list of channels the firmware
> consideres valid. And it tells us which country code firmware has
> detected during scans.
>
> As with earlier versions of this command, we do update the channel map
> but we don't do anything with the country code. We always run firmware
> in the "world" regulatory domain.
>
> ok?
Doesn't break MA and looks fine to me.
ok kettenis@
> M sys/dev/pci/if_iwx.c | 55+ 16-
> M sys/dev/pci/if_iwxreg.h | 28+ 0-
>
> 2 files changed, 83 insertions(+), 16 deletions(-)
>
> commit - 113cb9a5d6155149dad7584530c6b03a26fa6b67
> commit + 1c2d536d6cc6469071ec899f540dc8c94a45e0c3
> blob - 0c5699264df1312403e63d66e1f41a25b4837ca8
> blob + d51929b47f482a5fcae2c9c97d06ed79c2817f67
> --- sys/dev/pci/if_iwx.c
> +++ sys/dev/pci/if_iwx.c
> @@ -9731,10 +9731,17 @@ iwx_send_update_mcc_cmd(struct iwx_softc *sc, const ch
> .data = { &mcc_cmd },
> };
> struct iwx_rx_packet *pkt;
> - struct iwx_mcc_update_resp *resp;
> size_t resp_len;
> - int err;
> + int err, resp_version;
>
> + resp_version = iwx_lookup_notif_ver(sc, IWX_LONG_GROUP,
> + IWX_MCC_UPDATE_CMD);
> + if (resp_version >= 8) {
> + printf("%s: unsupported MCC update command response "
> + "version %u\n", DEVNAME(sc), resp_version);
> + return ENOTSUP;
> + }
> +
> memset(&mcc_cmd, 0, sizeof(mcc_cmd));
> mcc_cmd.mcc = htole16(alpha2[0] << 8 | alpha2[1]);
> if (isset(sc->sc_ucode_api, IWX_UCODE_TLV_API_WIFI_MCC_UPDATE) ||
> @@ -9757,24 +9764,56 @@ iwx_send_update_mcc_cmd(struct iwx_softc *sc, const ch
> }
>
> resp_len = iwx_rx_packet_payload_len(pkt);
> - if (resp_len < sizeof(*resp)) {
> - err = EIO;
> - goto out;
> - }
>
> - resp = (void *)pkt->data;
> - if (resp_len != sizeof(*resp) +
> - resp->n_channels * sizeof(resp->channels[0])) {
> - err = EIO;
> - goto out;
> - }
>
> - DPRINTF(("MCC status=0x%x mcc=0x%x cap=0x%x time=0x%x geo_info=0x%x source_id=0x%d n_channels=%u\n",
> - resp->status, resp->mcc, resp->cap, resp->time, resp->geo_info, resp->source_id, resp->n_channels));
> + if (isset(sc->sc_enabled_capa,
> + IWX_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
> + struct iwx_mcc_update_resp_v4 *resp;
>
> - /* Update channel map for net80211 and our scan configuration. */
> - iwx_init_channel_map(sc, NULL, resp->channels, resp->n_channels);
> + if (resp_len < sizeof(*resp)) {
> + err = EIO;
> + goto out;
> + }
>
> + resp = (void *)pkt->data;
> + if (resp_len != sizeof(*resp) +
> + resp->n_channels * sizeof(resp->channels[0])) {
> + err = EIO;
> + goto out;
> + }
> +
> + DPRINTF(("MCC status=0x%x mcc=0x%x cap=0x%x time=0x%x "
> + "geo_info=0x%x source_id=0x%d n_channels=%u\n",
> + resp->status, resp->mcc, resp->cap, resp->time,
> + resp->geo_info, resp->source_id, resp->n_channels));
> +
> + /* Update channel map and our scan configuration. */
> + iwx_init_channel_map(sc, NULL, resp->channels,
> + resp->n_channels);
> + } else {
> + struct iwx_mcc_update_resp *resp;
> +
> + if (resp_len < sizeof(*resp)) {
> + err = EIO;
> + goto out;
> + }
> + resp = (void *)pkt->data;
> + if (resp_len != sizeof(*resp) +
> + resp->n_channels * sizeof(resp->channels[0])) {
> + err = EIO;
> + goto out;
> + }
> +
> + DPRINTF(("MCC status=0x%x mcc=0x%x cap=0x%x time=0x%x "
> + "geo_info=0x%x source_id=0x%d n_channels=%u\n",
> + resp->status, resp->mcc, resp->cap, resp->time,
> + resp->geo_info, resp->source_id, resp->n_channels));
> +
> + /* Update channel map and our scan configuration. */
> + iwx_init_channel_map(sc, NULL, resp->channels,
> + resp->n_channels);
> + }
> +
> out:
> iwx_free_resp(sc, &hcmd);
>
> blob - fb40a1894862858f4e5baae506e0cae732e4cce7
> blob + d80e0fdff2017b0aac4512d5367ed3ee8eb93e29
> --- sys/dev/pci/if_iwxreg.h
> +++ sys/dev/pci/if_iwxreg.h
> @@ -8516,6 +8516,34 @@ struct iwx_mcc_update_resp_v3 {
> } __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */
>
> /**
> + * struct iwx_mcc_update_resp_v4 - response to MCC_UPDATE_CMD.
> + * Contains the new channel control profile map, if changed, and the new MCC
> + * (mobile country code).
> + * The new MCC may be different than what was requested in MCC_UPDATE_CMD.
> + * @status: see &enum iwx_mcc_update_status
> + * @mcc: the new applied MCC
> + * @cap: capabilities for all channels which matches the MCC
> + * @time: time elapsed from the MCC test start (in units of 30 seconds)
> + * @geo_info: geographic specific profile information
> + * see &enum iwl_geo_information.
> + * @source_id: the MCC source, see iwl_mcc_source
> + * @reserved: for four bytes alignment.
> + * @n_channels: number of channels in @channels_data.
> + * @channels: channel control data map, DWORD for each channel. Only the first
> + * 16bits are used.
> + */
> +struct iwx_mcc_update_resp_v4 {
> + uint32_t status;
> + uint16_t mcc;
> + uint16_t cap;
> + uint16_t time;
> + uint16_t geo_info;
> + uint8_t source_id;
> + uint8_t reserved[3];
> + uint32_t n_channels;
> + uint32_t channels[];
> +} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_4 */
> +/**
> * geographic information.
> * @GEO_NO_INFO: no special info for this geo profile.
> * @GEO_WMM_ETSI_5GHZ_INFO: this geo profile limits the WMM params
>
>
iwx: support MCC update response version 4