From: Stefan Sperling Subject: iwx: support MCC update response version 4 To: tech@openbsd.org Date: Mon, 2 Mar 2026 14:59:32 +0100 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? 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