diff options
Diffstat (limited to 'drivers/platform')
21 files changed, 310 insertions, 150 deletions
diff --git a/drivers/platform/x86/amd/pmc/pmc-quirks.c b/drivers/platform/x86/amd/pmc/pmc-quirks.c index 24506e342943..74ddf1d8289a 100644 --- a/drivers/platform/x86/amd/pmc/pmc-quirks.c +++ b/drivers/platform/x86/amd/pmc/pmc-quirks.c @@ -18,6 +18,7 @@ struct quirk_entry { u32 s2idle_bug_mmio; bool spurious_8042; + bool need_suspend_delay; }; static struct quirk_entry quirk_s2idle_bug = { @@ -33,6 +34,10 @@ static struct quirk_entry quirk_s2idle_spurious_8042 = { .spurious_8042 = true, }; +static struct quirk_entry quirk_s2idle_need_suspend_delay = { + .need_suspend_delay = true, +}; + static const struct dmi_system_id fwbug_list[] = { { .ident = "L14 Gen2 AMD", @@ -203,6 +208,35 @@ static const struct dmi_system_id fwbug_list[] = { DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"), } }, + /* https://bugzilla.kernel.org/show_bug.cgi?id=221383 */ + { + .ident = "Zen3-based IdeaPad Slim and similar", + .driver_data = &quirk_s2idle_need_suspend_delay, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + /* + * Note: there are also some Zen2-based 82X* devices that + * need different quirks, they're already handled above + */ + DMI_MATCH(DMI_PRODUCT_NAME, "82X"), + } + }, + { + .ident = "Zen3+-based IdeaPad Slim and similar", + .driver_data = &quirk_s2idle_need_suspend_delay, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83K"), + } + }, + { + .ident = "IdeaPad Slim 3 15ARP10 (83MM)", + .driver_data = &quirk_s2idle_need_suspend_delay, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83MM"), + } + }, /* https://bugzilla.kernel.org/show_bug.cgi?id=221273 */ { .ident = "Thinkpad L14 Gen3", @@ -356,6 +390,11 @@ void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev) amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio); } +bool amd_pmc_quirk_need_suspend_delay(struct amd_pmc_dev *dev) +{ + return dev->quirks && dev->quirks->need_suspend_delay; +} + void amd_pmc_quirks_init(struct amd_pmc_dev *dev) { const struct dmi_system_id *dmi_id; diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c index cae3fcafd4d7..2cd77a44c7e7 100644 --- a/drivers/platform/x86/amd/pmc/pmc.c +++ b/drivers/platform/x86/amd/pmc/pmc.c @@ -16,6 +16,7 @@ #include <linux/bits.h> #include <linux/debugfs.h> #include <linux/delay.h> +#include <linux/dmi.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/limits.h> @@ -89,6 +90,11 @@ static bool disable_workarounds; module_param(disable_workarounds, bool, 0644); MODULE_PARM_DESC(disable_workarounds, "Disable workarounds for platform bugs"); +static int delay_suspend = -1; +module_param(delay_suspend, int, 0644); +MODULE_PARM_DESC(delay_suspend, + "Delays s2idle by 2.5 seconds to work around buggy ECs, often causing keyboard issues after suspend. 0: don't delay, 1: do delay, -1 (default): let amd_pmc decide. If you need this please report this to: platform-driver-x86@vger.kernel.org"); + static struct amd_pmc_dev pmc; static inline u32 amd_pmc_reg_read(struct amd_pmc_dev *dev, int reg_offset) @@ -598,6 +604,72 @@ static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg) return rc; } +static bool amd_pmc_intermediate_wakeup_need_delay(struct amd_pmc_dev *pdev) +{ + /* + * Starting a new HW sleep cycle right after waking from one + * can cause electrical problems triggering the over voltage protection. + * That is avoided by delaying the next suspend a bit, see also + * https://lore.kernel.org/all/20250414162446.3853194-1-superm1@kernel.org/ + */ + struct smu_metrics table; + + return get_metrics_table(pdev, &table) == 0 && table.s0i3_last_entry_status; +} + +static bool amd_pmc_want_suspend_delay(struct amd_pmc_dev *pdev) +{ + /* + * intermediate_wakeup implies that the machine didn't get to deepest sleep + * state before - otherwise this function isn't called in amd_pmc_s2idle_check() + * because amd_pmc_intermediate_wakeup_need_delay() returns true first. + * On some IdeaPads that happens when charging, because the EC seems + * to send lots of messages then that wake the machine. + * + * But even in that case, the sleep here is necessary (on those IdeaPads), + * otherwise they wake up completely (resume) after a few seconds. + * So this variable is only used to avoid spamming dmesg on each + * intermediate wakeup. + */ + bool intermediate_wakeup = !pdev->is_first_check_after_suspend; + + /* + * Some Lenovo Laptops (like different IdeaPad 3 Slims) need some + * me-time before sleeping or they get uncooperative after waking + * up and don't send events for keyboard and lid switch anymore. + * + * Unfortunately this doesn't entirely fix the problem: It can still + * happen when resuming with a timer (wakealarm), but at least the + * more common usecases (wakeup by opening lid or pressing a key) + * work fine with this workaround. + * + * See https://bugzilla.kernel.org/show_bug.cgi?id=221383 + */ + if (amd_pmc_quirk_need_suspend_delay(pdev)) { + /* + * delay_suspend=1 force-enables this, otherwise it can be + * disabled with disable_workarounds or delay_suspend=0 + */ + if (delay_suspend == 1 || (delay_suspend == -1 && !disable_workarounds)) { + if (!intermediate_wakeup) + dev_info(pdev->dev, "Delaying suspend by 2.5s to avoid platform bug\n"); + return true; + } + if (!intermediate_wakeup) + dev_info(pdev->dev, "Not delaying suspend because of module parameter, even though your device is assumed to need it!\n"); + } else if (delay_suspend == 1) { + if (!intermediate_wakeup) + dev_info(pdev->dev, "Delaying suspend by 2.5s because delay_suspend=1. If this solves problems on your machine, please report this whole line to: platform-driver-x86@vger.kernel.org so it can be automatically detected as affected in the future. System Vendor: \"%s\" Product Name: \"%s\" Product Family: \"%s\" Board Vendor: \"%s\" Board Name: \"%s\"\n", + dmi_get_system_info(DMI_SYS_VENDOR) ?: "(Unknown)", + dmi_get_system_info(DMI_PRODUCT_NAME) ?: "(Unknown)", + dmi_get_system_info(DMI_PRODUCT_FAMILY) ?: "(Unknown)", + dmi_get_system_info(DMI_BOARD_VENDOR) ?: "(Unknown)", + dmi_get_system_info(DMI_BOARD_NAME) ?: "(Unknown)"); + return true; + } + return false; +} + static void amd_pmc_s2idle_prepare(void) { struct amd_pmc_dev *pdev = &pmc; @@ -605,6 +677,9 @@ static void amd_pmc_s2idle_prepare(void) u8 msg; u32 arg = 1; + /* Reset this variable because this is a fresh suspend */ + pdev->is_first_check_after_suspend = true; + /* Reset and Start SMU logging - to monitor the s0i3 stats */ amd_pmc_setup_smu_logging(pdev); @@ -632,11 +707,10 @@ static void amd_pmc_s2idle_prepare(void) static void amd_pmc_s2idle_check(void) { struct amd_pmc_dev *pdev = &pmc; - struct smu_metrics table; int rc; - /* Avoid triggering OVP */ - if (!get_metrics_table(pdev, &table) && table.s0i3_last_entry_status) + if (amd_pmc_intermediate_wakeup_need_delay(pdev) || + amd_pmc_want_suspend_delay(pdev)) msleep(2500); /* Dump the IdleMask before we add to the STB */ @@ -645,6 +719,9 @@ static void amd_pmc_s2idle_check(void) rc = amd_stb_write(pdev, AMD_PMC_STB_S2IDLE_CHECK); if (rc) dev_err(pdev->dev, "error writing to STB: %d\n", rc); + + /* remember that first check after suspend is done (until next prepare) */ + pdev->is_first_check_after_suspend = false; } static int amd_pmc_dump_data(struct amd_pmc_dev *pdev) diff --git a/drivers/platform/x86/amd/pmc/pmc.h b/drivers/platform/x86/amd/pmc/pmc.h index fe3f53eb5955..8aa7073ed09f 100644 --- a/drivers/platform/x86/amd/pmc/pmc.h +++ b/drivers/platform/x86/amd/pmc/pmc.h @@ -114,6 +114,7 @@ struct amd_pmc_dev { struct dentry *dbgfs_dir; struct quirk_entry *quirks; bool disable_8042_wakeup; + bool is_first_check_after_suspend; struct amd_mp2_dev *mp2; struct stb_arg stb_arg; }; @@ -147,6 +148,7 @@ enum amd_pmc_def { }; void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev); +bool amd_pmc_quirk_need_suspend_delay(struct amd_pmc_dev *dev); void amd_pmc_quirks_init(struct amd_pmc_dev *dev); void amd_mp2_stb_init(struct amd_pmc_dev *dev); void amd_mp2_stb_deinit(struct amd_pmc_dev *dev); diff --git a/drivers/platform/x86/dell/dell-laptop.c b/drivers/platform/x86/dell/dell-laptop.c index 57748c3ea24f..053f40572bf6 100644 --- a/drivers/platform/x86/dell/dell-laptop.c +++ b/drivers/platform/x86/dell/dell-laptop.c @@ -2551,7 +2551,12 @@ fail_backlight: if (mute_led_registered) led_classdev_unregister(&mute_led_cdev); fail_led: + dell_laptop_unregister_notifier(&dell_laptop_notifier); + debugfs_remove_recursive(dell_laptop_dir); dell_battery_exit(); + kbd_led_exit(); + if (quirks && quirks->touchpad_led) + touchpad_led_exit(); dell_cleanup_rfkill(); fail_rfkill: platform_device_del(platform_device); diff --git a/drivers/platform/x86/intel/pmc/arl.c b/drivers/platform/x86/intel/pmc/arl.c index 17ad87b392ab..7a802b799e0a 100644 --- a/drivers/platform/x86/intel/pmc/arl.c +++ b/drivers/platform/x86/intel/pmc/arl.c @@ -281,6 +281,7 @@ static const struct pmc_reg_map arl_socs_reg_map = { .etr3_offset = ETR3_OFFSET, .pson_residency_offset = TGL_PSON_RESIDENCY_OFFSET, .pson_residency_counter_step = TGL_PSON_RES_COUNTER_STEP, + .lpm_req_guid = SOCS_LPM_REQ_GUID, }; static const struct pmc_bit_map arl_pchs_ltr_show_map[] = { @@ -648,26 +649,23 @@ static const struct pmc_reg_map arl_pchs_reg_map = { .lpm_num_maps = ADL_LPM_NUM_MAPS, .lpm_reg_index = ARL_LPM_REG_INDEX, .etr3_offset = ETR3_OFFSET, + .lpm_req_guid = PCHS_LPM_REQ_GUID, }; static struct pmc_info arl_pmc_info_list[] = { { - .guid = IOEP_LPM_REQ_GUID, .devid = PMC_DEVID_ARL_IOEP, .map = &mtl_ioep_reg_map, }, { - .guid = SOCS_LPM_REQ_GUID, .devid = PMC_DEVID_ARL_SOCS, .map = &arl_socs_reg_map, }, { - .guid = PCHS_LPM_REQ_GUID, .devid = PMC_DEVID_ARL_PCHS, .map = &arl_pchs_reg_map, }, { - .guid = SOCM_LPM_REQ_GUID, .devid = PMC_DEVID_ARL_SOCM, .map = &mtl_socm_reg_map, }, @@ -720,9 +718,10 @@ static int arl_h_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_ return generic_core_init(pmcdev, pmc_dev_info); } +static u32 ARL_PMT_DMU_GUIDS[] = {ARL_PMT_DMU_GUID, 0x0}; struct pmc_dev_info arl_pmc_dev = { .pci_func = 0, - .dmu_guid = ARL_PMT_DMU_GUID, + .dmu_guids = ARL_PMT_DMU_GUIDS, .regmap_list = arl_pmc_info_list, .map = &arl_socs_reg_map, .sub_req_show = &pmc_core_substate_req_regs_fops, @@ -732,9 +731,10 @@ struct pmc_dev_info arl_pmc_dev = { .sub_req = pmc_core_pmt_get_lpm_req, }; +static u32 ARL_H_PMT_DMU_GUIDS[] = {ARL_PMT_DMU_GUID, 0x0}; struct pmc_dev_info arl_h_pmc_dev = { .pci_func = 2, - .dmu_guid = ARL_PMT_DMU_GUID, + .dmu_guids = ARL_H_PMT_DMU_GUIDS, .regmap_list = arl_pmc_info_list, .map = &mtl_socm_reg_map, .sub_req_show = &pmc_core_substate_req_regs_fops, diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index ac3d19ae8c56..ef712f3bc7ae 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -20,6 +20,7 @@ enum header_type { #include <linux/debugfs.h> #include <linux/delay.h> #include <linux/dmi.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/pci.h> @@ -311,20 +312,20 @@ static inline u8 pmc_core_reg_read_byte(struct pmc *pmc, int offset) } static void pmc_core_display_map(struct seq_file *s, int index, int idx, int ip, - int pmc_index, u8 pf_reg, const struct pmc_bit_map **pf_map) + int pmc_idx, u8 pf_reg, const struct pmc_bit_map **pf_map) { seq_printf(s, "PMC%d:PCH IP: %-2d - %-32s\tState: %s\n", - pmc_index, ip, pf_map[idx][index].name, + pmc_idx, ip, pf_map[idx][index].name, pf_map[idx][index].bit_mask & pf_reg ? "Off" : "On"); } static int pmc_core_ppfear_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - unsigned int i; + unsigned int pmc_idx; - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { - struct pmc *pmc = pmcdev->pmcs[i]; + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + struct pmc *pmc = pmcdev->pmcs[pmc_idx]; const struct pmc_bit_map **maps; u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; unsigned int index, iter, idx, ip = 0; @@ -342,7 +343,7 @@ static int pmc_core_ppfear_show(struct seq_file *s, void *unused) for (idx = 0; maps[idx]; idx++) { for (index = 0; maps[idx][index].name && index < pmc->map->ppfear_buckets * 8; ip++, index++) - pmc_core_display_map(s, index, idx, ip, i, + pmc_core_display_map(s, index, idx, ip, pmc_idx, pf_regs[index / 8], maps); } } @@ -471,7 +472,7 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore) struct pmc *pmc; const struct pmc_reg_map *map; u32 reg; - unsigned int pmc_index; + unsigned int pmc_idx; int ltr_index; ltr_index = value; @@ -479,8 +480,8 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore) * is based on the contiguous indexes from ltr_show output. * pmc index and ltr index needs to be calculated from it. */ - for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs) && ltr_index >= 0; pmc_index++) { - pmc = pmcdev->pmcs[pmc_index]; + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs) && ltr_index >= 0; pmc_idx++) { + pmc = pmcdev->pmcs[pmc_idx]; if (!pmc) continue; @@ -497,10 +498,10 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore) ltr_index = ltr_index - (map->ltr_ignore_max + 2) - 1; } - if (pmc_index >= ARRAY_SIZE(pmcdev->pmcs) || ltr_index < 0) + if (pmc_idx >= ARRAY_SIZE(pmcdev->pmcs) || ltr_index < 0) return -EINVAL; - pr_debug("ltr_ignore for pmc%d: ltr_index:%d\n", pmc_index, ltr_index); + pr_debug("ltr_ignore for pmc%d: ltr_index:%d\n", pmc_idx, ltr_index); guard(mutex)(&pmcdev->lock); @@ -635,14 +636,14 @@ static int pmc_core_ltr_show(struct seq_file *s, void *unused) u64 decoded_snoop_ltr, decoded_non_snoop_ltr, val; u32 ltr_raw_data, scale; u16 snoop_ltr, nonsnoop_ltr; - unsigned int i, index, ltr_index = 0; + unsigned int pmc_idx, index, ltr_index = 0; - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { struct pmc *pmc; const struct pmc_bit_map *map; u32 ltr_ign_reg; - pmc = pmcdev->pmcs[i]; + pmc = pmcdev->pmcs[pmc_idx]; if (!pmc) continue; @@ -676,7 +677,7 @@ static int pmc_core_ltr_show(struct seq_file *s, void *unused) } seq_printf(s, "%d\tPMC%d:%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\tLTR_IGNORE: %d\n", - ltr_index, i, map[index].name, ltr_raw_data, + ltr_index, pmc_idx, map[index].name, ltr_raw_data, decoded_non_snoop_ltr, decoded_snoop_ltr, ltr_ign_data); ltr_index++; @@ -689,15 +690,15 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); static int pmc_core_s0ix_blocker_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - unsigned int pmcidx; + unsigned int pmc_idx; - for (pmcidx = 0; pmcidx < ARRAY_SIZE(pmcdev->pmcs); pmcidx++) { + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); pmc_idx++) { const struct pmc_bit_map **maps; unsigned int arr_size, r_idx; u32 offset, counter; struct pmc *pmc; - pmc = pmcdev->pmcs[pmcidx]; + pmc = pmcdev->pmcs[pmc_idx]; if (!pmc) continue; maps = pmc->map->s0ix_blocker_maps; @@ -711,7 +712,7 @@ static int pmc_core_s0ix_blocker_show(struct seq_file *s, void *unused) if (!map->blk) continue; counter = pmc_core_reg_read(pmc, offset); - seq_printf(s, "PMC%d:%-30s %-30d\n", pmcidx, + seq_printf(s, "PMC%d:%-30s %-30d\n", pmc_idx, map->name, counter); offset += map->blk * S0IX_BLK_SIZE; } @@ -723,13 +724,13 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_s0ix_blocker); static void pmc_core_ltr_ignore_all(struct pmc_dev *pmcdev) { - unsigned int i; + unsigned int pmc_idx; - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); i++) { + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); pmc_idx++) { struct pmc *pmc; u32 ltr_ign; - pmc = pmcdev->pmcs[i]; + pmc = pmcdev->pmcs[pmc_idx]; if (!pmc) continue; @@ -750,12 +751,12 @@ static void pmc_core_ltr_ignore_all(struct pmc_dev *pmcdev) static void pmc_core_ltr_restore_all(struct pmc_dev *pmcdev) { - unsigned int i; + unsigned int pmc_idx; - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); i++) { + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); pmc_idx++) { struct pmc *pmc; - pmc = pmcdev->pmcs[i]; + pmc = pmcdev->pmcs[pmc_idx]; if (!pmc) continue; @@ -794,10 +795,10 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_res); static int pmc_core_substate_sts_regs_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - unsigned int i; + unsigned int pmc_idx; - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { - struct pmc *pmc = pmcdev->pmcs[i]; + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + struct pmc *pmc = pmcdev->pmcs[pmc_idx]; const struct pmc_bit_map **maps; u32 offset; @@ -805,7 +806,7 @@ static int pmc_core_substate_sts_regs_show(struct seq_file *s, void *unused) continue; maps = pmc->map->lpm_sts; offset = pmc->map->lpm_status_offset; - pmc_core_lpm_display(pmc, NULL, s, offset, i, "STATUS", maps); + pmc_core_lpm_display(pmc, NULL, s, offset, pmc_idx, "STATUS", maps); } return 0; @@ -815,10 +816,10 @@ DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_sts_regs); static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - unsigned int i; + unsigned int pmc_idx; - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { - struct pmc *pmc = pmcdev->pmcs[i]; + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + struct pmc *pmc = pmcdev->pmcs[pmc_idx]; const struct pmc_bit_map **maps; u32 offset; @@ -826,7 +827,7 @@ static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused) continue; maps = pmc->map->lpm_sts; offset = pmc->map->lpm_live_status_offset; - pmc_core_lpm_display(pmc, NULL, s, offset, i, "LIVE_STATUS", maps); + pmc_core_lpm_display(pmc, NULL, s, offset, pmc_idx, "LIVE_STATUS", maps); } return 0; @@ -919,11 +920,11 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) u32 sts_offset; u32 sts_offset_live; u32 *lpm_req_regs; - unsigned int mp, pmc_index; + unsigned int mp, pmc_idx; int num_maps; - for (pmc_index = 0; pmc_index < ARRAY_SIZE(pmcdev->pmcs); ++pmc_index) { - struct pmc *pmc = pmcdev->pmcs[pmc_index]; + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + struct pmc *pmc = pmcdev->pmcs[pmc_idx]; const struct pmc_bit_map **maps; if (!pmc) @@ -944,7 +945,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) continue; /* Display the header */ - pmc_core_substate_req_header_show(s, pmc_index, HEADER_STATUS); + pmc_core_substate_req_header_show(s, pmc_idx, HEADER_STATUS); /* Loop over maps */ for (mp = 0; mp < num_maps; mp++) { @@ -982,7 +983,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) } /* Display the element name in the first column */ - seq_printf(s, "pmc%d: %34s |", pmc_index, map[i].name); + seq_printf(s, "pmc%d: %34s |", pmc_idx, map[i].name); /* Loop over the enabled states and display if required */ pmc_for_each_mode(mode, pmcdev) { @@ -1281,7 +1282,20 @@ int get_primary_reg_base(struct pmc *pmc) return 0; } -void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid) +static struct telem_endpoint *pmc_core_register_endpoint(struct pci_dev *pcidev, u32 *guids) +{ + struct telem_endpoint *ep; + unsigned int i; + + for (i = 0; guids[i]; i++) { + ep = pmt_telem_find_and_register_endpoint(&pcidev->dev, guids[i], 0); + if (!IS_ERR(ep)) + return ep; + } + return ERR_PTR(-ENODEV); +} + +void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids) { struct telem_endpoint *ep; struct pci_dev *pcidev; @@ -1292,7 +1306,7 @@ void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid) return; } - ep = pmt_telem_find_and_register_endpoint(pcidev, guid, 0); + ep = pmc_core_register_endpoint(pcidev, guids); pci_dev_put(pcidev); if (IS_ERR(ep)) { dev_err(&pmcdev->pdev->dev, @@ -1430,15 +1444,6 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev, struct pmc_dev_info } } -static u32 pmc_core_find_guid(struct pmc_info *list, const struct pmc_reg_map *map) -{ - for (; list->map; ++list) - if (list->map == map) - return list->guid; - - return 0; -} - /* * This function retrieves low power mode requirement data from PMC Low * Power Mode (LPM) table. @@ -1553,26 +1558,24 @@ static int pmc_core_get_telem_info(struct pmc_dev *pmcdev, struct pmc_dev_info * { struct pci_dev *pcidev __free(pci_dev_put) = NULL; struct telem_endpoint *ep; - unsigned int i; - u32 guid; + unsigned int pmc_idx; int ret; pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, pmc_dev_info->pci_func)); if (!pcidev) return -ENODEV; - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { struct pmc *pmc; - pmc = pmcdev->pmcs[i]; + pmc = pmcdev->pmcs[pmc_idx]; if (!pmc) continue; - guid = pmc_core_find_guid(pmcdev->regmap_list, pmc->map); - if (!guid) + if (!pmc->map->lpm_req_guid) return -ENXIO; - ep = pmt_telem_find_and_register_endpoint(pcidev, guid, 0); + ep = pmt_telem_find_and_register_endpoint(&pcidev->dev, pmc->map->lpm_req_guid, 0); if (IS_ERR(ep)) { dev_dbg(&pmcdev->pdev->dev, "couldn't get telem endpoint %pe", ep); return -EPROBE_DEFER; @@ -1596,7 +1599,7 @@ static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 return NULL; } -static int pmc_core_pmc_add(struct pmc_dev *pmcdev, unsigned int pmc_index) +static int pmc_core_pmc_add(struct pmc_dev *pmcdev, unsigned int pmc_idx) { struct pmc_ssram_telemetry pmc_ssram_telemetry; @@ -1604,7 +1607,7 @@ static int pmc_core_pmc_add(struct pmc_dev *pmcdev, unsigned int pmc_index) struct pmc *pmc; int ret; - ret = pmc_ssram_telemetry_get_pmc_info(pmc_index, &pmc_ssram_telemetry); + ret = pmc_ssram_telemetry_get_pmc_info(pmc_idx, &pmc_ssram_telemetry); if (ret) return ret; @@ -1612,7 +1615,7 @@ static int pmc_core_pmc_add(struct pmc_dev *pmcdev, unsigned int pmc_index) if (!map) return -ENODEV; - pmc = pmcdev->pmcs[pmc_index]; + pmc = pmcdev->pmcs[pmc_idx]; /* Memory for primary PMC has been allocated */ if (!pmc) { pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL); @@ -1629,7 +1632,7 @@ static int pmc_core_pmc_add(struct pmc_dev *pmcdev, unsigned int pmc_index) return -ENOMEM; } - pmcdev->pmcs[pmc_index] = pmc; + pmcdev->pmcs[pmc_idx] = pmc; return 0; } @@ -1689,8 +1692,8 @@ int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) } pmc_core_get_low_power_modes(pmcdev); - if (pmc_dev_info->dmu_guid) - pmc_core_punit_pmt_init(pmcdev, pmc_dev_info->dmu_guid); + if (pmc_dev_info->dmu_guids) + pmc_core_punit_pmt_init(pmcdev, pmc_dev_info->dmu_guids); if (ssram) { ret = pmc_core_get_telem_info(pmcdev, pmc_dev_info); @@ -1701,8 +1704,8 @@ int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) return 0; unmap_regbase: - for (unsigned int i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { - struct pmc *pmc = pmcdev->pmcs[i]; + for (unsigned int pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + struct pmc *pmc = pmcdev->pmcs[pmc_idx]; if (pmc && pmc->regbase) iounmap(pmc->regbase); @@ -1795,10 +1798,10 @@ static void pmc_core_do_dmi_quirks(struct pmc *pmc) static void pmc_core_clean_structure(struct platform_device *pdev) { struct pmc_dev *pmcdev = platform_get_drvdata(pdev); - unsigned int i; + unsigned int pmc_idx; - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { - struct pmc *pmc = pmcdev->pmcs[i]; + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + struct pmc *pmc = pmcdev->pmcs[pmc_idx]; if (pmc && pmc->regbase) iounmap(pmc->regbase); @@ -1958,7 +1961,7 @@ int pmc_core_resume_common(struct pmc_dev *pmcdev) struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; const struct pmc_bit_map **maps = pmc->map->lpm_sts; int offset = pmc->map->lpm_status_offset; - unsigned int i; + unsigned int pmc_idx, i; /* Check if the syspend used S0ix */ if (pm_suspend_via_firmware()) @@ -1996,13 +1999,13 @@ int pmc_core_resume_common(struct pmc_dev *pmcdev) if (pmc->map->slps0_dbg_maps) pmc_core_slps0_display(pmc, dev, NULL); - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { - struct pmc *pmc = pmcdev->pmcs[i]; + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); ++pmc_idx) { + struct pmc *pmc = pmcdev->pmcs[pmc_idx]; if (!pmc) continue; if (pmc->map->lpm_sts) - pmc_core_lpm_display(pmc, dev, NULL, offset, i, "STATUS", maps); + pmc_core_lpm_display(pmc, dev, NULL, offset, pmc_idx, "STATUS", maps); } return 0; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index d6818bd34768..7d2ad88324b8 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -355,6 +355,7 @@ struct pmc_bit_map { * @s0ix_blocker_offset PWRMBASE offset to S0ix blocker counter * @num_s0ix_blocker: Number of S0ix blockers * @blocker_req_offset: Telemetry offset to S0ix blocker low power mode substate requirement table + * @lpm_req_guid: Telemetry GUID to read low power mode substate requirement table * * Each PCH has unique set of register offsets and bit indexes. This structure * captures them to have a common implementation. @@ -396,6 +397,8 @@ struct pmc_reg_map { const u8 *lpm_reg_index; const u32 pson_residency_offset; const u32 pson_residency_counter_step; + /* GUID for telemetry regions */ + const u32 lpm_req_guid; }; /** @@ -405,7 +408,6 @@ struct pmc_reg_map { * specific attributes */ struct pmc_info { - u32 guid; u16 devid; const struct pmc_reg_map *map; }; @@ -481,7 +483,7 @@ enum pmc_index { /** * struct pmc_dev_info - Structure to keep PMC device info * @pci_func: Function number of the primary PMC - * @dmu_guid: Die Management Unit GUID + * @dmu_guids: List of Die Management Unit GUID * @regmap_list: Pointer to a list of pmc_info structure that could be * available for the platform. When set, this field implies * SSRAM support. @@ -495,7 +497,7 @@ enum pmc_index { */ struct pmc_dev_info { u8 pci_func; - u32 dmu_guid; + u32 *dmu_guids; struct pmc_info *regmap_list; const struct pmc_reg_map *map; const struct file_operations *sub_req_show; @@ -532,7 +534,7 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); int pmc_core_resume_common(struct pmc_dev *pmcdev); int get_primary_reg_base(struct pmc *pmc); void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev); -void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid); +void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids); void pmc_core_set_device_d3(unsigned int device); int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info); diff --git a/drivers/platform/x86/intel/pmc/lnl.c b/drivers/platform/x86/intel/pmc/lnl.c index 6fa027e7071f..1cd81ee54dcf 100644 --- a/drivers/platform/x86/intel/pmc/lnl.c +++ b/drivers/platform/x86/intel/pmc/lnl.c @@ -533,11 +533,11 @@ static const struct pmc_reg_map lnl_socm_reg_map = { .s0ix_blocker_maps = lnl_blk_maps, .s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET, .lpm_reg_index = LNL_LPM_REG_INDEX, + .lpm_req_guid = SOCM_LPM_REQ_GUID, }; static struct pmc_info lnl_pmc_info_list[] = { { - .guid = SOCM_LPM_REQ_GUID, .devid = PMC_DEVID_LNL_SOCM, .map = &lnl_socm_reg_map, }, diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c index 0b87e10f864e..57508cbf9cd4 100644 --- a/drivers/platform/x86/intel/pmc/mtl.c +++ b/drivers/platform/x86/intel/pmc/mtl.c @@ -473,6 +473,7 @@ const struct pmc_reg_map mtl_socm_reg_map = { .lpm_status_offset = MTL_LPM_STATUS_OFFSET, .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, .lpm_reg_index = MTL_LPM_REG_INDEX, + .lpm_req_guid = SOCP_LPM_REQ_GUID, }; static const struct pmc_bit_map mtl_ioep_pfear_map[] = { @@ -797,6 +798,7 @@ const struct pmc_reg_map mtl_ioep_reg_map = { .lpm_en_offset = MTL_LPM_EN_OFFSET, .lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET, .lpm_reg_index = MTL_LPM_REG_INDEX, + .lpm_req_guid = IOEP_LPM_REQ_GUID, }; static const struct pmc_bit_map mtl_ioem_pfear_map[] = { @@ -944,21 +946,19 @@ static const struct pmc_reg_map mtl_ioem_reg_map = { .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, .lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET, .lpm_reg_index = MTL_LPM_REG_INDEX, + .lpm_req_guid = IOEM_LPM_REQ_GUID, }; static struct pmc_info mtl_pmc_info_list[] = { { - .guid = SOCP_LPM_REQ_GUID, .devid = PMC_DEVID_MTL_SOCM, .map = &mtl_socm_reg_map, }, { - .guid = IOEP_LPM_REQ_GUID, .devid = PMC_DEVID_MTL_IOEP, .map = &mtl_ioep_reg_map, }, { - .guid = IOEM_LPM_REQ_GUID, .devid = PMC_DEVID_MTL_IOEM, .map = &mtl_ioem_reg_map }, @@ -992,9 +992,10 @@ static int mtl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_in return generic_core_init(pmcdev, pmc_dev_info); } +static u32 MTL_PMT_DMU_GUIDS[] = {MTL_PMT_DMU_GUID, 0x0}; struct pmc_dev_info mtl_pmc_dev = { .pci_func = 2, - .dmu_guid = MTL_PMT_DMU_GUID, + .dmu_guids = MTL_PMT_DMU_GUIDS, .regmap_list = mtl_pmc_info_list, .map = &mtl_socm_reg_map, .sub_req_show = &pmc_core_substate_req_regs_fops, diff --git a/drivers/platform/x86/intel/pmc/ptl.c b/drivers/platform/x86/intel/pmc/ptl.c index 1b35b84e06fa..1f48e2bbc699 100644 --- a/drivers/platform/x86/intel/pmc/ptl.c +++ b/drivers/platform/x86/intel/pmc/ptl.c @@ -528,16 +528,15 @@ static const struct pmc_reg_map ptl_pcdp_reg_map = { .s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET, .num_s0ix_blocker = PTL_NUM_S0IX_BLOCKER, .blocker_req_offset = PTL_BLK_REQ_OFFSET, + .lpm_req_guid = PCDP_LPM_REQ_GUID, }; static struct pmc_info ptl_pmc_info_list[] = { { - .guid = PCDP_LPM_REQ_GUID, .devid = PMC_DEVID_PTL_PCDH, .map = &ptl_pcdp_reg_map, }, { - .guid = PCDP_LPM_REQ_GUID, .devid = PMC_DEVID_PTL_PCDP, .map = &ptl_pcdp_reg_map, }, diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c index 03fad9331fc0..6f6e83e70fc5 100644 --- a/drivers/platform/x86/intel/pmc/ssram_telemetry.c +++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c @@ -60,7 +60,7 @@ pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem info.base_addr = ssram_base; info.parent = &pcidev->dev; - return intel_vsec_register(pcidev, &info); + return intel_vsec_register(&pcidev->dev, &info); } static inline u64 get_base(void __iomem *addr, u32 offset) diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c index 7c3023d5d91d..8077274726b5 100644 --- a/drivers/platform/x86/intel/pmt/class.c +++ b/drivers/platform/x86/intel/pmt/class.c @@ -60,11 +60,11 @@ pmt_memcpy64_fromio(void *to, const u64 __iomem *from, size_t count) return count; } -int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf, +int pmt_telem_read_mmio(struct device *dev, struct pmt_callbacks *cb, u32 guid, void *buf, void __iomem *addr, loff_t off, u32 count) { if (cb && cb->read_telem) - return cb->read_telem(pdev, guid, buf, off, count); + return cb->read_telem(dev, guid, buf, off, count); addr += off; @@ -99,7 +99,7 @@ intel_pmt_read(struct file *filp, struct kobject *kobj, if (count > entry->size - off) count = entry->size - off; - count = pmt_telem_read_mmio(entry->pcidev, entry->cb, entry->header.guid, buf, + count = pmt_telem_read_mmio(entry->ep->dev, entry->cb, entry->header.guid, buf, entry->base, off, count); return count; @@ -208,7 +208,7 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry, struct intel_vsec_device *ivdev, struct resource *disc_res) { - struct pci_dev *pci_dev = ivdev->pcidev; + struct pci_dev *pci_dev = to_pci_dev(ivdev->dev); struct device *dev = &ivdev->auxdev.dev; struct intel_pmt_header *header = &entry->header; u8 bir; diff --git a/drivers/platform/x86/intel/pmt/class.h b/drivers/platform/x86/intel/pmt/class.h index 3c5ad5f52bca..1ae56a5baad2 100644 --- a/drivers/platform/x86/intel/pmt/class.h +++ b/drivers/platform/x86/intel/pmt/class.h @@ -19,11 +19,12 @@ #define GET_BIR(v) ((v) & GENMASK(2, 0)) #define GET_ADDRESS(v) ((v) & GENMASK(31, 3)) +struct device; struct pci_dev; extern struct class intel_pmt_class; struct telem_endpoint { - struct pci_dev *pcidev; + struct device *dev; struct telem_header header; struct pmt_callbacks *cb; void __iomem *base; @@ -65,7 +66,7 @@ struct intel_pmt_namespace { struct intel_pmt_entry *entry); }; -int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf, +int pmt_telem_read_mmio(struct device *dev, struct pmt_callbacks *cb, u32 guid, void *buf, void __iomem *addr, loff_t off, u32 count); bool intel_pmt_is_early_client_hw(struct device *dev); int intel_pmt_dev_create(struct intel_pmt_entry *entry, diff --git a/drivers/platform/x86/intel/pmt/discovery.c b/drivers/platform/x86/intel/pmt/discovery.c index e500aa327d23..c482368bfaae 100644 --- a/drivers/platform/x86/intel/pmt/discovery.c +++ b/drivers/platform/x86/intel/pmt/discovery.c @@ -542,7 +542,7 @@ static int pmt_features_probe(struct auxiliary_device *auxdev, const struct auxi if (!priv) return -ENOMEM; - priv->parent = &ivdev->pcidev->dev; + priv->parent = ivdev->dev; auxiliary_set_drvdata(auxdev, priv); priv->dev = device_create(&intel_pmt_class, &auxdev->dev, MKDEV(0, 0), priv, @@ -609,7 +609,7 @@ void intel_pmt_get_features(struct intel_pmt_entry *entry) mutex_lock(&feature_list_lock); list_for_each_entry(feature, &pmt_feature_list, list) { - if (feature->priv->parent != &entry->ep->pcidev->dev) + if (feature->priv->parent != entry->ep->dev) continue; pmt_get_features(entry, feature); diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c index a4dfca6cac19..e11f7bde41b2 100644 --- a/drivers/platform/x86/intel/pmt/telemetry.c +++ b/drivers/platform/x86/intel/pmt/telemetry.c @@ -112,7 +112,7 @@ static int pmt_telem_add_endpoint(struct intel_vsec_device *ivdev, return -ENOMEM; ep = entry->ep; - ep->pcidev = ivdev->pcidev; + ep->dev = ivdev->dev; ep->header.access_type = entry->header.access_type; ep->header.guid = entry->header.guid; ep->header.base_offset = entry->header.base_offset; @@ -204,7 +204,7 @@ int pmt_telem_get_endpoint_info(int devid, struct telem_endpoint_info *info) goto unlock; } - info->pdev = entry->ep->pcidev; + info->dev = entry->ep->dev; info->header = entry->ep->header; unlock: @@ -218,9 +218,10 @@ static int pmt_copy_region(struct telemetry_region *region, struct intel_pmt_entry *entry) { + struct pci_dev *pdev = to_pci_dev(entry->ep->dev); struct oobmsm_plat_info *plat_info; - plat_info = intel_vsec_get_mapping(entry->ep->pcidev); + plat_info = intel_vsec_get_mapping(pdev); if (IS_ERR(plat_info)) return PTR_ERR(plat_info); @@ -308,7 +309,7 @@ int pmt_telem_read(struct telem_endpoint *ep, u32 id, u64 *data, u32 count) if (offset + NUM_BYTES_QWORD(count) > size) return -EINVAL; - pmt_telem_read_mmio(ep->pcidev, ep->cb, ep->header.guid, data, ep->base, offset, + pmt_telem_read_mmio(ep->dev, ep->cb, ep->header.guid, data, ep->base, offset, NUM_BYTES_QWORD(count)); return ep->present ? 0 : -EPIPE; @@ -335,7 +336,7 @@ int pmt_telem_read32(struct telem_endpoint *ep, u32 id, u32 *data, u32 count) EXPORT_SYMBOL_NS_GPL(pmt_telem_read32, "INTEL_PMT_TELEMETRY"); struct telem_endpoint * -pmt_telem_find_and_register_endpoint(struct pci_dev *pcidev, u32 guid, u16 pos) +pmt_telem_find_and_register_endpoint(struct device *dev, u32 guid, u16 pos) { int devid = 0; int inst = 0; @@ -348,7 +349,7 @@ pmt_telem_find_and_register_endpoint(struct pci_dev *pcidev, u32 guid, u16 pos) if (err) return ERR_PTR(err); - if (ep_info.header.guid == guid && ep_info.pdev == pcidev) { + if (ep_info.header.guid == guid && ep_info.dev == dev) { if (inst == pos) return pmt_telem_register_endpoint(devid); ++inst; diff --git a/drivers/platform/x86/intel/pmt/telemetry.h b/drivers/platform/x86/intel/pmt/telemetry.h index d45af5512b4e..0f88c5e7d90e 100644 --- a/drivers/platform/x86/intel/pmt/telemetry.h +++ b/drivers/platform/x86/intel/pmt/telemetry.h @@ -6,8 +6,8 @@ #define PMT_TELEM_TELEMETRY 0 #define PMT_TELEM_CRASHLOG 1 +struct device; struct telem_endpoint; -struct pci_dev; struct telem_header { u8 access_type; @@ -17,7 +17,7 @@ struct telem_header { }; struct telem_endpoint_info { - struct pci_dev *pdev; + struct device *dev; struct telem_header header; }; @@ -71,8 +71,8 @@ int pmt_telem_get_endpoint_info(int devid, struct telem_endpoint_info *info); /** * pmt_telem_find_and_register_endpoint() - Get a telemetry endpoint from - * pci_dev device, guid and pos - * @pdev: PCI device inside the Intel vsec + * device, guid and pos + * @dev: device inside the Intel vsec * @guid: GUID of the telemetry space * @pos: Instance of the guid * @@ -80,8 +80,8 @@ int pmt_telem_get_endpoint_info(int devid, struct telem_endpoint_info *info); * * endpoint - On success returns pointer to the telemetry endpoint * * -ENXIO - telemetry endpoint not found */ -struct telem_endpoint *pmt_telem_find_and_register_endpoint(struct pci_dev *pcidev, - u32 guid, u16 pos); +struct telem_endpoint * +pmt_telem_find_and_register_endpoint(struct device *dev, u32 guid, u16 pos); /** * pmt_telem_read() - Read qwords from counter sram using sample id diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c index da75f53d0bcc..d7e37d4ace23 100644 --- a/drivers/platform/x86/intel/sdsi.c +++ b/drivers/platform/x86/intel/sdsi.c @@ -599,13 +599,14 @@ static int sdsi_get_layout(struct sdsi_priv *priv, struct disc_table *table) return 0; } -static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *parent, +static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct device *dev, struct disc_table *disc_table, struct resource *disc_res) { u32 access_type = FIELD_GET(DT_ACCESS_TYPE, disc_table->access_info); u32 size = FIELD_GET(DT_SIZE, disc_table->access_info); u32 tbir = FIELD_GET(DT_TBIR, disc_table->offset); u32 offset = DT_OFFSET(disc_table->offset); + struct pci_dev *parent = to_pci_dev(dev); struct resource res = {}; /* Starting location of SDSi MMIO region based on access type */ @@ -681,7 +682,7 @@ static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_de return ret; /* Map the SDSi mailbox registers */ - ret = sdsi_map_mbox_registers(priv, intel_cap_dev->pcidev, &disc_table, disc_res); + ret = sdsi_map_mbox_registers(priv, intel_cap_dev->dev, &disc_table, disc_res); if (ret) return ret; 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 c8de8688daed..b11d62c934b3 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 @@ -1786,7 +1786,7 @@ void tpmi_sst_dev_resume(struct auxiliary_device *auxdev) memcpy_toio(cp_base + SST_CLOS_ASSOC_0_OFFSET, pd_info->saved_clos_assocs, sizeof(pd_info->saved_clos_assocs)); - writeq(pd_info->saved_pp_control, power_domain_info->sst_base + + writeq(pd_info->saved_pp_control, pd_info->sst_base + pd_info->sst_header.pp_offset + SST_PP_CONTROL_OFFSET); } } diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c index 96fc27d88fbf..1e292eaeb209 100644 --- a/drivers/platform/x86/intel/vsec.c +++ b/drivers/platform/x86/intel/vsec.c @@ -158,18 +158,23 @@ static bool vsec_driver_present(int cap_id) */ static const struct pci_device_id intel_vsec_pci_ids[]; -static int intel_vsec_link_devices(struct pci_dev *pdev, struct device *dev, +static int intel_vsec_link_devices(struct device *parent, struct device *dev, int consumer_id) { const struct vsec_feature_dependency *deps; enum vsec_device_state *state; struct device **suppliers; struct vsec_priv *priv; + struct pci_dev *pdev; int supplier_id; if (!consumer_id) return 0; + if (!dev_is_pci(parent)) + return 0; + + pdev = to_pci_dev(parent); if (!pci_match_id(intel_vsec_pci_ids, pdev)) return 0; @@ -204,7 +209,7 @@ static int intel_vsec_link_devices(struct pci_dev *pdev, struct device *dev, return 0; } -int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent, +int intel_vsec_add_aux(struct device *parent, struct intel_vsec_device *intel_vsec_dev, const char *name) { @@ -252,7 +257,7 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent, if (ret) goto cleanup_aux; - ret = intel_vsec_link_devices(pdev, &auxdev->dev, intel_vsec_dev->cap_id); + ret = intel_vsec_link_devices(parent, &auxdev->dev, intel_vsec_dev->cap_id); if (ret) goto cleanup_aux; @@ -269,7 +274,7 @@ cleanup_aux: } EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, "INTEL_VSEC"); -static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header, +static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *header, const struct intel_vsec_platform_info *info, unsigned long cap_id, u64 base_addr) { @@ -283,18 +288,18 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he if (info->parent) parent = info->parent; else - parent = &pdev->dev; + parent = dev; if (!intel_vsec_supported(header->id, info->caps)) return -EINVAL; if (!header->num_entries) { - dev_dbg(&pdev->dev, "Invalid 0 entry count for header id %d\n", header->id); + dev_dbg(dev, "Invalid 0 entry count for header id %d\n", header->id); return -EINVAL; } if (!header->entry_size) { - dev_dbg(&pdev->dev, "Invalid 0 entry size for header id %d\n", header->id); + dev_dbg(dev, "Invalid 0 entry size for header id %d\n", header->id); return -EINVAL; } @@ -326,7 +331,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he release_mem_region(tmp->start, resource_size(tmp)); } - intel_vsec_dev->pcidev = pdev; + intel_vsec_dev->dev = dev; intel_vsec_dev->resource = no_free_ptr(res); intel_vsec_dev->num_resources = header->num_entries; intel_vsec_dev->quirks = info->quirks; @@ -343,7 +348,7 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he * Pass the ownership of intel_vsec_dev and resource within it to * intel_vsec_add_aux() */ - return intel_vsec_add_aux(pdev, parent, no_free_ptr(intel_vsec_dev), + return intel_vsec_add_aux(parent, no_free_ptr(intel_vsec_dev), intel_vsec_name(header->id)); } @@ -404,13 +409,14 @@ static int get_cap_id(u32 header_id, unsigned long *cap_id) return 0; } -static int intel_vsec_register_device(struct pci_dev *pdev, +static int intel_vsec_register_device(struct device *dev, struct intel_vsec_header *header, const struct intel_vsec_platform_info *info, u64 base_addr) { const struct vsec_feature_dependency *consumer_deps; struct vsec_priv *priv; + struct pci_dev *pdev; unsigned long cap_id; int ret; @@ -422,8 +428,12 @@ static int intel_vsec_register_device(struct pci_dev *pdev, * Only track dependencies for devices probed by the VSEC driver. * For others using the exported APIs, add the device directly. */ + if (!dev_is_pci(dev)) + return intel_vsec_add_dev(dev, header, info, cap_id, base_addr); + + pdev = to_pci_dev(dev); if (!pci_match_id(intel_vsec_pci_ids, pdev)) - return intel_vsec_add_dev(pdev, header, info, cap_id, base_addr); + return intel_vsec_add_dev(dev, header, info, cap_id, base_addr); priv = pci_get_drvdata(pdev); if (priv->state[cap_id] == STATE_REGISTERED || @@ -439,7 +449,7 @@ static int intel_vsec_register_device(struct pci_dev *pdev, consumer_deps = get_consumer_dependencies(priv, cap_id); if (!consumer_deps || suppliers_ready(priv, consumer_deps, cap_id)) { - ret = intel_vsec_add_dev(pdev, header, info, cap_id, base_addr); + ret = intel_vsec_add_dev(dev, header, info, cap_id, base_addr); if (ret) priv->state[cap_id] = STATE_SKIP; else @@ -451,20 +461,34 @@ static int intel_vsec_register_device(struct pci_dev *pdev, return -EAGAIN; } -static bool intel_vsec_walk_header(struct pci_dev *pdev, - const struct intel_vsec_platform_info *info) +static int intel_vsec_walk_header(struct device *dev, + const struct intel_vsec_platform_info *info) { struct intel_vsec_header **header = info->headers; - bool have_devices = false; + u64 base_addr; int ret; for ( ; *header; header++) { - ret = intel_vsec_register_device(pdev, *header, info, info->base_addr); - if (!ret) - have_devices = true; + if (info->base_addr) { + base_addr = info->base_addr; + } else { + struct pci_dev *pdev; + + if (!dev_is_pci(dev)) { + dev_err(dev, "non-PCI device without a base address\n"); + return -EINVAL; + } + + pdev = to_pci_dev(dev); + base_addr = pci_resource_start(pdev, (*header)->tbir); + } + + ret = intel_vsec_register_device(dev, *header, info, base_addr); + if (ret) + return ret; } - return have_devices; + return 0; } static bool intel_vsec_walk_dvsec(struct pci_dev *pdev, @@ -507,7 +531,7 @@ static bool intel_vsec_walk_dvsec(struct pci_dev *pdev, pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER2, &hdr); header.id = PCI_DVSEC_HEADER2_ID(hdr); - ret = intel_vsec_register_device(pdev, &header, info, + ret = intel_vsec_register_device(&pdev->dev, &header, info, pci_resource_start(pdev, header.tbir)); if (ret) continue; @@ -553,7 +577,7 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev, header.tbir = INTEL_DVSEC_TABLE_BAR(table); header.offset = INTEL_DVSEC_TABLE_OFFSET(table); - ret = intel_vsec_register_device(pdev, &header, info, + ret = intel_vsec_register_device(&pdev->dev, &header, info, pci_resource_start(pdev, header.tbir)); if (ret) continue; @@ -564,16 +588,13 @@ static bool intel_vsec_walk_vsec(struct pci_dev *pdev, return have_devices; } -int intel_vsec_register(struct pci_dev *pdev, +int intel_vsec_register(struct device *dev, const struct intel_vsec_platform_info *info) { - if (!pdev || !info || !info->headers) + if (!dev || !info || !info->headers) return -EINVAL; - if (!intel_vsec_walk_header(pdev, info)) - return -ENODEV; - else - return 0; + return intel_vsec_walk_header(dev, info); } EXPORT_SYMBOL_NS_GPL(intel_vsec_register, "INTEL_VSEC"); @@ -596,7 +617,7 @@ static bool intel_vsec_get_features(struct pci_dev *pdev, found = true; if (info && (info->quirks & VSEC_QUIRK_NO_DVSEC) && - intel_vsec_walk_header(pdev, info)) + intel_vsec_walk_header(&pdev->dev, info)) found = true; return found; @@ -677,7 +698,10 @@ int intel_vsec_set_mapping(struct oobmsm_plat_info *plat_info, { struct vsec_priv *priv; - priv = pci_get_drvdata(vsec_dev->pcidev); + if (!dev_is_pci(vsec_dev->dev)) + return -ENODEV; + + priv = pci_get_drvdata(to_pci_dev(vsec_dev->dev)); if (!priv) return -EINVAL; @@ -820,7 +844,7 @@ static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev) xa_for_each(&auxdev_array, index, intel_vsec_dev) { /* check if pdev doesn't match */ - if (pdev != intel_vsec_dev->pcidev) + if (&pdev->dev != intel_vsec_dev->dev) continue; devm_release_action(&pdev->dev, intel_vsec_remove_aux, &intel_vsec_dev->auxdev); diff --git a/drivers/platform/x86/intel/vsec_tpmi.c b/drivers/platform/x86/intel/vsec_tpmi.c index a8ccdd801ddd..e5f79c4a1d27 100644 --- a/drivers/platform/x86/intel/vsec_tpmi.c +++ b/drivers/platform/x86/intel/vsec_tpmi.c @@ -530,7 +530,7 @@ static const struct file_operations mem_write_ops = { .release = single_release, }; -#define tpmi_to_dev(info) (&info->vsec_dev->pcidev->dev) +#define tpmi_to_dev(info) ((info)->vsec_dev->dev) static void tpmi_dbgfs_register(struct intel_tpmi_info *tpmi_info) { @@ -642,7 +642,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, tmp->flags = IORESOURCE_MEM; } - feature_vsec_dev->pcidev = vsec_dev->pcidev; + feature_vsec_dev->dev = vsec_dev->dev; feature_vsec_dev->resource = res; feature_vsec_dev->num_resources = pfs->pfs_header.num_entries; feature_vsec_dev->priv_data = &tpmi_info->plat_info; @@ -655,7 +655,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, * feature_vsec_dev and res memory are also freed as part of * device deletion. */ - return intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev, + return intel_vsec_add_aux(&vsec_dev->auxdev.dev, feature_vsec_dev, feature_id_name); } @@ -742,7 +742,7 @@ static int tpmi_fetch_pfs_header(struct intel_tpmi_pm_feature *pfs, u64 start, i static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev) { struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev); - struct pci_dev *pci_dev = vsec_dev->pcidev; + struct pci_dev *pci_dev = to_pci_dev(vsec_dev->dev); struct intel_tpmi_info *tpmi_info; u64 pfs_start = 0; int ret, i; diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c index cb02222c978c..ced2b44fd7f7 100644 --- a/drivers/platform/x86/xo15-ebook.c +++ b/drivers/platform/x86/xo15-ebook.c @@ -38,6 +38,7 @@ MODULE_DEVICE_TABLE(acpi, ebook_device_ids); struct ebook_switch { struct input_dev *input; char phys[32]; /* for input device */ + bool gpe_enabled; }; static int ebook_send_state(struct acpi_device *device) @@ -128,7 +129,7 @@ static int ebook_switch_add(struct acpi_device *device) /* Button's GPE is run-wake GPE */ acpi_enable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number); - device_set_wakeup_enable(&device->dev, true); + button->gpe_enabled = true; } return 0; @@ -144,6 +145,10 @@ static void ebook_switch_remove(struct acpi_device *device) { struct ebook_switch *button = acpi_driver_data(device); + if (button->gpe_enabled) + acpi_disable_gpe(device->wakeup.gpe_device, + device->wakeup.gpe_number); + input_unregister_device(button->input); kfree(button); } |
