diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-14 20:44:09 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-14 20:44:09 +0300 |
commit | 66fd6d0bd7572fcb7859ebd4dbfb133881e1cd66 (patch) | |
tree | 53e7a8837794e12512a2b5f23783eef54af3ea3c /drivers/platform/x86/intel | |
parent | f5c31bcf604db54470868f3118a60dc4a9ba8813 (diff) | |
parent | 16f8091b49175f327120cdbbdde135d38a853ae1 (diff) | |
download | linux-66fd6d0bd7572fcb7859ebd4dbfb133881e1cd66.tar.xz |
Merge tag 'platform-drivers-x86-v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver updates from Ilpo Järvinen:
- New acer-wmi HW support
- Support for new revision of amd/pmf heartbeat notify
- Correctly handle asus-wmi HW without LEDs
- fujitsu-laptop battery charge control support
- Support for new hp-wmi thermal profiles
- Support ideapad-laptop refresh rate key
- Put intel/pmc AI accelerator (GNA) into D3 if it has no driver to
allow entry into low-power modes, and temporarily removed Lunar Lake
SSRAM support due to breaking FW changes causing probe fail (further
breaking FW changes are still pending)
- Report pmc/punit_atom devices that prevent reacing low power levels
- Surface Fan speed function support
- Support for more sperial keys and complete the list of models with
non-standard fan registers in thinkpad_acpi
- New DMI touchscreen HW support
- Continued modernization efforts of wmi
- Removal of obsoleted ledtrig-audio call and the related dependency
- Debug & metrics interface improvements
- Miscellaneous cleanups / fixes / improvements
* tag 'platform-drivers-x86-v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (87 commits)
platform/x86/intel/pmc: Improve PKGC residency counters debug
platform/x86: asus-wmi: Consider device is absent when the read is ~0
Documentation/x86/amd/hsmp: Updating urls
platform/mellanox: mlxreg-hotplug: Remove redundant NULL-check
platform/x86/amd/pmf: Update sps power thermals according to the platform-profiles
platform/x86/amd/pmf: Add support to get sps default APTS index values
platform/x86/amd/pmf: Add support to get APTS index numbers for static slider
platform/x86/amd/pmf: Add support to notify sbios heart beat event
platform/x86/amd/pmf: Add support to get sbios requests in PMF driver
platform/x86/amd/pmf: Disable debugfs support for querying power thermals
platform/x86/amd/pmf: Differentiate PMF ACPI versions
x86/platform/atom: Check state of Punit managed devices on s2idle
platform/x86: pmc_atom: Check state of PMC clocks on s2idle
platform/x86: pmc_atom: Check state of PMC managed devices on s2idle
platform/x86: pmc_atom: Annotate d3_sts register bit defines
clk: x86: Move clk-pmc-atom register defines to include/linux/platform_data/x86/pmc_atom.h
platform/x86: make fw_attr_class constant
platform/x86/intel/tpmi: Change vsec offset to u64
platform/x86: intel_scu_pcidrv: Remove unused intel-mid.h
platform/x86: intel_scu_wdt: Remove unused intel-mid.h
...
Diffstat (limited to 'drivers/platform/x86/intel')
-rw-r--r-- | drivers/platform/x86/intel/ifs/load.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/intel/ifs/runtest.c | 101 | ||||
-rw-r--r-- | drivers/platform/x86/intel/pmc/arl.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/intel/pmc/core.c | 47 | ||||
-rw-r--r-- | drivers/platform/x86/intel/pmc/core.h | 7 | ||||
-rw-r--r-- | drivers/platform/x86/intel/pmc/lnl.c | 40 | ||||
-rw-r--r-- | drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c | 4 | ||||
-rw-r--r-- | drivers/platform/x86/intel/tpmi.c | 9 | ||||
-rw-r--r-- | drivers/platform/x86/intel/vsec.c | 5 | ||||
-rw-r--r-- | drivers/platform/x86/intel/wmi/sbl-fw-update.c | 1 | ||||
-rw-r--r-- | drivers/platform/x86/intel/wmi/thunderbolt.c | 1 |
11 files changed, 121 insertions, 98 deletions
diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c index 2cf3b4a8813f..584c44387e10 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -383,7 +383,7 @@ int ifs_load_firmware(struct device *dev) unsigned int expected_size; const struct firmware *fw; char scan_path[64]; - int ret = -EINVAL; + int ret; snprintf(scan_path, sizeof(scan_path), "intel/ifs_%d/%02x-%02x-%02x-%02x.scan", test->test_num, boot_cpu_data.x86, boot_cpu_data.x86_model, diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c index 13ecd55c6668..95b4b71fab53 100644 --- a/drivers/platform/x86/intel/ifs/runtest.c +++ b/drivers/platform/x86/intel/ifs/runtest.c @@ -23,6 +23,12 @@ /* Max retries on the same chunk */ #define MAX_IFS_RETRIES 5 +struct run_params { + struct ifs_data *ifsd; + union ifs_scan *activate; + union ifs_status status; +}; + /* * Number of TSC cycles that a logical CPU will wait for the other * logical CPU on the core in the WRMSR(ACTIVATE_SCAN). @@ -134,19 +140,56 @@ static bool can_restart(union ifs_status status) return false; } +#define SPINUNIT 100 /* 100 nsec */ +static atomic_t array_cpus_in; +static atomic_t scan_cpus_in; + +/* + * Simplified cpu sibling rendezvous loop based on microcode loader __wait_for_cpus() + */ +static void wait_for_sibling_cpu(atomic_t *t, long long timeout) +{ + int cpu = smp_processor_id(); + const struct cpumask *smt_mask = cpu_smt_mask(cpu); + int all_cpus = cpumask_weight(smt_mask); + + atomic_inc(t); + while (atomic_read(t) < all_cpus) { + if (timeout < SPINUNIT) + return; + ndelay(SPINUNIT); + timeout -= SPINUNIT; + touch_nmi_watchdog(); + } +} + /* * Execute the scan. Called "simultaneously" on all threads of a core * at high priority using the stop_cpus mechanism. */ static int doscan(void *data) { - int cpu = smp_processor_id(); - u64 *msrs = data; + int cpu = smp_processor_id(), start, stop; + struct run_params *params = data; + union ifs_status status; + struct ifs_data *ifsd; int first; + ifsd = params->ifsd; + + if (ifsd->generation) { + start = params->activate->gen2.start; + stop = params->activate->gen2.stop; + } else { + start = params->activate->gen0.start; + stop = params->activate->gen0.stop; + } + /* Only the first logical CPU on a core reports result */ first = cpumask_first(cpu_smt_mask(cpu)); + wait_for_sibling_cpu(&scan_cpus_in, NSEC_PER_SEC); + /* * This WRMSR will wait for other HT threads to also write * to this MSR (at most for activate.delay cycles). Then it @@ -155,12 +198,14 @@ static int doscan(void *data) * take up to 200 milliseconds (in the case where all chunks * are processed in a single pass) before it retires. */ - wrmsrl(MSR_ACTIVATE_SCAN, msrs[0]); + wrmsrl(MSR_ACTIVATE_SCAN, params->activate->data); + rdmsrl(MSR_SCAN_STATUS, status.data); - if (cpu == first) { - /* Pass back the result of the scan */ - rdmsrl(MSR_SCAN_STATUS, msrs[1]); - } + trace_ifs_status(ifsd->cur_batch, start, stop, status.data); + + /* Pass back the result of the scan */ + if (cpu == first) + params->status = status; return 0; } @@ -179,7 +224,7 @@ static void ifs_test_core(int cpu, struct device *dev) struct ifs_data *ifsd; int to_start, to_stop; int status_chunk; - u64 msrvals[2]; + struct run_params params; int retries; ifsd = ifs_get_data(dev); @@ -190,6 +235,8 @@ static void ifs_test_core(int cpu, struct device *dev) to_start = 0; to_stop = ifsd->valid_chunks - 1; + params.ifsd = ifs_get_data(dev); + if (ifsd->generation) { activate.gen2.start = to_start; activate.gen2.stop = to_stop; @@ -207,12 +254,11 @@ static void ifs_test_core(int cpu, struct device *dev) break; } - msrvals[0] = activate.data; - stop_core_cpuslocked(cpu, doscan, msrvals); - - status.data = msrvals[1]; + params.activate = &activate; + atomic_set(&scan_cpus_in, 0); + stop_core_cpuslocked(cpu, doscan, ¶ms); - trace_ifs_status(cpu, to_start, to_stop, status.data); + status = params.status; /* Some cases can be retried, give up for others */ if (!can_restart(status)) @@ -250,34 +296,14 @@ static void ifs_test_core(int cpu, struct device *dev) } } -#define SPINUNIT 100 /* 100 nsec */ -static atomic_t array_cpus_out; - -/* - * Simplified cpu sibling rendezvous loop based on microcode loader __wait_for_cpus() - */ -static void wait_for_sibling_cpu(atomic_t *t, long long timeout) -{ - int cpu = smp_processor_id(); - const struct cpumask *smt_mask = cpu_smt_mask(cpu); - int all_cpus = cpumask_weight(smt_mask); - - atomic_inc(t); - while (atomic_read(t) < all_cpus) { - if (timeout < SPINUNIT) - return; - ndelay(SPINUNIT); - timeout -= SPINUNIT; - touch_nmi_watchdog(); - } -} - static int do_array_test(void *data) { union ifs_array *command = data; int cpu = smp_processor_id(); int first; + wait_for_sibling_cpu(&array_cpus_in, NSEC_PER_SEC); + /* * Only one logical CPU on a core needs to trigger the Array test via MSR write. */ @@ -289,9 +315,6 @@ static int do_array_test(void *data) rdmsrl(MSR_ARRAY_BIST, command->data); } - /* Tests complete faster if the sibling is spinning here */ - wait_for_sibling_cpu(&array_cpus_out, NSEC_PER_SEC); - return 0; } @@ -312,7 +335,7 @@ static void ifs_array_test_core(int cpu, struct device *dev) timed_out = true; break; } - atomic_set(&array_cpus_out, 0); + atomic_set(&array_cpus_in, 0); stop_core_cpuslocked(cpu, do_array_test, &command); if (command.ctrl_result) diff --git a/drivers/platform/x86/intel/pmc/arl.c b/drivers/platform/x86/intel/pmc/arl.c index 683ae828276b..34b4cd23bfe5 100644 --- a/drivers/platform/x86/intel/pmc/arl.c +++ b/drivers/platform/x86/intel/pmc/arl.c @@ -673,6 +673,7 @@ static struct pmc_info arl_pmc_info_list[] = { }; #define ARL_NPU_PCI_DEV 0xad1d +#define ARL_GNA_PCI_DEV 0xae4c /* * Set power state of select devices that do not have drivers to D3 * so that they do not block Package C entry. @@ -680,6 +681,7 @@ static struct pmc_info arl_pmc_info_list[] = { static void arl_d3_fixup(void) { pmc_core_set_device_d3(ARL_NPU_PCI_DEV); + pmc_core_set_device_d3(ARL_GNA_PCI_DEV); } static int arl_resume(struct pmc_dev *pmcdev) diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index 8f9c036809c7..10c96c1a850a 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -1389,6 +1389,15 @@ static int pmc_core_probe(struct platform_device *pdev) return -ENOMEM; pmcdev->pmcs[PMC_IDX_MAIN] = primary_pmc; + /* The last element in msr_map is empty */ + pmcdev->num_of_pkgc = ARRAY_SIZE(msr_map) - 1; + pmcdev->pkgc_res_cnt = devm_kcalloc(&pdev->dev, + pmcdev->num_of_pkgc, + sizeof(*pmcdev->pkgc_res_cnt), + GFP_KERNEL); + if (!pmcdev->pkgc_res_cnt) + return -ENOMEM; + /* * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here * Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap @@ -1432,6 +1441,7 @@ static __maybe_unused int pmc_core_suspend(struct device *dev) { struct pmc_dev *pmcdev = dev_get_drvdata(dev); struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + unsigned int i; if (pmcdev->suspend) pmcdev->suspend(pmcdev); @@ -1440,9 +1450,11 @@ static __maybe_unused int pmc_core_suspend(struct device *dev) if (pm_suspend_via_firmware()) return 0; - /* Save PC10 residency for checking later */ - if (rdmsrl_safe(MSR_PKG_C10_RESIDENCY, &pmcdev->pc10_counter)) - return -EIO; + /* Save PKGC residency for checking later */ + for (i = 0; i < pmcdev->num_of_pkgc; i++) { + if (rdmsrl_safe(msr_map[i].bit_mask, &pmcdev->pkgc_res_cnt[i])) + return -EIO; + } /* Save S0ix residency for checking later */ if (pmc_core_dev_state_get(pmc, &pmcdev->s0ix_counter)) @@ -1451,14 +1463,15 @@ static __maybe_unused int pmc_core_suspend(struct device *dev) return 0; } -static inline bool pmc_core_is_pc10_failed(struct pmc_dev *pmcdev) +static inline bool pmc_core_is_deepest_pkgc_failed(struct pmc_dev *pmcdev) { - u64 pc10_counter; + u32 deepest_pkgc_msr = msr_map[pmcdev->num_of_pkgc - 1].bit_mask; + u64 deepest_pkgc_residency; - if (rdmsrl_safe(MSR_PKG_C10_RESIDENCY, &pc10_counter)) + if (rdmsrl_safe(deepest_pkgc_msr, &deepest_pkgc_residency)) return false; - if (pc10_counter == pmcdev->pc10_counter) + if (deepest_pkgc_residency == pmcdev->pkgc_res_cnt[pmcdev->num_of_pkgc - 1]) return true; return false; @@ -1497,10 +1510,22 @@ int pmc_core_resume_common(struct pmc_dev *pmcdev) if (!warn_on_s0ix_failures) return 0; - if (pmc_core_is_pc10_failed(pmcdev)) { - /* S0ix failed because of PC10 entry failure */ - dev_info(dev, "CPU did not enter PC10!!! (PC10 cnt=0x%llx)\n", - pmcdev->pc10_counter); + if (pmc_core_is_deepest_pkgc_failed(pmcdev)) { + /* S0ix failed because of deepest PKGC entry failure */ + dev_info(dev, "CPU did not enter %s!!! (%s cnt=0x%llx)\n", + msr_map[pmcdev->num_of_pkgc - 1].name, + msr_map[pmcdev->num_of_pkgc - 1].name, + pmcdev->pkgc_res_cnt[pmcdev->num_of_pkgc - 1]); + + for (i = 0; i < pmcdev->num_of_pkgc; i++) { + u64 pc_cnt; + + if (!rdmsrl_safe(msr_map[i].bit_mask, &pc_cnt)) { + dev_info(dev, "Prev %s cnt = 0x%llx, Current %s cnt = 0x%llx\n", + msr_map[i].name, pmcdev->pkgc_res_cnt[i], + msr_map[i].name, pc_cnt); + } + } return 0; } diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index 54137faaae2b..83504c49a0e3 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -385,7 +385,8 @@ struct pmc { * @pmc_xram_read_bit: flag to indicate whether PMC XRAM shadow registers * used to read MPHY PG and PLL status are available * @mutex_lock: mutex to complete one transcation - * @pc10_counter: PC10 residency counter + * @pkgc_res_cnt: Array of PKGC residency counters + * @num_of_pkgc: Number of PKGC * @s0ix_counter: S0ix residency (step adjusted) * @num_lpm_modes: Count of enabled modes * @lpm_en_modes: Array of enabled modes from lowest to highest priority @@ -403,13 +404,15 @@ struct pmc_dev { int pmc_xram_read_bit; struct mutex lock; /* generic mutex lock for PMC Core */ - u64 pc10_counter; u64 s0ix_counter; int num_lpm_modes; int lpm_en_modes[LPM_MAX_NUM_MODES]; void (*suspend)(struct pmc_dev *pmcdev); int (*resume)(struct pmc_dev *pmcdev); + u64 *pkgc_res_cnt; + u8 num_of_pkgc; + bool has_die_c6; u32 die_c6_offset; struct telem_endpoint *punit_ep; diff --git a/drivers/platform/x86/intel/pmc/lnl.c b/drivers/platform/x86/intel/pmc/lnl.c index abad17cdd3d7..068d72504683 100644 --- a/drivers/platform/x86/intel/pmc/lnl.c +++ b/drivers/platform/x86/intel/pmc/lnl.c @@ -13,21 +13,6 @@ #include "core.h" -#define SOCM_LPM_REQ_GUID 0x11594920 - -#define PMC_DEVID_SOCM 0xa87f - -static const u8 LNL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20}; - -static struct pmc_info lnl_pmc_info_list[] = { - { - .guid = SOCM_LPM_REQ_GUID, - .devid = PMC_DEVID_SOCM, - .map = &lnl_socm_reg_map, - }, - {} -}; - const struct pmc_bit_map lnl_ltr_show_map[] = { {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, @@ -490,7 +475,6 @@ const struct pmc_reg_map lnl_socm_reg_map = { .lpm_sts = lnl_lpm_maps, .lpm_status_offset = MTL_LPM_STATUS_OFFSET, .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, - .lpm_reg_index = LNL_LPM_REG_INDEX, }; #define LNL_NPU_PCI_DEV 0x643e @@ -517,33 +501,19 @@ static int lnl_resume(struct pmc_dev *pmcdev) int lnl_core_init(struct pmc_dev *pmcdev) { int ret; - int func = 2; - bool ssram_init = true; struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC]; lnl_d3_fixup(); pmcdev->suspend = cnl_suspend; pmcdev->resume = lnl_resume; - pmcdev->regmap_list = lnl_pmc_info_list; - ret = pmc_core_ssram_init(pmcdev, func); - - /* If regbase not assigned, set map and discover using legacy method */ - if (ret) { - ssram_init = false; - pmc->map = &lnl_socm_reg_map; - ret = get_primary_reg_base(pmc); - if (ret) - return ret; - } - pmc_core_get_low_power_modes(pmcdev); + pmc->map = &lnl_socm_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; - if (ssram_init) { - ret = pmc_core_ssram_get_lpm_reqs(pmcdev); - if (ret) - return ret; - } + pmc_core_get_low_power_modes(pmcdev); return 0; } diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c index 2662fbbddf0c..1d918000d72b 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c @@ -462,10 +462,10 @@ static long isst_if_core_power_state(void __user *argp) struct tpmi_per_power_domain_info *power_domain_info; struct isst_core_power core_power; - if (disable_dynamic_sst_features()) + if (copy_from_user(&core_power, argp, sizeof(core_power))) return -EFAULT; - if (copy_from_user(&core_power, argp, sizeof(core_power))) + if (core_power.get_set && disable_dynamic_sst_features()) return -EFAULT; power_domain_info = get_instance(core_power.socket_id, core_power.power_domain_id); diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c index e73cdea67fff..910df7c654f4 100644 --- a/drivers/platform/x86/intel/tpmi.c +++ b/drivers/platform/x86/intel/tpmi.c @@ -96,7 +96,7 @@ struct intel_tpmi_pfs_entry { */ struct intel_tpmi_pm_feature { struct intel_tpmi_pfs_entry pfs_header; - unsigned int vsec_offset; + u64 vsec_offset; struct intel_vsec_device *vsec_dev; }; @@ -376,7 +376,7 @@ static int tpmi_pfs_dbg_show(struct seq_file *s, void *unused) read_blocked = feature_state.read_blocked ? 'Y' : 'N'; write_blocked = feature_state.write_blocked ? 'Y' : 'N'; } - seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%08x\t%c\t%c\t\t%c\t\t%c\n", + seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%016llx\t%c\t%c\t\t%c\t\t%c\n", pfs->pfs_header.tpmi_id, pfs->pfs_header.num_entries, pfs->pfs_header.entry_size, pfs->pfs_header.cap_offset, pfs->pfs_header.attribute, pfs->vsec_offset, locked, disabled, @@ -395,7 +395,8 @@ static int tpmi_mem_dump_show(struct seq_file *s, void *unused) struct intel_tpmi_pm_feature *pfs = s->private; int count, ret = 0; void __iomem *mem; - u32 off, size; + u32 size; + u64 off; u8 *buffer; size = TPMI_GET_SINGLE_ENTRY_SIZE(pfs); @@ -411,7 +412,7 @@ static int tpmi_mem_dump_show(struct seq_file *s, void *unused) mutex_lock(&tpmi_dev_lock); for (count = 0; count < pfs->pfs_header.num_entries; ++count) { - seq_printf(s, "TPMI Instance:%d offset:0x%x\n", count, off); + seq_printf(s, "TPMI Instance:%d offset:0x%llx\n", count, off); mem = ioremap(off, size); if (!mem) { diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c index 778eb0aa3479..0fdfaf3a4f5c 100644 --- a/drivers/platform/x86/intel/vsec.c +++ b/drivers/platform/x86/intel/vsec.c @@ -236,10 +236,7 @@ static bool intel_vsec_walk_header(struct pci_dev *pdev, for ( ; *header; header++) { ret = intel_vsec_add_dev(pdev, *header, info); - if (ret) - dev_info(&pdev->dev, "Could not add device for VSEC id %d\n", - (*header)->id); - else + if (!ret) have_devices = true; } diff --git a/drivers/platform/x86/intel/wmi/sbl-fw-update.c b/drivers/platform/x86/intel/wmi/sbl-fw-update.c index 040153ad67c1..75c82c08117f 100644 --- a/drivers/platform/x86/intel/wmi/sbl-fw-update.c +++ b/drivers/platform/x86/intel/wmi/sbl-fw-update.c @@ -131,6 +131,7 @@ static struct wmi_driver intel_wmi_sbl_fw_update_driver = { .probe = intel_wmi_sbl_fw_update_probe, .remove = intel_wmi_sbl_fw_update_remove, .id_table = intel_wmi_sbl_id_table, + .no_singleton = true, }; module_wmi_driver(intel_wmi_sbl_fw_update_driver); diff --git a/drivers/platform/x86/intel/wmi/thunderbolt.c b/drivers/platform/x86/intel/wmi/thunderbolt.c index e2ad3f46f356..08df560a2c7a 100644 --- a/drivers/platform/x86/intel/wmi/thunderbolt.c +++ b/drivers/platform/x86/intel/wmi/thunderbolt.c @@ -63,6 +63,7 @@ static struct wmi_driver intel_wmi_thunderbolt_driver = { .dev_groups = tbt_groups, }, .id_table = intel_wmi_thunderbolt_id_table, + .no_singleton = true, }; module_wmi_driver(intel_wmi_thunderbolt_driver); |