diff options
Diffstat (limited to 'sys/contrib/dev/iwlwifi/tests')
| -rw-r--r-- | sys/contrib/dev/iwlwifi/tests/Makefile | 2 | ||||
| -rw-r--r-- | sys/contrib/dev/iwlwifi/tests/devinfo.c | 229 | 
2 files changed, 220 insertions, 11 deletions
| diff --git a/sys/contrib/dev/iwlwifi/tests/Makefile b/sys/contrib/dev/iwlwifi/tests/Makefile index 84491488f589..1b49241c578f 100644 --- a/sys/contrib/dev/iwlwifi/tests/Makefile +++ b/sys/contrib/dev/iwlwifi/tests/Makefile @@ -1,6 +1,6 @@  # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -iwlwifi-tests-y += module.o devinfo.o +iwlwifi-tests-y += module.o devinfo.o utils.o  ccflags-y += -I$(src)/../ diff --git a/sys/contrib/dev/iwlwifi/tests/devinfo.c b/sys/contrib/dev/iwlwifi/tests/devinfo.c index 7361b6d0cdb8..c31bbd4e7a4a 100644 --- a/sys/contrib/dev/iwlwifi/tests/devinfo.c +++ b/sys/contrib/dev/iwlwifi/tests/devinfo.c @@ -2,21 +2,59 @@  /*   * KUnit tests for the iwlwifi device info table   * - * Copyright (C) 2023-2024 Intel Corporation + * Copyright (C) 2023-2025 Intel Corporation   */  #include <kunit/test.h>  #include <linux/pci.h>  #include "iwl-drv.h"  #include "iwl-config.h" -MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); +MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");  static void iwl_pci_print_dev_info(const char *pfx, const struct iwl_dev_info *di)  { -	printk(KERN_DEBUG "%sdev=%.4x,subdev=%.4x,mac_type=%.4x,mac_step=%.4x,rf_type=%.4x,cdb=%d,jacket=%d,rf_id=%.2x,no_160=%d,cores=%.2x\n", -	       pfx, di->device, di->subdevice, di->mac_type, di->mac_step, -	       di->rf_type, di->cdb, di->jacket, di->rf_id, di->no_160, -	       di->cores); +	u16 subdevice_mask = GENMASK(di->subdevice_m_h, di->subdevice_m_l); +	char buf[100] = {}; +	int pos = 0; + +	if (di->match_rf_type) +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " rf_type=%03x", di->rf_type); +	else +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " rf_type=*"); + +	if (di->match_bw_limit) +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " bw_limit=%d", di->bw_limit); +	else +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " bw_limit=*"); + +	if (di->match_rf_id) +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " rf_id=0x%x", di->rf_id); +	else +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " rf_id=*"); + +	if (di->match_cdb) +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " cdb=%d", di->cdb); +	else +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " cdb=*"); + +	if (di->match_discrete) +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " discrete=%d", +				 di->discrete); +	else +		pos += scnprintf(buf + pos, sizeof(buf) - pos, +				 " discrete=*"); + +	printk(KERN_DEBUG "%sdev=%04x subdev=%04x/%04x%s\n", +	       pfx, di->device, di->subdevice, subdevice_mask, buf);  }  static void devinfo_table_order(struct kunit *test) @@ -28,11 +66,14 @@ static void devinfo_table_order(struct kunit *test)  		const struct iwl_dev_info *ret;  		ret = iwl_pci_find_dev_info(di->device, di->subdevice, -					    di->mac_type, di->mac_step,  					    di->rf_type, di->cdb, -					    di->jacket, di->rf_id, -					    di->no_160, di->cores, di->rf_step); -		if (ret != di) { +					    di->rf_id, di->bw_limit, +					    di->discrete); +		if (!ret) { +			iwl_pci_print_dev_info("No entry found for: ", di); +			KUNIT_FAIL(test, +				   "No entry found for entry at index %d\n", idx); +		} else if (ret != di) {  			iwl_pci_print_dev_info("searched: ", di);  			iwl_pci_print_dev_info("found:    ", ret);  			KUNIT_FAIL(test, @@ -42,6 +83,118 @@ static void devinfo_table_order(struct kunit *test)  	}  } +static void devinfo_discrete_match(struct kunit *test) +{ +	/* +	 * Validate that any entries with discrete/integrated match have +	 * the same config with the value inverted (if they match at all.) +	 */ + +	for (int idx = 0; idx < iwl_dev_info_table_size; idx++) { +		const struct iwl_dev_info *di = &iwl_dev_info_table[idx]; +		const struct iwl_dev_info *ret; + +		if (!di->match_discrete) +			continue; + +		ret = iwl_pci_find_dev_info(di->device, di->subdevice, +					    di->rf_type, di->cdb, +					    di->rf_id, di->bw_limit, +					    !di->discrete); +		if (!ret) +			continue; +		KUNIT_EXPECT_PTR_EQ(test, di->cfg, ret->cfg); +		/* and check the name is different, that'd be the point of it */ +		KUNIT_EXPECT_NE(test, strcmp(di->name, ret->name), 0); +	} +} + +static void devinfo_names(struct kunit *test) +{ +	int idx; + +	for (idx = 0; idx < iwl_dev_info_table_size; idx++) { +		const struct iwl_dev_info *di = &iwl_dev_info_table[idx]; + +		KUNIT_ASSERT_TRUE(test, di->name); +	} +} + +static void devinfo_no_cfg_dups(struct kunit *test) +{ +	for (int i = 0; i < iwl_dev_info_table_size; i++) { +		const struct iwl_rf_cfg *cfg_i = iwl_dev_info_table[i].cfg; + +		for (int j = 0; j < i; j++) { +			const struct iwl_rf_cfg *cfg_j = iwl_dev_info_table[j].cfg; + +			if (cfg_i == cfg_j) +				continue; + +			KUNIT_EXPECT_NE_MSG(test, memcmp(cfg_i, cfg_j, +							 sizeof(*cfg_i)), 0, +					    "identical configs: %ps and %ps\n", +					    cfg_i, cfg_j); +		} +	} +} + +static void devinfo_no_name_dups(struct kunit *test) +{ +	for (int i = 0; i < iwl_dev_info_table_size; i++) { +		for (int j = 0; j < i; j++) { +			if (iwl_dev_info_table[i].name == iwl_dev_info_table[j].name) +				continue; + +			KUNIT_EXPECT_NE_MSG(test, +					    strcmp(iwl_dev_info_table[i].name, +						   iwl_dev_info_table[j].name), +					    0, +					    "name dup: %ps/%ps", +					    iwl_dev_info_table[i].name, +					    iwl_dev_info_table[j].name); +		} +	} +} + +static void devinfo_check_subdev_match(struct kunit *test) +{ +	for (int i = 0; i < iwl_dev_info_table_size; i++) { +		const struct iwl_dev_info *di = &iwl_dev_info_table[i]; +		u16 subdevice_mask = GENMASK(di->subdevice_m_h, +					     di->subdevice_m_l); + +		/* if BW limit bit is matched then must have a limit */ +		if (di->match_bw_limit == 1 && di->bw_limit == 1) +			KUNIT_EXPECT_NE(test, di->cfg->bw_limit, 0); + +		/* if subdevice is ANY we can have RF ID/BW limit */ +		if (di->subdevice == (u16)IWL_CFG_ANY) +			continue; + +		/* same if the subdevice mask doesn't overlap them */ +		if (IWL_SUBDEVICE_RF_ID(subdevice_mask) == 0 && +		    IWL_SUBDEVICE_BW_LIM(subdevice_mask) == 0) +			continue; + +		/* but otherwise they shouldn't be used */ +		KUNIT_EXPECT_EQ(test, (int)di->match_rf_id, 0); +		KUNIT_EXPECT_EQ(test, (int)di->match_bw_limit, 0); +	} +} + +static void devinfo_check_killer_subdev(struct kunit *test) +{ +	for (int i = 0; i < iwl_dev_info_table_size; i++) { +		const struct iwl_dev_info *di = &iwl_dev_info_table[i]; + +		if (!strstr(di->name, "Killer")) +			continue; + +		KUNIT_EXPECT_NE(test, di->subdevice, (u16)IWL_CFG_ANY); +	} +} +  static void devinfo_pci_ids(struct kunit *test)  {  	struct pci_dev *dev; @@ -64,9 +217,65 @@ static void devinfo_pci_ids(struct kunit *test)  	}  } +static void devinfo_no_mac_cfg_dups(struct kunit *test) +{ +	for (int i = 0; iwl_hw_card_ids[i].vendor; i++) { +		const struct iwl_mac_cfg *cfg_i = +			(void *)iwl_hw_card_ids[i].driver_data; + +		for (int j = 0; j < i; j++) { +			const struct iwl_mac_cfg *cfg_j = +				(void *)iwl_hw_card_ids[j].driver_data; + +			if (cfg_i == cfg_j) +				continue; + +			KUNIT_EXPECT_NE_MSG(test, memcmp(cfg_j, cfg_i, +							 sizeof(*cfg_i)), 0, +					    "identical configs: %ps and %ps\n", +					    cfg_i, cfg_j); +		} +	} +} + +static void devinfo_api_range(struct kunit *test) +{ +	/* Check that all iwl_mac_cfg's have either both min and max set, or neither */ +	for (int i = 0; iwl_hw_card_ids[i].vendor; i++) { +		const struct iwl_mac_cfg *mac_cfg = +			(void *)iwl_hw_card_ids[i].driver_data; +		const struct iwl_family_base_params *base = mac_cfg->base; + +		KUNIT_EXPECT_EQ_MSG(test, !!base->ucode_api_min, +				    !!base->ucode_api_max, +				    "%ps: ucode_api_min (%u) and ucode_api_min (%u) should be both set or neither.\n", +				    base, base->ucode_api_min, +				    base->ucode_api_max); +	} + +	/* Check the same for the iwl_rf_cfg's */ +	for (int i = 0; i < iwl_dev_info_table_size; i++) { +		const struct iwl_rf_cfg *rf_cfg = iwl_dev_info_table[i].cfg; + +		KUNIT_EXPECT_EQ_MSG(test, !!rf_cfg->ucode_api_min, +				    !!rf_cfg->ucode_api_max, +				    "%ps: ucode_api_min (%u) and ucode_api_min (%u) should be both set or neither.\n", +				    rf_cfg, rf_cfg->ucode_api_min, +				    rf_cfg->ucode_api_max); +	} +} +  static struct kunit_case devinfo_test_cases[] = {  	KUNIT_CASE(devinfo_table_order), +	KUNIT_CASE(devinfo_discrete_match), +	KUNIT_CASE(devinfo_names), +	KUNIT_CASE(devinfo_no_cfg_dups), +	KUNIT_CASE(devinfo_no_name_dups), +	KUNIT_CASE(devinfo_check_subdev_match), +	KUNIT_CASE(devinfo_check_killer_subdev),  	KUNIT_CASE(devinfo_pci_ids), +	KUNIT_CASE(devinfo_no_mac_cfg_dups), +	KUNIT_CASE(devinfo_api_range),  	{}  }; | 
