Path: blob/main/sys/contrib/dev/iwlwifi/tests/devinfo.c
48375 views
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1/*2* KUnit tests for the iwlwifi device info table3*4* Copyright (C) 2023-2025 Intel Corporation5*/6#include <kunit/test.h>7#include <linux/pci.h>8#include "iwl-drv.h"9#include "iwl-config.h"1011MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");1213static void iwl_pci_print_dev_info(const char *pfx, const struct iwl_dev_info *di)14{15u16 subdevice_mask = GENMASK(di->subdevice_m_h, di->subdevice_m_l);16char buf[100] = {};17int pos = 0;1819if (di->match_rf_type)20pos += scnprintf(buf + pos, sizeof(buf) - pos,21" rf_type=%03x", di->rf_type);22else23pos += scnprintf(buf + pos, sizeof(buf) - pos,24" rf_type=*");2526if (di->match_bw_limit)27pos += scnprintf(buf + pos, sizeof(buf) - pos,28" bw_limit=%d", di->bw_limit);29else30pos += scnprintf(buf + pos, sizeof(buf) - pos,31" bw_limit=*");3233if (di->match_rf_id)34pos += scnprintf(buf + pos, sizeof(buf) - pos,35" rf_id=0x%x", di->rf_id);36else37pos += scnprintf(buf + pos, sizeof(buf) - pos,38" rf_id=*");3940if (di->match_cdb)41pos += scnprintf(buf + pos, sizeof(buf) - pos,42" cdb=%d", di->cdb);43else44pos += scnprintf(buf + pos, sizeof(buf) - pos,45" cdb=*");4647if (di->match_discrete)48pos += scnprintf(buf + pos, sizeof(buf) - pos,49" discrete=%d",50di->discrete);51else52pos += scnprintf(buf + pos, sizeof(buf) - pos,53" discrete=*");5455printk(KERN_DEBUG "%sdev=%04x subdev=%04x/%04x%s\n",56pfx, di->device, di->subdevice, subdevice_mask, buf);57}5859static void devinfo_table_order(struct kunit *test)60{61int idx;6263for (idx = 0; idx < iwl_dev_info_table_size; idx++) {64const struct iwl_dev_info *di = &iwl_dev_info_table[idx];65const struct iwl_dev_info *ret;6667ret = iwl_pci_find_dev_info(di->device, di->subdevice,68di->rf_type, di->cdb,69di->rf_id, di->bw_limit,70di->discrete);71if (!ret) {72iwl_pci_print_dev_info("No entry found for: ", di);73KUNIT_FAIL(test,74"No entry found for entry at index %d\n", idx);75} else if (ret != di) {76iwl_pci_print_dev_info("searched: ", di);77iwl_pci_print_dev_info("found: ", ret);78KUNIT_FAIL(test,79"unusable entry at index %d (found index %d instead)\n",80idx, (int)(ret - iwl_dev_info_table));81}82}83}8485static void devinfo_discrete_match(struct kunit *test)86{87/*88* Validate that any entries with discrete/integrated match have89* the same config with the value inverted (if they match at all.)90*/9192for (int idx = 0; idx < iwl_dev_info_table_size; idx++) {93const struct iwl_dev_info *di = &iwl_dev_info_table[idx];94const struct iwl_dev_info *ret;9596if (!di->match_discrete)97continue;9899ret = iwl_pci_find_dev_info(di->device, di->subdevice,100di->rf_type, di->cdb,101di->rf_id, di->bw_limit,102!di->discrete);103if (!ret)104continue;105KUNIT_EXPECT_PTR_EQ(test, di->cfg, ret->cfg);106/* and check the name is different, that'd be the point of it */107KUNIT_EXPECT_NE(test, strcmp(di->name, ret->name), 0);108}109}110111static void devinfo_names(struct kunit *test)112{113int idx;114115for (idx = 0; idx < iwl_dev_info_table_size; idx++) {116const struct iwl_dev_info *di = &iwl_dev_info_table[idx];117118KUNIT_ASSERT_TRUE(test, di->name);119}120}121122static void devinfo_no_cfg_dups(struct kunit *test)123{124for (int i = 0; i < iwl_dev_info_table_size; i++) {125const struct iwl_rf_cfg *cfg_i = iwl_dev_info_table[i].cfg;126127for (int j = 0; j < i; j++) {128const struct iwl_rf_cfg *cfg_j = iwl_dev_info_table[j].cfg;129130if (cfg_i == cfg_j)131continue;132133KUNIT_EXPECT_NE_MSG(test, memcmp(cfg_i, cfg_j,134sizeof(*cfg_i)), 0,135"identical configs: %ps and %ps\n",136cfg_i, cfg_j);137}138}139}140141static void devinfo_no_name_dups(struct kunit *test)142{143for (int i = 0; i < iwl_dev_info_table_size; i++) {144for (int j = 0; j < i; j++) {145if (iwl_dev_info_table[i].name == iwl_dev_info_table[j].name)146continue;147148KUNIT_EXPECT_NE_MSG(test,149strcmp(iwl_dev_info_table[i].name,150iwl_dev_info_table[j].name),1510,152"name dup: %ps/%ps",153iwl_dev_info_table[i].name,154iwl_dev_info_table[j].name);155}156}157}158159static void devinfo_check_subdev_match(struct kunit *test)160{161for (int i = 0; i < iwl_dev_info_table_size; i++) {162const struct iwl_dev_info *di = &iwl_dev_info_table[i];163u16 subdevice_mask = GENMASK(di->subdevice_m_h,164di->subdevice_m_l);165166/* if BW limit bit is matched then must have a limit */167if (di->match_bw_limit == 1 && di->bw_limit == 1)168KUNIT_EXPECT_NE(test, di->cfg->bw_limit, 0);169170/* if subdevice is ANY we can have RF ID/BW limit */171if (di->subdevice == (u16)IWL_CFG_ANY)172continue;173174/* same if the subdevice mask doesn't overlap them */175if (IWL_SUBDEVICE_RF_ID(subdevice_mask) == 0 &&176IWL_SUBDEVICE_BW_LIM(subdevice_mask) == 0)177continue;178179/* but otherwise they shouldn't be used */180KUNIT_EXPECT_EQ(test, (int)di->match_rf_id, 0);181KUNIT_EXPECT_EQ(test, (int)di->match_bw_limit, 0);182}183}184185static void devinfo_check_killer_subdev(struct kunit *test)186{187for (int i = 0; i < iwl_dev_info_table_size; i++) {188const struct iwl_dev_info *di = &iwl_dev_info_table[i];189190if (!strstr(di->name, "Killer"))191continue;192193KUNIT_EXPECT_NE(test, di->subdevice, (u16)IWL_CFG_ANY);194}195}196197static void devinfo_pci_ids(struct kunit *test)198{199struct pci_dev *dev;200201dev = kunit_kmalloc(test, sizeof(*dev), GFP_KERNEL);202KUNIT_ASSERT_NOT_NULL(test, dev);203204for (int i = 0; iwl_hw_card_ids[i].vendor; i++) {205const struct pci_device_id *s, *t;206207s = &iwl_hw_card_ids[i];208dev->vendor = s->vendor;209dev->device = s->device;210dev->subsystem_vendor = s->subvendor;211dev->subsystem_device = s->subdevice;212dev->class = s->class;213214t = pci_match_id(iwl_hw_card_ids, dev);215KUNIT_EXPECT_PTR_EQ(test, t, s);216}217}218219static void devinfo_no_mac_cfg_dups(struct kunit *test)220{221for (int i = 0; iwl_hw_card_ids[i].vendor; i++) {222const struct iwl_mac_cfg *cfg_i =223(void *)iwl_hw_card_ids[i].driver_data;224225for (int j = 0; j < i; j++) {226const struct iwl_mac_cfg *cfg_j =227(void *)iwl_hw_card_ids[j].driver_data;228229if (cfg_i == cfg_j)230continue;231232KUNIT_EXPECT_NE_MSG(test, memcmp(cfg_j, cfg_i,233sizeof(*cfg_i)), 0,234"identical configs: %ps and %ps\n",235cfg_i, cfg_j);236}237}238}239240static void devinfo_api_range(struct kunit *test)241{242/* Check that all iwl_mac_cfg's have either both min and max set, or neither */243for (int i = 0; iwl_hw_card_ids[i].vendor; i++) {244const struct iwl_mac_cfg *mac_cfg =245(void *)iwl_hw_card_ids[i].driver_data;246const struct iwl_family_base_params *base = mac_cfg->base;247248KUNIT_EXPECT_EQ_MSG(test, !!base->ucode_api_min,249!!base->ucode_api_max,250"%ps: ucode_api_min (%u) and ucode_api_min (%u) should be both set or neither.\n",251base, base->ucode_api_min,252base->ucode_api_max);253}254255/* Check the same for the iwl_rf_cfg's */256for (int i = 0; i < iwl_dev_info_table_size; i++) {257const struct iwl_rf_cfg *rf_cfg = iwl_dev_info_table[i].cfg;258259KUNIT_EXPECT_EQ_MSG(test, !!rf_cfg->ucode_api_min,260!!rf_cfg->ucode_api_max,261"%ps: ucode_api_min (%u) and ucode_api_min (%u) should be both set or neither.\n",262rf_cfg, rf_cfg->ucode_api_min,263rf_cfg->ucode_api_max);264}265}266267static struct kunit_case devinfo_test_cases[] = {268KUNIT_CASE(devinfo_table_order),269KUNIT_CASE(devinfo_discrete_match),270KUNIT_CASE(devinfo_names),271KUNIT_CASE(devinfo_no_cfg_dups),272KUNIT_CASE(devinfo_no_name_dups),273KUNIT_CASE(devinfo_check_subdev_match),274KUNIT_CASE(devinfo_check_killer_subdev),275KUNIT_CASE(devinfo_pci_ids),276KUNIT_CASE(devinfo_no_mac_cfg_dups),277KUNIT_CASE(devinfo_api_range),278{}279};280281static struct kunit_suite iwlwifi_devinfo = {282.name = "iwlwifi-devinfo",283.test_cases = devinfo_test_cases,284};285286kunit_test_suite(iwlwifi_devinfo);287288289