Index | Thread | Search

From:
Mark Kettenis <mark.kettenis@xs4all.nl>
Subject:
Re: iwx: support MCC update response version 4
To:
Stefan Sperling <stsp@stsp.name>
Cc:
tech@openbsd.org
Date:
Mon, 02 Mar 2026 21:24:37 +0100

Download raw body.

Thread
> 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
> 
>