diff --git a/config/arm64/default b/config/arm64/default index 812cb29..072b9ff 100644 --- a/config/arm64/default +++ b/config/arm64/default @@ -771,6 +771,7 @@ CONFIG_ACPI_APEI_EINJ=m CONFIG_ACPI_APEI_ERST_DEBUG=m CONFIG_ACPI_WATCHDOG=y CONFIG_ACPI_CONFIGFS=m +CONFIG_ACPI_PFRUT=m CONFIG_ACPI_IORT=y CONFIG_ACPI_GTDT=y CONFIG_ACPI_PPTT=y diff --git a/config/x86_64/default b/config/x86_64/default index 85068b6..6fda052 100644 --- a/config/x86_64/default +++ b/config/x86_64/default @@ -625,6 +625,7 @@ CONFIG_ACPI_WATCHDOG=y CONFIG_ACPI_EXTLOG=m CONFIG_ACPI_ADXL=y CONFIG_ACPI_CONFIGFS=m +CONFIG_ACPI_PFRUT=m CONFIG_PMIC_OPREGION=y CONFIG_XPOWER_PMIC_OPREGION=y CONFIG_BXT_WC_PMIC_OPREGION=y diff --git a/patches.suse/ACPI-APD-Add-a-fmw-property-clk-name.patch b/patches.suse/ACPI-APD-Add-a-fmw-property-clk-name.patch new file mode 100644 index 0000000..ebfcfd7 --- /dev/null +++ b/patches.suse/ACPI-APD-Add-a-fmw-property-clk-name.patch @@ -0,0 +1,48 @@ +From: Ajit Kumar Pandey +Date: Sun, 12 Dec 2021 23:35:25 +0530 +Subject: ACPI: APD: Add a fmw property clk-name +Patch-mainline: v5.17-rc1 +Git-commit: 7fdb98e8a768b3ccc05494d3ea4436047f512b9d +References: jsc#PED-1408 + +Add a new device property to fetch clk-name from firmware. + +Signed-off-by: Ajit Kumar Pandey +Reviewed-by: Mario Limonciello +Link: https://lore.kernel.org/r/20211212180527.1641362-4-AjitKumar.Pandey@amd.com +Signed-off-by: Stephen Boyd +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpi_apd.c | 10 ++++++++++ + include/linux/platform_data/clk-fch.h | 1 + + 2 files changed, 11 insertions(+) + +--- a/drivers/acpi/acpi_apd.c ++++ b/drivers/acpi/acpi_apd.c +@@ -87,6 +87,16 @@ static int fch_misc_setup(struct apd_pri + if (ret < 0) + return -ENOENT; + ++ if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) { ++ clk_data->name = devm_kzalloc(&adev->dev, obj->string.length, ++ GFP_KERNEL); ++ ++ strcpy(clk_data->name, obj->string.pointer); ++ } else { ++ /* Set default name to mclk if entry missing in firmware */ ++ clk_data->name = "mclk"; ++ } ++ + list_for_each_entry(rentry, &resource_list, node) { + clk_data->base = devm_ioremap(&adev->dev, rentry->res->start, + resource_size(rentry->res)); +--- a/include/linux/platform_data/clk-fch.h ++++ b/include/linux/platform_data/clk-fch.h +@@ -12,6 +12,7 @@ + + struct fch_clk_data { + void __iomem *base; ++ char *name; + }; + + #endif /* __CLK_FCH_H */ diff --git a/patches.suse/ACPI-Add-a-context-argument-for-table-parsing-handle.patch b/patches.suse/ACPI-Add-a-context-argument-for-table-parsing-handle.patch new file mode 100644 index 0000000..b3fec9b --- /dev/null +++ b/patches.suse/ACPI-Add-a-context-argument-for-table-parsing-handle.patch @@ -0,0 +1,158 @@ +From: Dan Williams +Date: Fri, 29 Oct 2021 12:51:42 -0700 +Subject: ACPI: Add a context argument for table parsing handlers +Patch-mainline: v5.17-rc1 +Git-commit: 2d03e46a4bad20191d07b83ec1242d5f002577be +References: jsc#PED-1408 + +In preparation for drivers reusing the core table parsing +infrastructure, arrange for handlers to take a context argument. This +allows driver table parsing to wrap ACPI table entries in +driver-specific data. + +The first consumer of this infrastructure is the CEDT parsing that +happens in the cxl_acpi driver, add a conditional +(CONFIG_ACPI_TABLE_LIB=y) export of a acpi_table_parse_cedt() helper for +this case. + +Cc: "Rafael J. Wysocki" +Cc: Len Brown +Tested-by: Alison Schofield +Reviewed-by: Alison Schofield +Acked-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/163553710257.2509508.14310494417463866020.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/tables.c | 51 +++++++++++++++++++++++++++++++++++++++++++------- + include/linux/acpi.h | 11 ++++++++++ + 2 files changed, 55 insertions(+), 7 deletions(-) + +--- a/drivers/acpi/tables.c ++++ b/drivers/acpi/tables.c +@@ -276,6 +276,22 @@ acpi_get_subtable_type(char *id) + return ACPI_SUBTABLE_COMMON; + } + ++static __init_or_acpilib bool has_handler(struct acpi_subtable_proc *proc) ++{ ++ return proc->handler || proc->handler_arg; ++} ++ ++static __init_or_acpilib int call_handler(struct acpi_subtable_proc *proc, ++ union acpi_subtable_headers *hdr, ++ unsigned long end) ++{ ++ if (proc->handler) ++ return proc->handler(hdr, end); ++ if (proc->handler_arg) ++ return proc->handler_arg(hdr, proc->arg, end); ++ return -EINVAL; ++} ++ + /** + * acpi_parse_entries_array - for each proc_num find a suitable subtable + * +@@ -326,8 +342,9 @@ static int __init_or_acpilib acpi_parse_ + for (i = 0; i < proc_num; i++) { + if (acpi_get_entry_type(&entry) != proc[i].id) + continue; +- if (!proc[i].handler || +- (!errs && proc[i].handler(entry.hdr, table_end))) { ++ if (!has_handler(&proc[i]) || ++ (!errs && ++ call_handler(&proc[i], entry.hdr, table_end))) { + errs++; + continue; + } +@@ -393,21 +410,41 @@ int __init_or_acpilib acpi_table_parse_e + return count; + } + +-int __init acpi_table_parse_entries(char *id, +- unsigned long table_size, +- int entry_id, +- acpi_tbl_entry_handler handler, +- unsigned int max_entries) ++static int __init_or_acpilib __acpi_table_parse_entries( ++ char *id, unsigned long table_size, int entry_id, ++ acpi_tbl_entry_handler handler, acpi_tbl_entry_handler_arg handler_arg, ++ void *arg, unsigned int max_entries) + { + struct acpi_subtable_proc proc = { + .id = entry_id, + .handler = handler, ++ .handler_arg = handler_arg, ++ .arg = arg, + }; + + return acpi_table_parse_entries_array(id, table_size, &proc, 1, + max_entries); + } + ++int __init_or_acpilib ++acpi_table_parse_cedt(enum acpi_cedt_type id, ++ acpi_tbl_entry_handler_arg handler_arg, void *arg) ++{ ++ return __acpi_table_parse_entries(ACPI_SIG_CEDT, ++ sizeof(struct acpi_table_cedt), id, ++ NULL, handler_arg, arg, 0); ++} ++EXPORT_SYMBOL_ACPI_LIB(acpi_table_parse_cedt); ++ ++int __init acpi_table_parse_entries(char *id, unsigned long table_size, ++ int entry_id, ++ acpi_tbl_entry_handler handler, ++ unsigned int max_entries) ++{ ++ return __acpi_table_parse_entries(id, table_size, entry_id, handler, ++ NULL, NULL, max_entries); ++} ++ + int __init acpi_table_parse_madt(enum acpi_madt_type id, + acpi_tbl_entry_handler handler, unsigned int max_entries) + { +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -141,6 +141,9 @@ typedef int (*acpi_tbl_table_handler)(st + typedef int (*acpi_tbl_entry_handler)(union acpi_subtable_headers *header, + const unsigned long end); + ++typedef int (*acpi_tbl_entry_handler_arg)(union acpi_subtable_headers *header, ++ void *arg, const unsigned long end); ++ + /* Debugger support */ + + struct acpi_debugger_ops { +@@ -217,6 +220,8 @@ static inline int acpi_debugger_notify_c + struct acpi_subtable_proc { + int id; + acpi_tbl_entry_handler handler; ++ acpi_tbl_entry_handler_arg handler_arg; ++ void *arg; + int count; + }; + +@@ -235,9 +240,11 @@ void acpi_table_init_complete (void); + int acpi_table_init (void); + + #ifdef CONFIG_ACPI_TABLE_LIB ++#define EXPORT_SYMBOL_ACPI_LIB(x) EXPORT_SYMBOL_NS_GPL(x, ACPI) + #define __init_or_acpilib + #define __initdata_or_acpilib + #else ++#define EXPORT_SYMBOL_ACPI_LIB(x) + #define __init_or_acpilib __init + #define __initdata_or_acpilib __initdata + #endif +@@ -252,6 +259,10 @@ int __init_or_acpilib acpi_table_parse_e + int acpi_table_parse_madt(enum acpi_madt_type id, + acpi_tbl_entry_handler handler, + unsigned int max_entries); ++int __init_or_acpilib ++acpi_table_parse_cedt(enum acpi_cedt_type id, ++ acpi_tbl_entry_handler_arg handler_arg, void *arg); ++ + int acpi_parse_mcfg (struct acpi_table_header *header); + void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); + diff --git a/patches.suse/ACPI-CPPC-Add-CPPC-enable-register-function.patch b/patches.suse/ACPI-CPPC-Add-CPPC-enable-register-function.patch new file mode 100644 index 0000000..2523f64 --- /dev/null +++ b/patches.suse/ACPI-CPPC-Add-CPPC-enable-register-function.patch @@ -0,0 +1,105 @@ +From: Jinzhou Su +Date: Fri, 24 Dec 2021 09:04:59 +0800 +Subject: ACPI: CPPC: Add CPPC enable register function +Patch-mainline: v5.17-rc1 +Git-commit: fb0b00af04d083770d6e2762b2838357519f7d2d +References: jsc#PED-1408 + +Add a new function to enable CPPC feature. This function +will write Continuous Performance Control package +EnableRegister field on the processor. + +CPPC EnableRegister register described in section 8.4.7.1 of ACPI 6.4: +This element is optional. If supported, contains a resource descriptor +with a single Register() descriptor that describes a register to which +OSPM writes a One to enable CPPC on this processor. Before this register +is set, the processor will be controlled by legacy mechanisms (ACPI +Pstates, firmware, etc.). + +This register will be used for AMD processors to enable AMD P-State +function instead of legacy ACPI P-States. + +Signed-off-by: Jinzhou Su +Signed-off-by: Huang Rui +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/cppc_acpi.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + include/acpi/cppc_acpi.h | 5 +++++ + 2 files changed, 50 insertions(+) + +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -1273,6 +1273,51 @@ out_err: + EXPORT_SYMBOL_GPL(cppc_get_perf_ctrs); + + /** ++ * cppc_set_enable - Set to enable CPPC on the processor by writing the ++ * Continuous Performance Control package EnableRegister field. ++ * @cpu: CPU for which to enable CPPC register. ++ * @enable: 0 - disable, 1 - enable CPPC feature on the processor. ++ * ++ * Return: 0 for success, -ERRNO or -EIO otherwise. ++ */ ++int cppc_set_enable(int cpu, bool enable) ++{ ++ int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); ++ struct cpc_register_resource *enable_reg; ++ struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu); ++ struct cppc_pcc_data *pcc_ss_data = NULL; ++ int ret = -EINVAL; ++ ++ if (!cpc_desc) { ++ pr_debug("No CPC descriptor for CPU:%d\n", cpu); ++ return -EINVAL; ++ } ++ ++ enable_reg = &cpc_desc->cpc_regs[ENABLE]; ++ ++ if (CPC_IN_PCC(enable_reg)) { ++ ++ if (pcc_ss_id < 0) ++ return -EIO; ++ ++ ret = cpc_write(cpu, enable_reg, enable); ++ if (ret) ++ return ret; ++ ++ pcc_ss_data = pcc_data[pcc_ss_id]; ++ ++ down_write(&pcc_ss_data->pcc_lock); ++ /* after writing CPC, transfer the ownership of PCC to platfrom */ ++ ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE); ++ up_write(&pcc_ss_data->pcc_lock); ++ return ret; ++ } ++ ++ return cpc_write(cpu, enable_reg, enable); ++} ++EXPORT_SYMBOL_GPL(cppc_set_enable); ++ ++/** + * cppc_set_perf - Set a CPU's performance controls. + * @cpu: CPU for which to set performance controls. + * @perf_ctrls: ptr to cppc_perf_ctrls. See cppc_acpi.h +--- a/include/acpi/cppc_acpi.h ++++ b/include/acpi/cppc_acpi.h +@@ -138,6 +138,7 @@ extern int cppc_get_desired_perf(int cpu + extern int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf); + extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs); + extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls); ++extern int cppc_set_enable(int cpu, bool enable); + extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps); + extern bool acpi_cpc_valid(void); + extern int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data); +@@ -162,6 +163,10 @@ static inline int cppc_set_perf(int cpu, + { + return -ENOTSUPP; + } ++static inline int cppc_set_enable(int cpu, bool enable) ++{ ++ return -ENOTSUPP; ++} + static inline int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps) + { + return -ENOTSUPP; diff --git a/patches.suse/ACPI-CPPC-Amend-documentation-in-the-comments.patch b/patches.suse/ACPI-CPPC-Amend-documentation-in-the-comments.patch new file mode 100644 index 0000000..211ce55 --- /dev/null +++ b/patches.suse/ACPI-CPPC-Amend-documentation-in-the-comments.patch @@ -0,0 +1,88 @@ +From: Andy Shevchenko +Date: Wed, 22 Dec 2021 16:04:45 +0200 +Subject: ACPI: CPPC: Amend documentation in the comments +Patch-mainline: v5.17-rc1 +Git-commit: 1a901c914dfbee04f20200a116dc9d30679c8cc6 +References: jsc#PED-1408 + +Currently it's too hard to read the _CPC structure as it's commented. +Reshuffle indentation and style to make it readable. + +Signed-off-by: Andy Shevchenko +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/cppc_acpi.c | 59 ++++++++++++++++------------------------------- + 1 file changed, 21 insertions(+), 38 deletions(-) + +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -618,47 +618,30 @@ static bool is_cppc_supported(int revisi + /* + * An example CPC table looks like the following. + * +- * Name(_CPC, Package() +- * { +- * 17, +- * NumEntries +- * 1, +- * // Revision +- * ResourceTemplate(){Register(PCC, 32, 0, 0x120, 2)}, +- * // Highest Performance +- * ResourceTemplate(){Register(PCC, 32, 0, 0x124, 2)}, +- * // Nominal Performance +- * ResourceTemplate(){Register(PCC, 32, 0, 0x128, 2)}, +- * // Lowest Nonlinear Performance +- * ResourceTemplate(){Register(PCC, 32, 0, 0x12C, 2)}, +- * // Lowest Performance +- * ResourceTemplate(){Register(PCC, 32, 0, 0x130, 2)}, +- * // Guaranteed Performance Register +- * ResourceTemplate(){Register(PCC, 32, 0, 0x110, 2)}, +- * // Desired Performance Register +- * ResourceTemplate(){Register(SystemMemory, 0, 0, 0, 0)}, +- * .. +- * .. +- * .. +- * +- * } ++ * Name (_CPC, Package() { ++ * 17, // NumEntries ++ * 1, // Revision ++ * ResourceTemplate() {Register(PCC, 32, 0, 0x120, 2)}, // Highest Performance ++ * ResourceTemplate() {Register(PCC, 32, 0, 0x124, 2)}, // Nominal Performance ++ * ResourceTemplate() {Register(PCC, 32, 0, 0x128, 2)}, // Lowest Nonlinear Performance ++ * ResourceTemplate() {Register(PCC, 32, 0, 0x12C, 2)}, // Lowest Performance ++ * ResourceTemplate() {Register(PCC, 32, 0, 0x130, 2)}, // Guaranteed Performance Register ++ * ResourceTemplate() {Register(PCC, 32, 0, 0x110, 2)}, // Desired Performance Register ++ * ResourceTemplate() {Register(SystemMemory, 0, 0, 0, 0)}, ++ * ... ++ * ... ++ * ... ++ * } + * Each Register() encodes how to access that specific register. + * e.g. a sample PCC entry has the following encoding: + * +- * Register ( +- * PCC, +- * AddressSpaceKeyword +- * 8, +- * //RegisterBitWidth +- * 8, +- * //RegisterBitOffset +- * 0x30, +- * //RegisterAddress +- * 9 +- * //AccessSize (subspace ID) +- * 0 +- * ) +- * } ++ * Register ( ++ * PCC, // AddressSpaceKeyword ++ * 8, // RegisterBitWidth ++ * 8, // RegisterBitOffset ++ * 0x30, // RegisterAddress ++ * 9, // AccessSize (subspace ID) ++ * ) + */ + + #ifndef init_freq_invariance_cppc diff --git a/patches.suse/ACPI-CPPC-Drop-redundant-local-variable-from-cpc_rea.patch b/patches.suse/ACPI-CPPC-Drop-redundant-local-variable-from-cpc_rea.patch new file mode 100644 index 0000000..355a90d --- /dev/null +++ b/patches.suse/ACPI-CPPC-Drop-redundant-local-variable-from-cpc_rea.patch @@ -0,0 +1,50 @@ +From: "Rafael J. Wysocki" +Date: Wed, 12 Jan 2022 19:27:22 +0100 +Subject: ACPI: CPPC: Drop redundant local variable from cpc_read() +Patch-mainline: v5.17-rc1 +Git-commit: f684b10751287e8b7e15e8f10ae40bdd74149bba +References: jsc#PED-1408 + +The ret_val local variable in cpc_read() is not necessary, so +eliminate it. + +No functional impact. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Huang Rui +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/cppc_acpi.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -928,14 +928,13 @@ int __weak cpc_write_ffh(int cpunum, str + + static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) + { +- int ret_val = 0; + void __iomem *vaddr = NULL; + int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); + struct cpc_reg *reg = ®_res->cpc_entry.reg; + + if (reg_res->type == ACPI_TYPE_INTEGER) { + *val = reg_res->cpc_entry.int_value; +- return ret_val; ++ return 0; + } + + *val = 0; +@@ -981,10 +980,10 @@ static int cpc_read(int cpu, struct cpc_ + default: + pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n", + reg->bit_width, pcc_ss_id); +- ret_val = -EFAULT; ++ return -EFAULT; + } + +- return ret_val; ++ return 0; + } + + static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) diff --git a/patches.suse/ACPI-CPPC-Fix-up-I-O-port-access-in-cpc_read.patch b/patches.suse/ACPI-CPPC-Fix-up-I-O-port-access-in-cpc_read.patch new file mode 100644 index 0000000..4c3dcc9 --- /dev/null +++ b/patches.suse/ACPI-CPPC-Fix-up-I-O-port-access-in-cpc_read.patch @@ -0,0 +1,43 @@ +From: "Rafael J. Wysocki" +Date: Wed, 12 Jan 2022 19:26:32 +0100 +Subject: ACPI: CPPC: Fix up I/O port access in cpc_read() +Patch-mainline: v5.17-rc1 +Git-commit: 5f51c7ce1dc36565296b3ef342585f70ec72a2a9 +References: jsc#PED-1408 + +The code as currently implemented does not work on big endian systems, +so fix it up. + +Fixes: a2c8f92bea5f ("ACPI: CPPC: Implement support for SystemIO registers") +Reported-by: Dan Carpenter +Suggested-by: Dan Carpenter +Link: https://lore.kernel.org/linux-acpi/20220111092928.GA24968@kili/ +Signed-off-by: Rafael J. Wysocki +Acked-by: Huang Rui +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/cppc_acpi.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -942,16 +942,18 @@ static int cpc_read(int cpu, struct cpc_ + + if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { + u32 width = 8 << (reg->access_width - 1); ++ u32 val_u32; + acpi_status status; + + status = acpi_os_read_port((acpi_io_address)reg->address, +- (u32 *)val, width); ++ &val_u32, width); + if (ACPI_FAILURE(status)) { + pr_debug("Error: Failed to read SystemIO port %llx\n", + reg->address); + return -EFAULT; + } + ++ *val = val_u32; + return 0; + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) + vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); diff --git a/patches.suse/ACPI-CPPC-Implement-support-for-SystemIO-registers.patch b/patches.suse/ACPI-CPPC-Implement-support-for-SystemIO-registers.patch new file mode 100644 index 0000000..46d4c70 --- /dev/null +++ b/patches.suse/ACPI-CPPC-Implement-support-for-SystemIO-registers.patch @@ -0,0 +1,107 @@ +From: Steven Noonan +Date: Fri, 24 Dec 2021 09:04:57 +0800 +Subject: ACPI: CPPC: Implement support for SystemIO registers +Patch-mainline: v5.17-rc1 +Git-commit: a2c8f92bea5f8f1a87fc3caf063d67876dbf5d47 +References: jsc#PED-1408 + +According to the ACPI v6.2 (and later) specification, SystemIO can be +used for _CPC registers. This teaches cppc_acpi how to handle such +registers. + +This patch was tested using the amd_pstate driver on my Zephyrus G15 +(model GA503QS) using the current version 410 BIOS, which uses +a SystemIO register for the HighestPerformance element in _CPC. + +Signed-off-by: Steven Noonan +Signed-off-by: Huang Rui +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/cppc_acpi.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 49 insertions(+), 3 deletions(-) + +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -118,6 +118,8 @@ static DEFINE_PER_CPU(struct cpc_desc *, + */ + #define NUM_RETRIES 500ULL + ++#define OVER_16BTS_MASK ~0xFFFFULL ++ + #define define_one_cppc_ro(_name) \ + static struct kobj_attribute _name = \ + __ATTR(_name, 0444, show_##_name, NULL) +@@ -743,9 +745,26 @@ int acpi_cppc_processor_probe(struct acp + goto out_free; + cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr; + } ++ } else if (gas_t->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { ++ if (gas_t->access_width < 1 || gas_t->access_width > 3) { ++ /* ++ * 1 = 8-bit, 2 = 16-bit, and 3 = 32-bit. ++ * SystemIO doesn't implement 64-bit ++ * registers. ++ */ ++ pr_debug("Invalid access width %d for SystemIO register\n", ++ gas_t->access_width); ++ goto out_free; ++ } ++ if (gas_t->address & OVER_16BTS_MASK) { ++ /* SystemIO registers use 16-bit integer addresses */ ++ pr_debug("Invalid IO port %llu for SystemIO register\n", ++ gas_t->address); ++ goto out_free; ++ } + } else { + if (gas_t->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE || !cpc_ffh_supported()) { +- /* Support only PCC ,SYS MEM and FFH type regs */ ++ /* Support only PCC, SystemMemory, SystemIO, and FFH type regs. */ + pr_debug("Unsupported register type: %d\n", gas_t->space_id); + goto out_free; + } +@@ -920,7 +939,21 @@ static int cpc_read(int cpu, struct cpc_ + } + + *val = 0; +- if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) ++ ++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { ++ u32 width = 8 << (reg->access_width - 1); ++ acpi_status status; ++ ++ status = acpi_os_read_port((acpi_io_address)reg->address, ++ (u32 *)val, width); ++ if (ACPI_FAILURE(status)) { ++ pr_debug("Error: Failed to read SystemIO port %llx\n", ++ reg->address); ++ return -EFAULT; ++ } ++ ++ return 0; ++ } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) + vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); + else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + vaddr = reg_res->sys_mem_vaddr; +@@ -959,7 +992,20 @@ static int cpc_write(int cpu, struct cpc + int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); + struct cpc_reg *reg = ®_res->cpc_entry.reg; + +- if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) ++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { ++ u32 width = 8 << (reg->access_width - 1); ++ acpi_status status; ++ ++ status = acpi_os_write_port((acpi_io_address)reg->address, ++ (u32)val, width); ++ if (ACPI_FAILURE(status)) { ++ pr_debug("Error: Failed to write SystemIO port %llx\n", ++ reg->address); ++ return -EFAULT; ++ } ++ ++ return 0; ++ } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) + vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); + else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + vaddr = reg_res->sys_mem_vaddr; diff --git a/patches.suse/ACPI-DPTF-Support-Raptor-Lake.patch b/patches.suse/ACPI-DPTF-Support-Raptor-Lake.patch new file mode 100644 index 0000000..4404669 --- /dev/null +++ b/patches.suse/ACPI-DPTF-Support-Raptor-Lake.patch @@ -0,0 +1,63 @@ +From: Srinivas Pandruvada +Date: Fri, 14 Jan 2022 15:24:33 -0800 +Subject: ACPI: DPTF: Support Raptor Lake +Patch-mainline: v5.17-rc1 +Git-commit: a510c78e5b6f2f9b9add88071fdfc2b740d2e356 +References: jsc#PED-1408 + +Add Raptor Lake ACPI IDs for DPTF devices. + +Signed-off-by: Srinivas Pandruvada +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/dptf/dptf_pch_fivr.c | 1 + + drivers/acpi/dptf/dptf_power.c | 2 ++ + drivers/acpi/dptf/int340x_thermal.c | 6 ++++++ + drivers/acpi/fan.h | 1 + + 4 files changed, 10 insertions(+) + +--- a/drivers/acpi/dptf/dptf_pch_fivr.c ++++ b/drivers/acpi/dptf/dptf_pch_fivr.c +@@ -151,6 +151,7 @@ static int pch_fivr_remove(struct platfo + static const struct acpi_device_id pch_fivr_device_ids[] = { + {"INTC1045", 0}, + {"INTC1049", 0}, ++ {"INTC10A3", 0}, + {"", 0}, + }; + MODULE_DEVICE_TABLE(acpi, pch_fivr_device_ids); +--- a/drivers/acpi/dptf/dptf_power.c ++++ b/drivers/acpi/dptf/dptf_power.c +@@ -231,6 +231,8 @@ static const struct acpi_device_id int34 + {"INTC1050", 0}, + {"INTC1060", 0}, + {"INTC1061", 0}, ++ {"INTC10A4", 0}, ++ {"INTC10A5", 0}, + {"", 0}, + }; + MODULE_DEVICE_TABLE(acpi, int3407_device_ids); +--- a/drivers/acpi/dptf/int340x_thermal.c ++++ b/drivers/acpi/dptf/int340x_thermal.c +@@ -37,6 +37,12 @@ static const struct acpi_device_id int34 + {"INTC1050"}, + {"INTC1060"}, + {"INTC1061"}, ++ {"INTC10A0"}, ++ {"INTC10A1"}, ++ {"INTC10A2"}, ++ {"INTC10A3"}, ++ {"INTC10A4"}, ++ {"INTC10A5"}, + {""}, + }; + +--- a/drivers/acpi/fan.h ++++ b/drivers/acpi/fan.h +@@ -10,4 +10,5 @@ + {"INT3404", }, /* Fan */ \ + {"INTC1044", }, /* Fan for Tiger Lake generation */ \ + {"INTC1048", }, /* Fan for Alder Lake generation */ \ ++ {"INTC10A2", }, /* Fan for Raptor Lake generation */ \ + {"PNP0C0B", } /* Generic ACPI fan */ diff --git a/patches.suse/ACPI-DPTF-Update-device-ID-in-a-comment.patch b/patches.suse/ACPI-DPTF-Update-device-ID-in-a-comment.patch new file mode 100644 index 0000000..1eb0fac --- /dev/null +++ b/patches.suse/ACPI-DPTF-Update-device-ID-in-a-comment.patch @@ -0,0 +1,33 @@ +From: Sumeet Pawnikar +Date: Fri, 12 Nov 2021 17:30:29 +0530 +Subject: ACPI: DPTF: Update device ID in a comment +Patch-mainline: v5.17-rc1 +Git-commit: 75f32fa3a6fbaed25ad741221ab60bb4b08d7656 +References: jsc#PED-1408 + +There is a comment in dptf_pch_fivr.c which seemingly was added under +the assumption that the PCH FIVR driver would be used on Tiger Lake +platforms, but support for Alder Lake has been udded to it by commit +38748bcb940e ("ACPI: DPTF: Support Alder Lake"), so update the +comment to cover a broader range of platforms by changing the device +ID mentioned by it to INTC10xx. + +Signed-off-by: Sumeet Pawnikar +[ rjw: Subject and changelog rewrite ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/dptf/dptf_pch_fivr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/acpi/dptf/dptf_pch_fivr.c ++++ b/drivers/acpi/dptf/dptf_pch_fivr.c +@@ -46,7 +46,7 @@ release_buffer: + } + + /* +- * Presentation of attributes which are defined for INT1045 ++ * Presentation of attributes which are defined for INTC10xx + * They are: + * freq_mhz_low_clock : Set PCH FIVR switching freq for + * FIVR clock 19.2MHz and 24MHz diff --git a/patches.suse/ACPI-EC-Avoid-queuing-unnecessary-work-in-acpi_ec_su.patch b/patches.suse/ACPI-EC-Avoid-queuing-unnecessary-work-in-acpi_ec_su.patch new file mode 100644 index 0000000..b6f03b3 --- /dev/null +++ b/patches.suse/ACPI-EC-Avoid-queuing-unnecessary-work-in-acpi_ec_su.patch @@ -0,0 +1,82 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:43:05 +0100 +Subject: ACPI: EC: Avoid queuing unnecessary work in acpi_ec_submit_event() +Patch-mainline: v5.17-rc1 +Git-commit: c793570d8725e44b64dbe466eb8ecda34c5eb8ac +References: jsc#PED-1408 + +Notice that it is not necessary to queue up the event work again +if the while () loop in acpi_ec_event_handler() is still running +which is the case if nr_pending_queries is greater than 0 at the +beginning of acpi_ec_submit_event() and modify the code to avoid +doing that. + +While at it, rename nr_pending_queries in struct acpi_ec to +events_to_process which actually matches the role of that field +and change its data type to unsigned int which is sufficient. + +No expected functional impact. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 17 +++++++++++++---- + drivers/acpi/internal.h | 2 +- + 2 files changed, 14 insertions(+), 5 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -453,7 +453,16 @@ static bool acpi_ec_submit_event(struct + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { + ec_dbg_evt("Command(%s) submitted/blocked", + acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); +- ec->nr_pending_queries++; ++ /* ++ * If events_to_process is greqter than 0 at this point, the ++ * while () loop in acpi_ec_event_handler() is still running ++ * and incrementing events_to_process will cause it to invoke ++ * acpi_ec_submit_query() once more, so it is not necessary to ++ * queue up the event work to start the same loop again. ++ */ ++ if (ec->events_to_process++ > 0) ++ return true; ++ + ec->events_in_progress++; + return queue_work(ec_wq, &ec->work); + } +@@ -665,7 +674,7 @@ static bool advance_transaction(struct a + */ + if (!t || !(t->flags & ACPI_EC_COMMAND_POLL)) { + if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && +- (!ec->nr_pending_queries || ++ (!ec->events_to_process || + test_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags))) { + clear_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags); + acpi_ec_close_event(ec); +@@ -1223,13 +1232,13 @@ static void acpi_ec_event_handler(struct + + spin_lock_irq(&ec->lock); + +- while (ec->nr_pending_queries) { ++ while (ec->events_to_process) { + spin_unlock_irq(&ec->lock); + + acpi_ec_submit_query(ec); + + spin_lock_irq(&ec->lock); +- ec->nr_pending_queries--; ++ ec->events_to_process--; + } + + /* +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -182,7 +182,7 @@ struct acpi_ec { + spinlock_t lock; + struct work_struct work; + unsigned long timestamp; +- unsigned long nr_pending_queries; ++ unsigned int events_to_process; + unsigned int events_in_progress; + unsigned int queries_in_progress; + bool busy_polling; diff --git a/patches.suse/ACPI-EC-Call-advance_transaction-from-acpi_ec_dispat.patch b/patches.suse/ACPI-EC-Call-advance_transaction-from-acpi_ec_dispat.patch new file mode 100644 index 0000000..8e96702 --- /dev/null +++ b/patches.suse/ACPI-EC-Call-advance_transaction-from-acpi_ec_dispat.patch @@ -0,0 +1,125 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:37:39 +0100 +Subject: ACPI: EC: Call advance_transaction() from acpi_ec_dispatch_gpe() +Patch-mainline: v5.17-rc1 +Git-commit: ca8283dcd933a2ca776fade77fb4527321521463 +References: jsc#PED-1408 + +Calling acpi_dispatch_gpe() from acpi_ec_dispatch_gpe() is generally +problematic, because it may cause the spurious interrupt handling in +advance_transaction() to trigger in theory. + +However, instead of calling acpi_dispatch_gpe() to dispatch the EC +GPE, acpi_ec_dispatch_gpe() can call advance_transaction() directly +on first_ec and it can pass 'false' as its second argument to indicate +calling it from process context. + +Moreover, if advance_transaction() is modified to return a bool value +indicating whether or not the EC work needs to be flushed, it can be +used to avoid unnecessary EC work flushing in acpi_ec_dispatch_gpe(), +so change the code accordingly. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 39 ++++++++++++++++++++++++++++----------- + 1 file changed, 28 insertions(+), 11 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -170,7 +170,7 @@ struct acpi_ec_query { + }; + + static int acpi_ec_query(struct acpi_ec *ec, u8 *data); +-static void advance_transaction(struct acpi_ec *ec, bool interrupt); ++static bool advance_transaction(struct acpi_ec *ec, bool interrupt); + static void acpi_ec_event_handler(struct work_struct *work); + static void acpi_ec_event_processor(struct work_struct *work); + +@@ -444,18 +444,25 @@ static bool acpi_ec_submit_flushable_req + return true; + } + +-static void acpi_ec_submit_query(struct acpi_ec *ec) ++static bool acpi_ec_submit_query(struct acpi_ec *ec) + { + acpi_ec_mask_events(ec); + if (!acpi_ec_event_enabled(ec)) +- return; ++ return false; ++ + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { + ec_dbg_evt("Command(%s) submitted/blocked", + acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); + ec->nr_pending_queries++; + ec->events_in_progress++; +- queue_work(ec_wq, &ec->work); ++ return queue_work(ec_wq, &ec->work); + } ++ ++ /* ++ * The event handling work has not been completed yet, so it needs to be ++ * flushed. ++ */ ++ return true; + } + + static void acpi_ec_complete_query(struct acpi_ec *ec) +@@ -628,10 +635,11 @@ static void acpi_ec_spurious_interrupt(s + acpi_ec_mask_events(ec); + } + +-static void advance_transaction(struct acpi_ec *ec, bool interrupt) ++static bool advance_transaction(struct acpi_ec *ec, bool interrupt) + { + struct transaction *t = ec->curr; + bool wakeup = false; ++ bool ret = false; + u8 status; + + ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id()); +@@ -698,10 +706,12 @@ static void advance_transaction(struct a + + out: + if (status & ACPI_EC_FLAG_SCI) +- acpi_ec_submit_query(ec); ++ ret = acpi_ec_submit_query(ec); + + if (wakeup && interrupt) + wake_up(&ec->wait); ++ ++ return ret; + } + + static void start_transaction(struct acpi_ec *ec) +@@ -2038,8 +2048,7 @@ void acpi_ec_set_gpe_wake_mask(u8 action + + bool acpi_ec_dispatch_gpe(void) + { +- bool work_in_progress; +- u32 ret; ++ bool work_in_progress = false; + + if (!first_ec) + return acpi_any_gpe_status_set(U32_MAX); +@@ -2055,9 +2064,17 @@ bool acpi_ec_dispatch_gpe(void) + * Dispatch the EC GPE in-band, but do not report wakeup in any case + * to allow the caller to process events properly after that. + */ +- ret = acpi_dispatch_gpe(NULL, first_ec->gpe); +- if (ret == ACPI_INTERRUPT_HANDLED) +- pm_pr_dbg("ACPI EC GPE dispatched\n"); ++ spin_lock_irq(&first_ec->lock); ++ ++ if (acpi_ec_gpe_status_set(first_ec)) ++ work_in_progress = advance_transaction(first_ec, false); ++ ++ spin_unlock_irq(&first_ec->lock); ++ ++ if (!work_in_progress) ++ return false; ++ ++ pm_pr_dbg("ACPI EC GPE dispatched\n"); + + /* Drain EC work. */ + do { diff --git a/patches.suse/ACPI-EC-Fold-acpi_ec_check_event-into-acpi_ec_event_.patch b/patches.suse/ACPI-EC-Fold-acpi_ec_check_event-into-acpi_ec_event_.patch new file mode 100644 index 0000000..e99a689 --- /dev/null +++ b/patches.suse/ACPI-EC-Fold-acpi_ec_check_event-into-acpi_ec_event_.patch @@ -0,0 +1,64 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:39:05 +0100 +Subject: ACPI: EC: Fold acpi_ec_check_event() into acpi_ec_event_handler() +Patch-mainline: v5.17-rc1 +Git-commit: 98d364509d77e2d441ef6d8bdf13e1a4258eac6c +References: jsc#PED-1408 + +Because acpi_ec_event_handler() is the only caller of +acpi_ec_check_event() and the separation of these two functions +makes it harder to follow the code flow, fold the latter into the +former (and simplify that code while at it). + +No expected functional impact. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 28 +++++++++------------------- + 1 file changed, 9 insertions(+), 19 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1215,24 +1215,6 @@ err_exit: + return result; + } + +-static void acpi_ec_check_event(struct acpi_ec *ec) +-{ +- unsigned long flags; +- +- if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT) { +- if (ec_guard(ec)) { +- spin_lock_irqsave(&ec->lock, flags); +- /* +- * Take care of the SCI_EVT unless no one else is +- * taking care of it. +- */ +- if (!ec->curr) +- advance_transaction(ec, false); +- spin_unlock_irqrestore(&ec->lock, flags); +- } +- } +-} +- + static void acpi_ec_event_handler(struct work_struct *work) + { + unsigned long flags; +@@ -1264,7 +1246,15 @@ static void acpi_ec_event_handler(struct + + ec_dbg_evt("Event stopped"); + +- acpi_ec_check_event(ec); ++ if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && ec_guard(ec)) { ++ spin_lock_irqsave(&ec->lock, flags); ++ ++ /* Take care of SCI_EVT unless someone else is doing that. */ ++ if (!ec->curr) ++ advance_transaction(ec, false); ++ ++ spin_unlock_irqrestore(&ec->lock, flags); ++ } + + spin_lock_irqsave(&ec->lock, flags); + ec->events_in_progress--; diff --git a/patches.suse/ACPI-EC-Make-the-event-work-state-machine-visible.patch b/patches.suse/ACPI-EC-Make-the-event-work-state-machine-visible.patch new file mode 100644 index 0000000..b94e5f2 --- /dev/null +++ b/patches.suse/ACPI-EC-Make-the-event-work-state-machine-visible.patch @@ -0,0 +1,243 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:44:46 +0100 +Subject: ACPI: EC: Make the event work state machine visible +Patch-mainline: v5.17-rc1 +Git-commit: c33676aa48249b007d55198dc8348cd117e3d8cc +References: jsc#PED-1408 + +The EC driver uses a relatively simple state machine for the event +work handling, but it is not really straightforward to figure out. + +The states are as follows: + + "Ready": The event handling work can be submitted. + + In this state, the EC_FLAGS_QUERY_PENDING flag is clear. + + "In progress": The event handling work is pending or is being + processed. It cannot be submitted again. + + In ths state, the EC_FLAGS_QUERY_PENDING flag is set and both the + events_to_process count is nonzero and the EC_FLAGS_QUERY_GUARDING + flag is clear. + + "Complete": The event handling work has been completed, but it still + cannot be submitted again. + + In ths state, the EC_FLAGS_QUERY_PENDING flag is set and the + events_to_process count is zero or the EC_FLAGS_QUERY_GUARDING + flag is set. + +The state changes from "Ready" to "In progress" when new event is +detected by advance_transaction() and acpi_ec_submit_event() is +called by it. + +Next, the state can change from "In progress" directly to "Ready" in +the following situations: + + * ec_event_clearing is ACPI_EC_EVT_TIMING_STATUS and the state of + an ACPI_EC_COMMAND_QUERY transaction becomes ACPI_EC_COMMAND_POLL. + + * ec_event_clearing is ACPI_EC_EVT_TIMING_QUERY and the state of + an ACPI_EC_COMMAND_QUERY transaction becomes + ACPI_EC_COMMAND_COMPLETE. + + * ec_event_clearing is either ACPI_EC_EVT_TIMING_STATUS or + ACPI_EC_EVT_TIMING_QUERY and there are no more events to + process (ie. ec->events_to_process becomes 0). + +If ec_event_clearing is ACPI_EC_EVT_TIMING_EVENT, however, the +state must change from "In progress" to "Complete" before it +can change to "Ready". The changes from "In progress" to +"Complete" in that case occur in the following situations: + + * The state of an ACPI_EC_COMMAND_QUERY transaction becomes + ACPI_EC_COMMAND_COMPLETE. + + * There are no more events to process (ie. ec->events_to_process + becomes 0). + +Finally, the state changes from "Complete" to "Ready" when +advance_transaction() is invoked when the state is "Complete" and +the state of the current transaction is not ACPI_EC_COMMAND_POLL. + +To make this state machine visible in the code, add a new +event_state field to struct acpi_ec and modify the code to use +it istead the EC_FLAGS_QUERY_PENDING and EC_FLAGS_QUERY_GUARDING +flags. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 75 ++++++++++++++++++++++++++++-------------------- + drivers/acpi/internal.h | 8 +++++ + 2 files changed, 52 insertions(+), 31 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -92,8 +92,6 @@ enum ec_command { + + enum { + EC_FLAGS_QUERY_ENABLED, /* Query is enabled */ +- EC_FLAGS_QUERY_PENDING, /* Query is pending */ +- EC_FLAGS_QUERY_GUARDING, /* Guard for SCI_EVT check */ + EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */ + EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */ + EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */ +@@ -450,9 +448,11 @@ static bool acpi_ec_submit_event(struct + if (!acpi_ec_event_enabled(ec)) + return false; + +- if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { ++ if (ec->event_state == EC_EVENT_READY) { + ec_dbg_evt("Command(%s) submitted/blocked", + acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); ++ ++ ec->event_state = EC_EVENT_IN_PROGRESS; + /* + * If events_to_process is greqter than 0 at this point, the + * while () loop in acpi_ec_event_handler() is still running +@@ -474,11 +474,19 @@ static bool acpi_ec_submit_event(struct + return true; + } + ++static void acpi_ec_complete_event(struct acpi_ec *ec) ++{ ++ if (ec->event_state == EC_EVENT_IN_PROGRESS) ++ ec->event_state = EC_EVENT_COMPLETE; ++} ++ + static void acpi_ec_close_event(struct acpi_ec *ec) + { +- if (test_and_clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) ++ if (ec->event_state != EC_EVENT_READY) + ec_dbg_evt("Command(%s) unblocked", + acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); ++ ++ ec->event_state = EC_EVENT_READY; + acpi_ec_unmask_events(ec); + } + +@@ -565,8 +573,8 @@ void acpi_ec_flush_work(void) + + static bool acpi_ec_guard_event(struct acpi_ec *ec) + { +- bool guarded = true; + unsigned long flags; ++ bool guarded; + + spin_lock_irqsave(&ec->lock, flags); + /* +@@ -575,19 +583,15 @@ static bool acpi_ec_guard_event(struct a + * evaluating _Qxx, so we need to re-check SCI_EVT after waiting an + * acceptable period. + * +- * The guarding period begins when EC_FLAGS_QUERY_PENDING is +- * flagged, which means SCI_EVT check has just been performed. +- * But if the current transaction is ACPI_EC_COMMAND_QUERY, the +- * guarding should have already been performed (via +- * EC_FLAGS_QUERY_GUARDING) and should not be applied so that the +- * ACPI_EC_COMMAND_QUERY transaction can be transitioned into +- * ACPI_EC_COMMAND_POLL state immediately. ++ * The guarding period is applicable if the event state is not ++ * EC_EVENT_READY, but otherwise if the current transaction is of the ++ * ACPI_EC_COMMAND_QUERY type, the guarding should have elapsed already ++ * and it should not be applied to let the transaction transition into ++ * the ACPI_EC_COMMAND_POLL state immediately. + */ +- if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS || +- ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY || +- !test_bit(EC_FLAGS_QUERY_PENDING, &ec->flags) || +- (ec->curr && ec->curr->command == ACPI_EC_COMMAND_QUERY)) +- guarded = false; ++ guarded = ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && ++ ec->event_state != EC_EVENT_READY && ++ (!ec->curr || ec->curr->command != ACPI_EC_COMMAND_QUERY); + spin_unlock_irqrestore(&ec->lock, flags); + return guarded; + } +@@ -619,16 +623,26 @@ static int ec_transaction_completed(stru + static inline void ec_transaction_transition(struct acpi_ec *ec, unsigned long flag) + { + ec->curr->flags |= flag; +- if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { +- if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS && +- flag == ACPI_EC_COMMAND_POLL) ++ ++ if (ec->curr->command != ACPI_EC_COMMAND_QUERY) ++ return; ++ ++ switch (ec_event_clearing) { ++ case ACPI_EC_EVT_TIMING_STATUS: ++ if (flag == ACPI_EC_COMMAND_POLL) + acpi_ec_close_event(ec); +- if (ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY && +- flag == ACPI_EC_COMMAND_COMPLETE) ++ ++ return; ++ ++ case ACPI_EC_EVT_TIMING_QUERY: ++ if (flag == ACPI_EC_COMMAND_COMPLETE) + acpi_ec_close_event(ec); +- if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && +- flag == ACPI_EC_COMMAND_COMPLETE) +- set_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags); ++ ++ return; ++ ++ case ACPI_EC_EVT_TIMING_EVENT: ++ if (flag == ACPI_EC_COMMAND_COMPLETE) ++ acpi_ec_complete_event(ec); + } + } + +@@ -674,11 +688,9 @@ static bool advance_transaction(struct a + */ + if (!t || !(t->flags & ACPI_EC_COMMAND_POLL)) { + if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && +- (!ec->events_to_process || +- test_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags))) { +- clear_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags); ++ ec->event_state == EC_EVENT_COMPLETE) + acpi_ec_close_event(ec); +- } ++ + if (!t) + goto out; + } +@@ -1246,8 +1258,9 @@ static void acpi_ec_event_handler(struct + * event handling work again regardless of whether or not the query + * queued up above is processed successfully. + */ +- if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS || +- ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY) ++ if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT) ++ acpi_ec_complete_event(ec); ++ else + acpi_ec_close_event(ec); + + spin_unlock_irq(&ec->lock); +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -166,6 +166,13 @@ static inline void acpi_early_processor_ + /* -------------------------------------------------------------------------- + Embedded Controller + -------------------------------------------------------------------------- */ ++ ++enum acpi_ec_event_state { ++ EC_EVENT_READY = 0, /* Event work can be submitted */ ++ EC_EVENT_IN_PROGRESS, /* Event work is pending or being processed */ ++ EC_EVENT_COMPLETE, /* Event work processing has completed */ ++}; ++ + struct acpi_ec { + acpi_handle handle; + int gpe; +@@ -182,6 +189,7 @@ struct acpi_ec { + spinlock_t lock; + struct work_struct work; + unsigned long timestamp; ++ enum acpi_ec_event_state event_state; + unsigned int events_to_process; + unsigned int events_in_progress; + unsigned int queries_in_progress; diff --git a/patches.suse/ACPI-EC-Mark-the-ec_sys-write_support-param-as-modul.patch b/patches.suse/ACPI-EC-Mark-the-ec_sys-write_support-param-as-modul.patch new file mode 100644 index 0000000..4c59ac3 --- /dev/null +++ b/patches.suse/ACPI-EC-Mark-the-ec_sys-write_support-param-as-modul.patch @@ -0,0 +1,33 @@ +From: Hans de Goede +Date: Thu, 25 Nov 2021 11:36:16 +0100 +Subject: ACPI: EC: Mark the ec_sys write_support param as module_param_hw() +Patch-mainline: v5.17-rc1 +Git-commit: b66f86849414807745b5c2129e2de5f27a788c9f +References: jsc#PED-1408 + +Using write_support=1 with the ec_sys module changes the mode of the +"io" debugfs file to 0600. This will cause any attempts to access it under +a kernel in lockdown mode to return -EPERM, which makes the entire ec_sys +module unusable. + +Use the special module_param_hw() macro for module parameters which +may not be used while in lockdown mode, to avoid this. + +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec_sys.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/acpi/ec_sys.c ++++ b/drivers/acpi/ec_sys.c +@@ -19,7 +19,7 @@ MODULE_DESCRIPTION("ACPI EC sysfs access + MODULE_LICENSE("GPL"); + + static bool write_support; +-module_param(write_support, bool, 0644); ++module_param_hw(write_support, bool, other, 0644); + MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may " + "be needed."); + diff --git a/patches.suse/ACPI-EC-Pass-one-argument-to-acpi_ec_query.patch b/patches.suse/ACPI-EC-Pass-one-argument-to-acpi_ec_query.patch new file mode 100644 index 0000000..edf4b0d --- /dev/null +++ b/patches.suse/ACPI-EC-Pass-one-argument-to-acpi_ec_query.patch @@ -0,0 +1,105 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:38:21 +0100 +Subject: ACPI: EC: Pass one argument to acpi_ec_query() +Patch-mainline: v5.17-rc1 +Git-commit: 1f2350443dd21028d3de6907f98ff1be75a2c9bc +References: jsc#PED-1408 + +Notice that the second argument to acpi_ec_query() is redundant, +because in the only case when it is not NULL, the value passed +through it is only checked against 0 and it can only be 0 when +acpi_ec_query() returns an error code, but its return value +is checked along with the value passed through its second +argument. + +Accordingly, modify acpi_ec_query() to take only one argument +and while at it, change its handling of the case when +acpi_ec_transaction() returns an error so as to return that +error value to the caller right away. + +No expected functional impact. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -169,7 +169,7 @@ struct acpi_ec_query { + struct acpi_ec *ec; + }; + +-static int acpi_ec_query(struct acpi_ec *ec, u8 *data); ++static int acpi_ec_query(struct acpi_ec *ec); + static bool advance_transaction(struct acpi_ec *ec, bool interrupt); + static void acpi_ec_event_handler(struct work_struct *work); + static void acpi_ec_event_processor(struct work_struct *work); +@@ -496,12 +496,10 @@ static inline void __acpi_ec_disable_eve + */ + static void acpi_ec_clear(struct acpi_ec *ec) + { +- int i, status; +- u8 value = 0; ++ int i; + + for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) { +- status = acpi_ec_query(ec, &value); +- if (status || !value) ++ if (acpi_ec_query(ec)) + break; + } + if (unlikely(i == ACPI_EC_CLEAR_MAX)) +@@ -1164,11 +1162,11 @@ static void acpi_ec_event_processor(stru + acpi_ec_delete_query(q); + } + +-static int acpi_ec_query(struct acpi_ec *ec, u8 *data) ++static int acpi_ec_query(struct acpi_ec *ec) + { ++ struct acpi_ec_query *q; + u8 value = 0; + int result; +- struct acpi_ec_query *q; + + q = acpi_ec_create_query(ec, &value); + if (!q) +@@ -1180,11 +1178,14 @@ static int acpi_ec_query(struct acpi_ec + * bit to be cleared (and thus clearing the interrupt source). + */ + result = acpi_ec_transaction(ec, &q->transaction); +- if (!value) +- result = -ENODATA; + if (result) + goto err_exit; + ++ if (!value) { ++ result = -ENODATA; ++ goto err_exit; ++ } ++ + q->handler = acpi_ec_get_query_handler_by_value(ec, value); + if (!q->handler) { + result = -ENODATA; +@@ -1210,8 +1211,7 @@ static int acpi_ec_query(struct acpi_ec + err_exit: + if (result) + acpi_ec_delete_query(q); +- if (data) +- *data = value; ++ + return result; + } + +@@ -1243,7 +1243,9 @@ static void acpi_ec_event_handler(struct + spin_lock_irqsave(&ec->lock, flags); + while (ec->nr_pending_queries) { + spin_unlock_irqrestore(&ec->lock, flags); +- (void)acpi_ec_query(ec, NULL); ++ ++ acpi_ec_query(ec); ++ + spin_lock_irqsave(&ec->lock, flags); + ec->nr_pending_queries--; + /* diff --git a/patches.suse/ACPI-EC-Rearrange-the-loop-in-acpi_ec_event_handler.patch b/patches.suse/ACPI-EC-Rearrange-the-loop-in-acpi_ec_event_handler.patch new file mode 100644 index 0000000..2e481e1 --- /dev/null +++ b/patches.suse/ACPI-EC-Rearrange-the-loop-in-acpi_ec_event_handler.patch @@ -0,0 +1,54 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:40:04 +0100 +Subject: ACPI: EC: Rearrange the loop in acpi_ec_event_handler() +Patch-mainline: v5.17-rc1 +Git-commit: 388fb77dcf9793b9882e0f0651019f416ef50900 +References: jsc#PED-1408 + +It is not necessary to check ec->nr_pending_queries against 0 in the +while () loop in acpi_ec_event_handler(), because that loop terminates +when ec->nr_pending_queries is 0 and the code depending on that can be +run after the loop has ended. + +Modify the code accordingly and while at it rewrite the comment +regarding that code to make it clearer. + +No intentional functional impact. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1230,18 +1230,17 @@ static void acpi_ec_event_handler(struct + + spin_lock_irqsave(&ec->lock, flags); + ec->nr_pending_queries--; +- /* +- * Before exit, make sure that this work item can be +- * scheduled again. There might be QR_EC failures, leaving +- * EC_FLAGS_QUERY_PENDING uncleared and preventing this work +- * item from being scheduled again. +- */ +- if (!ec->nr_pending_queries) { +- if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS || +- ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY) +- acpi_ec_complete_query(ec); +- } + } ++ ++ /* ++ * Before exit, make sure that the it will be possible to queue up the ++ * event handling work again regardless of whether or not the query ++ * queued up above is processed successfully. ++ */ ++ if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS || ++ ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY) ++ acpi_ec_complete_query(ec); ++ + spin_unlock_irqrestore(&ec->lock, flags); + + ec_dbg_evt("Event stopped"); diff --git a/patches.suse/ACPI-EC-Relocate-acpi_ec_create_query-and-drop-acpi_.patch b/patches.suse/ACPI-EC-Relocate-acpi_ec_create_query-and-drop-acpi_.patch new file mode 100644 index 0000000..0620902 --- /dev/null +++ b/patches.suse/ACPI-EC-Relocate-acpi_ec_create_query-and-drop-acpi_.patch @@ -0,0 +1,105 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:46:09 +0100 +Subject: ACPI: EC: Relocate acpi_ec_create_query() and drop + acpi_ec_delete_query() +Patch-mainline: v5.17-rc1 +Git-commit: befd9b5b0c621af33a363596c65a8fc0176e2795 +References: jsc#PED-1408 + +Move acpi_ec_create_query() after acpi_ec_event_processor(), drop the +no longer needed forward declaration of the latter, and eliminate +acpi_ec_delete_query() which isn't really necessary. + +No intentional functional impact. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 54 +++++++++++++++++++++++------------------------------- + 1 file changed, 23 insertions(+), 31 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -170,7 +170,6 @@ struct acpi_ec_query { + static int acpi_ec_submit_query(struct acpi_ec *ec); + static bool advance_transaction(struct acpi_ec *ec, bool interrupt); + static void acpi_ec_event_handler(struct work_struct *work); +-static void acpi_ec_event_processor(struct work_struct *work); + + struct acpi_ec *first_ec; + EXPORT_SYMBOL(first_ec); +@@ -1134,33 +1133,6 @@ void acpi_ec_remove_query_handler(struct + } + EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); + +-static struct acpi_ec_query *acpi_ec_create_query(struct acpi_ec *ec, u8 *pval) +-{ +- struct acpi_ec_query *q; +- struct transaction *t; +- +- q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL); +- if (!q) +- return NULL; +- +- INIT_WORK(&q->work, acpi_ec_event_processor); +- t = &q->transaction; +- t->command = ACPI_EC_COMMAND_QUERY; +- t->rdata = pval; +- t->rlen = 1; +- q->ec = ec; +- return q; +-} +- +-static void acpi_ec_delete_query(struct acpi_ec_query *q) +-{ +- if (q) { +- if (q->handler) +- acpi_ec_put_query_handler(q->handler); +- kfree(q); +- } +-} +- + static void acpi_ec_event_processor(struct work_struct *work) + { + struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work); +@@ -1180,7 +1152,26 @@ static void acpi_ec_event_processor(stru + ec->queries_in_progress--; + spin_unlock_irq(&ec->lock); + +- acpi_ec_delete_query(q); ++ acpi_ec_put_query_handler(handler); ++ kfree(q); ++} ++ ++static struct acpi_ec_query *acpi_ec_create_query(struct acpi_ec *ec, u8 *pval) ++{ ++ struct acpi_ec_query *q; ++ struct transaction *t; ++ ++ q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL); ++ if (!q) ++ return NULL; ++ ++ INIT_WORK(&q->work, acpi_ec_event_processor); ++ t = &q->transaction; ++ t->command = ACPI_EC_COMMAND_QUERY; ++ t->rdata = pval; ++ t->rlen = 1; ++ q->ec = ec; ++ return q; + } + + static int acpi_ec_submit_query(struct acpi_ec *ec) +@@ -1229,9 +1220,10 @@ static int acpi_ec_submit_query(struct a + + spin_unlock_irq(&ec->lock); + ++ return 0; ++ + err_exit: +- if (result) +- acpi_ec_delete_query(q); ++ kfree(q); + + return result; + } diff --git a/patches.suse/ACPI-EC-Rename-three-functions.patch b/patches.suse/ACPI-EC-Rename-three-functions.patch new file mode 100644 index 0000000..f870d8c --- /dev/null +++ b/patches.suse/ACPI-EC-Rename-three-functions.patch @@ -0,0 +1,116 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:42:02 +0100 +Subject: ACPI: EC: Rename three functions +Patch-mainline: v5.17-rc1 +Git-commit: eafe7509ab8c8a200a169bc378fc9a56164acc66 +References: jsc#PED-1408 + +Rename acpi_ec_submit_query() to acpi_ec_submit_event(), +acpi_ec_query() to acpi_ec_submit_query(), and +acpi_ec_complete_query() to acpi_ec_close_event() to make +the names reflect what the functions do. + +No expected functional impact. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -169,7 +169,7 @@ struct acpi_ec_query { + struct acpi_ec *ec; + }; + +-static int acpi_ec_query(struct acpi_ec *ec); ++static int acpi_ec_submit_query(struct acpi_ec *ec); + static bool advance_transaction(struct acpi_ec *ec, bool interrupt); + static void acpi_ec_event_handler(struct work_struct *work); + static void acpi_ec_event_processor(struct work_struct *work); +@@ -444,7 +444,7 @@ static bool acpi_ec_submit_flushable_req + return true; + } + +-static bool acpi_ec_submit_query(struct acpi_ec *ec) ++static bool acpi_ec_submit_event(struct acpi_ec *ec) + { + acpi_ec_mask_events(ec); + if (!acpi_ec_event_enabled(ec)) +@@ -465,7 +465,7 @@ static bool acpi_ec_submit_query(struct + return true; + } + +-static void acpi_ec_complete_query(struct acpi_ec *ec) ++static void acpi_ec_close_event(struct acpi_ec *ec) + { + if (test_and_clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) + ec_dbg_evt("Command(%s) unblocked", +@@ -499,7 +499,7 @@ static void acpi_ec_clear(struct acpi_ec + int i; + + for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) { +- if (acpi_ec_query(ec)) ++ if (acpi_ec_submit_query(ec)) + break; + } + if (unlikely(i == ACPI_EC_CLEAR_MAX)) +@@ -613,10 +613,10 @@ static inline void ec_transaction_transi + if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { + if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS && + flag == ACPI_EC_COMMAND_POLL) +- acpi_ec_complete_query(ec); ++ acpi_ec_close_event(ec); + if (ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY && + flag == ACPI_EC_COMMAND_COMPLETE) +- acpi_ec_complete_query(ec); ++ acpi_ec_close_event(ec); + if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && + flag == ACPI_EC_COMMAND_COMPLETE) + set_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags); +@@ -668,7 +668,7 @@ static bool advance_transaction(struct a + (!ec->nr_pending_queries || + test_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags))) { + clear_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags); +- acpi_ec_complete_query(ec); ++ acpi_ec_close_event(ec); + } + if (!t) + goto out; +@@ -704,7 +704,7 @@ static bool advance_transaction(struct a + + out: + if (status & ACPI_EC_FLAG_SCI) +- ret = acpi_ec_submit_query(ec); ++ ret = acpi_ec_submit_event(ec); + + if (wakeup && interrupt) + wake_up(&ec->wait); +@@ -1162,7 +1162,7 @@ static void acpi_ec_event_processor(stru + acpi_ec_delete_query(q); + } + +-static int acpi_ec_query(struct acpi_ec *ec) ++static int acpi_ec_submit_query(struct acpi_ec *ec) + { + struct acpi_ec_query *q; + u8 value = 0; +@@ -1226,7 +1226,7 @@ static void acpi_ec_event_handler(struct + while (ec->nr_pending_queries) { + spin_unlock_irq(&ec->lock); + +- acpi_ec_query(ec); ++ acpi_ec_submit_query(ec); + + spin_lock_irq(&ec->lock); + ec->nr_pending_queries--; +@@ -1239,7 +1239,7 @@ static void acpi_ec_event_handler(struct + */ + if (ec_event_clearing == ACPI_EC_EVT_TIMING_STATUS || + ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY) +- acpi_ec_complete_query(ec); ++ acpi_ec_close_event(ec); + + spin_unlock_irq(&ec->lock); + diff --git a/patches.suse/ACPI-EC-Rework-flushing-of-EC-work-while-suspended-t.patch b/patches.suse/ACPI-EC-Rework-flushing-of-EC-work-while-suspended-t.patch new file mode 100644 index 0000000..2577bae --- /dev/null +++ b/patches.suse/ACPI-EC-Rework-flushing-of-EC-work-while-suspended-t.patch @@ -0,0 +1,209 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:36:51 +0100 +Subject: ACPI: EC: Rework flushing of EC work while suspended to idle +Patch-mainline: v5.17-rc1 +Git-commit: 4a9af6cac050dce2e895ec3205c4615383ad9112 +References: jsc#PED-1408 + +The flushing of pending work in the EC driver uses drain_workqueue() +to flush the event handling work that can requeue itself via +advance_transaction(), but this is problematic, because that +work may also be requeued from the query workqueue. + +Namely, if an EC transaction is carried out during the execution of +a query handler, it involves calling advance_transaction() which +may queue up the event handling work again. This causes the kernel +to complain about attempts to add a work item to the EC event +workqueue while it is being drained and worst-case it may cause a +valid event to be skipped. + +To avoid this problem, introduce two new counters, events_in_progress +and queries_in_progress, incremented when a work item is queued on +the event workqueue or the query workqueue, respectively, and +decremented at the end of the corresponding work function, and make +acpi_ec_dispatch_gpe() the workqueues in a loop until the both of +these counters are zero (or system wakeup is pending) instead of +calling acpi_ec_flush_work(). + +At the same time, change __acpi_ec_flush_work() to call +flush_workqueue() instead of drain_workqueue() to flush the event +workqueue. + +While at it, use the observation that the work item queued in +acpi_ec_query() cannot be pending at that time, because it is used +only once, to simplify the code in there. + +Additionally, clean up a comment in acpi_ec_query() and adjust white +space in acpi_ec_event_processor(). + +Fixes: f0ac20c3f613 ("ACPI: EC: Fix flushing of pending work") +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 57 ++++++++++++++++++++++++++++++++++++------------ + drivers/acpi/internal.h | 2 + + 2 files changed, 45 insertions(+), 14 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -166,6 +166,7 @@ struct acpi_ec_query { + struct transaction transaction; + struct work_struct work; + struct acpi_ec_query_handler *handler; ++ struct acpi_ec *ec; + }; + + static int acpi_ec_query(struct acpi_ec *ec, u8 *data); +@@ -452,6 +453,7 @@ static void acpi_ec_submit_query(struct + ec_dbg_evt("Command(%s) submitted/blocked", + acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); + ec->nr_pending_queries++; ++ ec->events_in_progress++; + queue_work(ec_wq, &ec->work); + } + } +@@ -518,7 +520,7 @@ static void acpi_ec_enable_event(struct + #ifdef CONFIG_PM_SLEEP + static void __acpi_ec_flush_work(void) + { +- drain_workqueue(ec_wq); /* flush ec->work */ ++ flush_workqueue(ec_wq); /* flush ec->work */ + flush_workqueue(ec_query_wq); /* flush queries */ + } + +@@ -1103,7 +1105,7 @@ void acpi_ec_remove_query_handler(struct + } + EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); + +-static struct acpi_ec_query *acpi_ec_create_query(u8 *pval) ++static struct acpi_ec_query *acpi_ec_create_query(struct acpi_ec *ec, u8 *pval) + { + struct acpi_ec_query *q; + struct transaction *t; +@@ -1111,11 +1113,13 @@ static struct acpi_ec_query *acpi_ec_cre + q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL); + if (!q) + return NULL; ++ + INIT_WORK(&q->work, acpi_ec_event_processor); + t = &q->transaction; + t->command = ACPI_EC_COMMAND_QUERY; + t->rdata = pval; + t->rlen = 1; ++ q->ec = ec; + return q; + } + +@@ -1132,13 +1136,21 @@ static void acpi_ec_event_processor(stru + { + struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work); + struct acpi_ec_query_handler *handler = q->handler; ++ struct acpi_ec *ec = q->ec; + + ec_dbg_evt("Query(0x%02x) started", handler->query_bit); ++ + if (handler->func) + handler->func(handler->data); + else if (handler->handle) + acpi_evaluate_object(handler->handle, NULL, NULL, NULL); ++ + ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit); ++ ++ spin_lock_irq(&ec->lock); ++ ec->queries_in_progress--; ++ spin_unlock_irq(&ec->lock); ++ + acpi_ec_delete_query(q); + } + +@@ -1148,7 +1160,7 @@ static int acpi_ec_query(struct acpi_ec + int result; + struct acpi_ec_query *q; + +- q = acpi_ec_create_query(&value); ++ q = acpi_ec_create_query(ec, &value); + if (!q) + return -ENOMEM; + +@@ -1170,19 +1182,20 @@ static int acpi_ec_query(struct acpi_ec + } + + /* +- * It is reported that _Qxx are evaluated in a parallel way on +- * Windows: ++ * It is reported that _Qxx are evaluated in a parallel way on Windows: + * https://bugzilla.kernel.org/show_bug.cgi?id=94411 + * +- * Put this log entry before schedule_work() in order to make +- * it appearing before any other log entries occurred during the +- * work queue execution. ++ * Put this log entry before queue_work() to make it appear in the log ++ * before any other messages emitted during workqueue handling. + */ + ec_dbg_evt("Query(0x%02x) scheduled", value); +- if (!queue_work(ec_query_wq, &q->work)) { +- ec_dbg_evt("Query(0x%02x) overlapped", value); +- result = -EBUSY; +- } ++ ++ spin_lock_irq(&ec->lock); ++ ++ ec->queries_in_progress++; ++ queue_work(ec_query_wq, &q->work); ++ ++ spin_unlock_irq(&ec->lock); + + err_exit: + if (result) +@@ -1240,6 +1253,10 @@ static void acpi_ec_event_handler(struct + ec_dbg_evt("Event stopped"); + + acpi_ec_check_event(ec); ++ ++ spin_lock_irqsave(&ec->lock, flags); ++ ec->events_in_progress--; ++ spin_unlock_irqrestore(&ec->lock, flags); + } + + static void acpi_ec_handle_interrupt(struct acpi_ec *ec) +@@ -2021,6 +2038,7 @@ void acpi_ec_set_gpe_wake_mask(u8 action + + bool acpi_ec_dispatch_gpe(void) + { ++ bool work_in_progress; + u32 ret; + + if (!first_ec) +@@ -2041,8 +2059,19 @@ bool acpi_ec_dispatch_gpe(void) + if (ret == ACPI_INTERRUPT_HANDLED) + pm_pr_dbg("ACPI EC GPE dispatched\n"); + +- /* Flush the event and query workqueues. */ +- acpi_ec_flush_work(); ++ /* Drain EC work. */ ++ do { ++ acpi_ec_flush_work(); ++ ++ pm_pr_dbg("ACPI EC work flushed\n"); ++ ++ spin_lock_irq(&first_ec->lock); ++ ++ work_in_progress = first_ec->events_in_progress + ++ first_ec->queries_in_progress > 0; ++ ++ spin_unlock_irq(&first_ec->lock); ++ } while (work_in_progress && !pm_wakeup_pending()); + + return false; + } +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -183,6 +183,8 @@ struct acpi_ec { + struct work_struct work; + unsigned long timestamp; + unsigned long nr_pending_queries; ++ unsigned int events_in_progress; ++ unsigned int queries_in_progress; + bool busy_polling; + unsigned int polling_guard; + }; diff --git a/patches.suse/ACPI-EC-Simplify-locking-in-acpi_ec_event_handler.patch b/patches.suse/ACPI-EC-Simplify-locking-in-acpi_ec_event_handler.patch new file mode 100644 index 0000000..7162adb --- /dev/null +++ b/patches.suse/ACPI-EC-Simplify-locking-in-acpi_ec_event_handler.patch @@ -0,0 +1,75 @@ +From: "Rafael J. Wysocki" +Date: Tue, 23 Nov 2021 19:40:50 +0100 +Subject: ACPI: EC: Simplify locking in acpi_ec_event_handler() +Patch-mainline: v5.17-rc1 +Git-commit: a105acd7e38436ed6bc0714f3120aaaad56cbe3d +References: jsc#PED-1408 + +Because acpi_ec_event_handler() is a work function, it always +runs in process context with interrupts enabled, so it can use +spin_lock_irq() and spin_unlock_irq() for the locking. + +Make it do so and adjust white space around those calls. + +No expected functional impact. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ec.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1217,18 +1217,18 @@ err_exit: + + static void acpi_ec_event_handler(struct work_struct *work) + { +- unsigned long flags; + struct acpi_ec *ec = container_of(work, struct acpi_ec, work); + + ec_dbg_evt("Event started"); + +- spin_lock_irqsave(&ec->lock, flags); ++ spin_lock_irq(&ec->lock); ++ + while (ec->nr_pending_queries) { +- spin_unlock_irqrestore(&ec->lock, flags); ++ spin_unlock_irq(&ec->lock); + + acpi_ec_query(ec); + +- spin_lock_irqsave(&ec->lock, flags); ++ spin_lock_irq(&ec->lock); + ec->nr_pending_queries--; + } + +@@ -1241,23 +1241,23 @@ static void acpi_ec_event_handler(struct + ec_event_clearing == ACPI_EC_EVT_TIMING_QUERY) + acpi_ec_complete_query(ec); + +- spin_unlock_irqrestore(&ec->lock, flags); ++ spin_unlock_irq(&ec->lock); + + ec_dbg_evt("Event stopped"); + + if (ec_event_clearing == ACPI_EC_EVT_TIMING_EVENT && ec_guard(ec)) { +- spin_lock_irqsave(&ec->lock, flags); ++ spin_lock_irq(&ec->lock); + + /* Take care of SCI_EVT unless someone else is doing that. */ + if (!ec->curr) + advance_transaction(ec, false); + +- spin_unlock_irqrestore(&ec->lock, flags); ++ spin_unlock_irq(&ec->lock); + } + +- spin_lock_irqsave(&ec->lock, flags); ++ spin_lock_irq(&ec->lock); + ec->events_in_progress--; +- spin_unlock_irqrestore(&ec->lock, flags); ++ spin_unlock_irq(&ec->lock); + } + + static void acpi_ec_handle_interrupt(struct acpi_ec *ec) diff --git a/patches.suse/ACPI-Introduce-Platform-Firmware-Runtime-Telemetry-d.patch b/patches.suse/ACPI-Introduce-Platform-Firmware-Runtime-Telemetry-d.patch new file mode 100644 index 0000000..c2c676c --- /dev/null +++ b/patches.suse/ACPI-Introduce-Platform-Firmware-Runtime-Telemetry-d.patch @@ -0,0 +1,590 @@ +From: Chen Yu +Date: Wed, 22 Dec 2021 12:32:02 +0800 +Subject: ACPI: Introduce Platform Firmware Runtime Telemetry driver +Patch-mainline: v5.17-rc1 +Git-commit: b0013e037a8b07772c74ce24f1ae4743b30fc3cf +References: jsc#PED-1408 + +This driver allows user space to fetch telemetry data from the +firmware with the help of the Platform Firmware Runtime Telemetry +interface. + +Both PFRU and PFRT are based on ACPI _DSM interfaces located under +special device objects in the ACPI Namespace, but these interfaces +are different from each other, so it is better to provide a separate +driver from each of them, even though they share some common +definitions and naming conventions. + +Tested-by: Hongyu Ning +Signed-off-by: Chen Yu +[ rjw: Subject and changelog edits ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/Kconfig | 8 + drivers/acpi/Makefile | 2 + drivers/acpi/pfr_telemetry.c | 434 +++++++++++++++++++++++++++++++++++++++++++ + include/uapi/linux/pfrut.h | 88 ++++++++ + 4 files changed, 529 insertions(+), 3 deletions(-) + create mode 100644 drivers/acpi/pfr_telemetry.c + +--- a/drivers/acpi/Kconfig ++++ b/drivers/acpi/Kconfig +@@ -535,8 +535,12 @@ config ACPI_PFRUT + The existing firmware code can be modified (driver update) or + extended by adding new code to the firmware (code injection). + +- To compile this driver as module, choose M here: +- the module will be called pfr_update. ++ Besides, the telemetry driver allows user space to fetch telemetry ++ data from the firmware with the help of the Platform Firmware Runtime ++ Telemetry interface. ++ ++ To compile the drivers as modules, choose M here: ++ the modules will be called pfr_update and pfr_telemetry. + + if ARM64 + source "drivers/acpi/arm64/Kconfig" +--- a/drivers/acpi/Makefile ++++ b/drivers/acpi/Makefile +@@ -102,7 +102,7 @@ obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi + obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o + obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o + obj-$(CONFIG_ACPI_PPTT) += pptt.o +-obj-$(CONFIG_ACPI_PFRUT) += pfr_update.o ++obj-$(CONFIG_ACPI_PFRUT) += pfr_update.o pfr_telemetry.o + + # processor has its own "processor." module_param namespace + processor-y := processor_driver.o +--- /dev/null ++++ b/drivers/acpi/pfr_telemetry.c +@@ -0,0 +1,434 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * ACPI Platform Firmware Runtime Telemetry driver ++ * ++ * Copyright (C) 2021 Intel Corporation ++ * Author: Chen Yu ++ * ++ * This driver allows user space to fetch telemetry data from the ++ * firmware with the help of the Platform Firmware Runtime Telemetry ++ * interface. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define PFRT_LOG_EXEC_IDX 0 ++#define PFRT_LOG_HISTORY_IDX 1 ++ ++#define PFRT_LOG_ERR 0 ++#define PFRT_LOG_WARN 1 ++#define PFRT_LOG_INFO 2 ++#define PFRT_LOG_VERB 4 ++ ++#define PFRT_FUNC_SET_LEV 1 ++#define PFRT_FUNC_GET_LEV 2 ++#define PFRT_FUNC_GET_DATA 3 ++ ++#define PFRT_REVID_1 1 ++#define PFRT_REVID_2 2 ++#define PFRT_DEFAULT_REV_ID PFRT_REVID_1 ++ ++enum log_index { ++ LOG_STATUS_IDX = 0, ++ LOG_EXT_STATUS_IDX = 1, ++ LOG_MAX_SZ_IDX = 2, ++ LOG_CHUNK1_LO_IDX = 3, ++ LOG_CHUNK1_HI_IDX = 4, ++ LOG_CHUNK1_SZ_IDX = 5, ++ LOG_CHUNK2_LO_IDX = 6, ++ LOG_CHUNK2_HI_IDX = 7, ++ LOG_CHUNK2_SZ_IDX = 8, ++ LOG_ROLLOVER_CNT_IDX = 9, ++ LOG_RESET_CNT_IDX = 10, ++ LOG_NR_IDX ++}; ++ ++struct pfrt_log_device { ++ int index; ++ struct pfrt_log_info info; ++ struct device *parent_dev; ++ struct miscdevice miscdev; ++}; ++ ++/* pfrt_guid is the parameter for _DSM method */ ++static const guid_t pfrt_log_guid = ++ GUID_INIT(0x75191659, 0x8178, 0x4D9D, 0xB8, 0x8F, 0xAC, 0x5E, ++ 0x5E, 0x93, 0xE8, 0xBF); ++ ++static DEFINE_IDA(pfrt_log_ida); ++ ++static inline struct pfrt_log_device *to_pfrt_log_dev(struct file *file) ++{ ++ return container_of(file->private_data, struct pfrt_log_device, miscdev); ++} ++ ++static int get_pfrt_log_data_info(struct pfrt_log_data_info *data_info, ++ struct pfrt_log_device *pfrt_log_dev) ++{ ++ acpi_handle handle = ACPI_HANDLE(pfrt_log_dev->parent_dev); ++ union acpi_object *out_obj, in_obj, in_buf; ++ int ret = -EBUSY; ++ ++ memset(&in_obj, 0, sizeof(in_obj)); ++ memset(&in_buf, 0, sizeof(in_buf)); ++ in_obj.type = ACPI_TYPE_PACKAGE; ++ in_obj.package.count = 1; ++ in_obj.package.elements = &in_buf; ++ in_buf.type = ACPI_TYPE_INTEGER; ++ in_buf.integer.value = pfrt_log_dev->info.log_type; ++ ++ out_obj = acpi_evaluate_dsm_typed(handle, &pfrt_log_guid, ++ pfrt_log_dev->info.log_revid, PFRT_FUNC_GET_DATA, ++ &in_obj, ACPI_TYPE_PACKAGE); ++ if (!out_obj) ++ return -EINVAL; ++ ++ if (out_obj->package.count < LOG_NR_IDX || ++ out_obj->package.elements[LOG_STATUS_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_EXT_STATUS_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_MAX_SZ_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_CHUNK1_LO_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_CHUNK1_HI_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_CHUNK1_SZ_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_CHUNK2_LO_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_CHUNK2_HI_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_CHUNK2_SZ_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_ROLLOVER_CNT_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[LOG_RESET_CNT_IDX].type != ACPI_TYPE_INTEGER) ++ goto free_acpi_buffer; ++ ++ data_info->status = out_obj->package.elements[LOG_STATUS_IDX].integer.value; ++ data_info->ext_status = ++ out_obj->package.elements[LOG_EXT_STATUS_IDX].integer.value; ++ if (data_info->status != DSM_SUCCEED) { ++ dev_dbg(pfrt_log_dev->parent_dev, "Error Status:%d\n", data_info->status); ++ dev_dbg(pfrt_log_dev->parent_dev, "Error Extend Status:%d\n", ++ data_info->ext_status); ++ goto free_acpi_buffer; ++ } ++ ++ data_info->max_data_size = ++ out_obj->package.elements[LOG_MAX_SZ_IDX].integer.value; ++ data_info->chunk1_addr_lo = ++ out_obj->package.elements[LOG_CHUNK1_LO_IDX].integer.value; ++ data_info->chunk1_addr_hi = ++ out_obj->package.elements[LOG_CHUNK1_HI_IDX].integer.value; ++ data_info->chunk1_size = ++ out_obj->package.elements[LOG_CHUNK1_SZ_IDX].integer.value; ++ data_info->chunk2_addr_lo = ++ out_obj->package.elements[LOG_CHUNK2_LO_IDX].integer.value; ++ data_info->chunk2_addr_hi = ++ out_obj->package.elements[LOG_CHUNK2_HI_IDX].integer.value; ++ data_info->chunk2_size = ++ out_obj->package.elements[LOG_CHUNK2_SZ_IDX].integer.value; ++ data_info->rollover_cnt = ++ out_obj->package.elements[LOG_ROLLOVER_CNT_IDX].integer.value; ++ data_info->reset_cnt = ++ out_obj->package.elements[LOG_RESET_CNT_IDX].integer.value; ++ ++ ret = 0; ++ ++free_acpi_buffer: ++ kfree(out_obj); ++ ++ return ret; ++} ++ ++static int set_pfrt_log_level(int level, struct pfrt_log_device *pfrt_log_dev) ++{ ++ acpi_handle handle = ACPI_HANDLE(pfrt_log_dev->parent_dev); ++ union acpi_object *out_obj, *obj, in_obj, in_buf; ++ enum pfru_dsm_status status, ext_status; ++ int ret = 0; ++ ++ memset(&in_obj, 0, sizeof(in_obj)); ++ memset(&in_buf, 0, sizeof(in_buf)); ++ in_obj.type = ACPI_TYPE_PACKAGE; ++ in_obj.package.count = 1; ++ in_obj.package.elements = &in_buf; ++ in_buf.type = ACPI_TYPE_INTEGER; ++ in_buf.integer.value = level; ++ ++ out_obj = acpi_evaluate_dsm_typed(handle, &pfrt_log_guid, ++ pfrt_log_dev->info.log_revid, PFRT_FUNC_SET_LEV, ++ &in_obj, ACPI_TYPE_PACKAGE); ++ if (!out_obj) ++ return -EINVAL; ++ ++ obj = &out_obj->package.elements[0]; ++ status = obj->integer.value; ++ if (status != DSM_SUCCEED) { ++ obj = &out_obj->package.elements[1]; ++ ext_status = obj->integer.value; ++ dev_dbg(pfrt_log_dev->parent_dev, "Error Status:%d\n", status); ++ dev_dbg(pfrt_log_dev->parent_dev, "Error Extend Status:%d\n", ext_status); ++ ret = -EBUSY; ++ } ++ ++ kfree(out_obj); ++ ++ return ret; ++} ++ ++static int get_pfrt_log_level(struct pfrt_log_device *pfrt_log_dev) ++{ ++ acpi_handle handle = ACPI_HANDLE(pfrt_log_dev->parent_dev); ++ union acpi_object *out_obj, *obj; ++ enum pfru_dsm_status status, ext_status; ++ int ret = -EBUSY; ++ ++ out_obj = acpi_evaluate_dsm_typed(handle, &pfrt_log_guid, ++ pfrt_log_dev->info.log_revid, PFRT_FUNC_GET_LEV, ++ NULL, ACPI_TYPE_PACKAGE); ++ if (!out_obj) ++ return -EINVAL; ++ ++ obj = &out_obj->package.elements[0]; ++ if (obj->type != ACPI_TYPE_INTEGER) ++ goto free_acpi_buffer; ++ ++ status = obj->integer.value; ++ if (status != DSM_SUCCEED) { ++ obj = &out_obj->package.elements[1]; ++ ext_status = obj->integer.value; ++ dev_dbg(pfrt_log_dev->parent_dev, "Error Status:%d\n", status); ++ dev_dbg(pfrt_log_dev->parent_dev, "Error Extend Status:%d\n", ext_status); ++ goto free_acpi_buffer; ++ } ++ ++ obj = &out_obj->package.elements[2]; ++ if (obj->type != ACPI_TYPE_INTEGER) ++ goto free_acpi_buffer; ++ ++ ret = obj->integer.value; ++ ++free_acpi_buffer: ++ kfree(out_obj); ++ ++ return ret; ++} ++ ++static int valid_log_level(u32 level) ++{ ++ return level == PFRT_LOG_ERR || level == PFRT_LOG_WARN || ++ level == PFRT_LOG_INFO || level == PFRT_LOG_VERB; ++} ++ ++static int valid_log_type(u32 type) ++{ ++ return type == PFRT_LOG_EXEC_IDX || type == PFRT_LOG_HISTORY_IDX; ++} ++ ++static inline int valid_log_revid(u32 id) ++{ ++ return id == PFRT_REVID_1 || id == PFRT_REVID_2; ++} ++ ++static long pfrt_log_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ struct pfrt_log_device *pfrt_log_dev = to_pfrt_log_dev(file); ++ struct pfrt_log_data_info data_info; ++ struct pfrt_log_info info; ++ void __user *p; ++ int ret = 0; ++ ++ p = (void __user *)arg; ++ ++ switch (cmd) { ++ case PFRT_LOG_IOC_SET_INFO: ++ if (copy_from_user(&info, p, sizeof(info))) ++ return -EFAULT; ++ ++ if (valid_log_revid(info.log_revid)) ++ pfrt_log_dev->info.log_revid = info.log_revid; ++ ++ if (valid_log_level(info.log_level)) { ++ ret = set_pfrt_log_level(info.log_level, pfrt_log_dev); ++ if (ret < 0) ++ return ret; ++ ++ pfrt_log_dev->info.log_level = info.log_level; ++ } ++ ++ if (valid_log_type(info.log_type)) ++ pfrt_log_dev->info.log_type = info.log_type; ++ ++ return 0; ++ ++ case PFRT_LOG_IOC_GET_INFO: ++ info.log_level = get_pfrt_log_level(pfrt_log_dev); ++ if (ret < 0) ++ return ret; ++ ++ info.log_type = pfrt_log_dev->info.log_type; ++ info.log_revid = pfrt_log_dev->info.log_revid; ++ if (copy_to_user(p, &info, sizeof(info))) ++ return -EFAULT; ++ ++ return 0; ++ ++ case PFRT_LOG_IOC_GET_DATA_INFO: ++ ret = get_pfrt_log_data_info(&data_info, pfrt_log_dev); ++ if (ret) ++ return ret; ++ ++ if (copy_to_user(p, &data_info, sizeof(struct pfrt_log_data_info))) ++ return -EFAULT; ++ ++ return 0; ++ ++ default: ++ return -ENOTTY; ++ } ++} ++ ++static int ++pfrt_log_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct pfrt_log_device *pfrt_log_dev; ++ struct pfrt_log_data_info info; ++ unsigned long psize, vsize; ++ phys_addr_t base_addr; ++ int ret; ++ ++ if (vma->vm_flags & VM_WRITE) ++ return -EROFS; ++ ++ /* changing from read to write with mprotect is not allowed */ ++ vma->vm_flags &= ~VM_MAYWRITE; ++ ++ pfrt_log_dev = to_pfrt_log_dev(file); ++ ++ ret = get_pfrt_log_data_info(&info, pfrt_log_dev); ++ if (ret) ++ return ret; ++ ++ base_addr = (phys_addr_t)((info.chunk2_addr_hi << 32) | info.chunk2_addr_lo); ++ /* pfrt update has not been launched yet */ ++ if (!base_addr) ++ return -ENODEV; ++ ++ psize = info.max_data_size; ++ /* base address and total buffer size must be page aligned */ ++ if (!PAGE_ALIGNED(base_addr) || !PAGE_ALIGNED(psize)) ++ return -ENODEV; ++ ++ vsize = vma->vm_end - vma->vm_start; ++ if (vsize > psize) ++ return -EINVAL; ++ ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ if (io_remap_pfn_range(vma, vma->vm_start, PFN_DOWN(base_addr), ++ vsize, vma->vm_page_prot)) ++ return -EAGAIN; ++ ++ return 0; ++} ++ ++static const struct file_operations acpi_pfrt_log_fops = { ++ .owner = THIS_MODULE, ++ .mmap = pfrt_log_mmap, ++ .unlocked_ioctl = pfrt_log_ioctl, ++ .llseek = noop_llseek, ++}; ++ ++static int acpi_pfrt_log_remove(struct platform_device *pdev) ++{ ++ struct pfrt_log_device *pfrt_log_dev = platform_get_drvdata(pdev); ++ ++ misc_deregister(&pfrt_log_dev->miscdev); ++ ++ return 0; ++} ++ ++static void pfrt_log_put_idx(void *data) ++{ ++ struct pfrt_log_device *pfrt_log_dev = data; ++ ++ ida_free(&pfrt_log_ida, pfrt_log_dev->index); ++} ++ ++static int acpi_pfrt_log_probe(struct platform_device *pdev) ++{ ++ acpi_handle handle = ACPI_HANDLE(&pdev->dev); ++ struct pfrt_log_device *pfrt_log_dev; ++ int ret; ++ ++ if (!acpi_has_method(handle, "_DSM")) { ++ dev_dbg(&pdev->dev, "Missing _DSM\n"); ++ return -ENODEV; ++ } ++ ++ pfrt_log_dev = devm_kzalloc(&pdev->dev, sizeof(*pfrt_log_dev), GFP_KERNEL); ++ if (!pfrt_log_dev) ++ return -ENOMEM; ++ ++ ret = ida_alloc(&pfrt_log_ida, GFP_KERNEL); ++ if (ret < 0) ++ return ret; ++ ++ pfrt_log_dev->index = ret; ++ ret = devm_add_action_or_reset(&pdev->dev, pfrt_log_put_idx, pfrt_log_dev); ++ if (ret) ++ return ret; ++ ++ pfrt_log_dev->info.log_revid = PFRT_DEFAULT_REV_ID; ++ pfrt_log_dev->parent_dev = &pdev->dev; ++ ++ pfrt_log_dev->miscdev.minor = MISC_DYNAMIC_MINOR; ++ pfrt_log_dev->miscdev.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "pfrt%d", ++ pfrt_log_dev->index); ++ if (!pfrt_log_dev->miscdev.name) ++ return -ENOMEM; ++ ++ pfrt_log_dev->miscdev.nodename = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "acpi_pfr_telemetry%d", ++ pfrt_log_dev->index); ++ if (!pfrt_log_dev->miscdev.nodename) ++ return -ENOMEM; ++ ++ pfrt_log_dev->miscdev.fops = &acpi_pfrt_log_fops; ++ pfrt_log_dev->miscdev.parent = &pdev->dev; ++ ++ ret = misc_register(&pfrt_log_dev->miscdev); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, pfrt_log_dev); ++ ++ return 0; ++} ++ ++static const struct acpi_device_id acpi_pfrt_log_ids[] = { ++ {"INTC1081"}, ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, acpi_pfrt_log_ids); ++ ++static struct platform_driver acpi_pfrt_log_driver = { ++ .driver = { ++ .name = "pfr_telemetry", ++ .acpi_match_table = acpi_pfrt_log_ids, ++ }, ++ .probe = acpi_pfrt_log_probe, ++ .remove = acpi_pfrt_log_remove, ++}; ++module_platform_driver(acpi_pfrt_log_driver); ++ ++MODULE_DESCRIPTION("Platform Firmware Runtime Update Telemetry driver"); ++MODULE_LICENSE("GPL v2"); +--- a/include/uapi/linux/pfrut.h ++++ b/include/uapi/linux/pfrut.h +@@ -171,4 +171,92 @@ struct pfru_updated_result { + __u64 high_exec_time; + }; + ++/** ++ * struct pfrt_log_data_info - Log Data from telemetry service. ++ * @status: Indicator of whether this update succeed. ++ * @ext_status: Implementation specific update result. ++ * @chunk1_addr_lo: Low 32bit physical address of the telemetry data chunk1 ++ * starting address. ++ * @chunk1_addr_hi: High 32bit physical address of the telemetry data chunk1 ++ * starting address. ++ * @chunk2_addr_lo: Low 32bit physical address of the telemetry data chunk2 ++ * starting address. ++ * @chunk2_addr_hi: High 32bit physical address of the telemetry data chunk2 ++ * starting address. ++ * @max_data_size: Maximum supported size of data of all data chunks combined. ++ * @chunk1_size: Data size in bytes of the telemetry data chunk1 buffer. ++ * @chunk2_size: Data size in bytes of the telemetry data chunk2 buffer. ++ * @rollover_cnt: Number of times telemetry data buffer is overwritten ++ * since telemetry buffer reset. ++ * @reset_cnt: Number of times telemetry services resets that results in ++ * rollover count and data chunk buffers are reset. ++ */ ++struct pfrt_log_data_info { ++ __u32 status; ++ __u32 ext_status; ++ __u64 chunk1_addr_lo; ++ __u64 chunk1_addr_hi; ++ __u64 chunk2_addr_lo; ++ __u64 chunk2_addr_hi; ++ __u32 max_data_size; ++ __u32 chunk1_size; ++ __u32 chunk2_size; ++ __u32 rollover_cnt; ++ __u32 reset_cnt; ++}; ++ ++/** ++ * struct pfrt_log_info - Telemetry log information. ++ * @log_level: The telemetry log level. ++ * @log_type: The telemetry log type(history and execution). ++ * @log_revid: The telemetry log revision id. ++ */ ++struct pfrt_log_info { ++ __u32 log_level; ++ __u32 log_type; ++ __u32 log_revid; ++}; ++ ++/** ++ * PFRT_LOG_IOC_SET_INFO - _IOW(PFRUT_IOCTL_MAGIC, 0x06, ++ * struct pfrt_log_info) ++ * ++ * Return: ++ * * 0 - success ++ * * -EFAULT - fail to get the setting parameter ++ * * -EINVAL - fail to set the log level ++ * ++ * Set the PFRT log level and log type. The input information is ++ * a struct pfrt_log_info. ++ */ ++#define PFRT_LOG_IOC_SET_INFO _IOW(PFRUT_IOCTL_MAGIC, 0x06, struct pfrt_log_info) ++ ++/** ++ * PFRT_LOG_IOC_GET_INFO - _IOR(PFRUT_IOCTL_MAGIC, 0x07, ++ * struct pfrt_log_info) ++ * ++ * Return: ++ * * 0 - success ++ * * -EINVAL - fail to get the log level ++ * * -EFAULT - fail to copy the result back to userspace ++ * ++ * Retrieve log level and log type of the telemetry. The information is ++ * a struct pfrt_log_info. ++ */ ++#define PFRT_LOG_IOC_GET_INFO _IOR(PFRUT_IOCTL_MAGIC, 0x07, struct pfrt_log_info) ++ ++/** ++ * PFRT_LOG_IOC_GET_DATA_INFO - _IOR(PFRUT_IOCTL_MAGIC, 0x08, ++ * struct pfrt_log_data_info) ++ * ++ * Return: ++ * * 0 - success ++ * * -EINVAL - fail to get the log buffer information ++ * * -EFAULT - fail to copy the log buffer information to userspace ++ * ++ * Retrieve data information about the telemetry. The information ++ * is a struct pfrt_log_data_info. ++ */ ++#define PFRT_LOG_IOC_GET_DATA_INFO _IOR(PFRUT_IOCTL_MAGIC, 0x08, struct pfrt_log_data_info) ++ + #endif /* __PFRUT_H__ */ diff --git a/patches.suse/ACPI-Introduce-Platform-Firmware-Runtime-Update-devi.patch b/patches.suse/ACPI-Introduce-Platform-Firmware-Runtime-Update-devi.patch new file mode 100644 index 0000000..704b92c --- /dev/null +++ b/patches.suse/ACPI-Introduce-Platform-Firmware-Runtime-Update-devi.patch @@ -0,0 +1,844 @@ +From: Chen Yu +Date: Wed, 22 Dec 2021 12:31:41 +0800 +Subject: ACPI: Introduce Platform Firmware Runtime Update device driver +Patch-mainline: v5.17-rc1 +Git-commit: 0db89fa243e5edc5de38c88b369e4c3755c5fb74 +References: jsc#PED-1408 + +Introduce the pfr_update driver which can be used for Platform Firmware +Runtime code injection and driver update [1]. + +The user is expected to provide the EFI capsule, and pass it to the +driver by writing the capsule to a device special file. The capsule +is transferred by the driver to the platform firmware with the help +of an ACPI _DSM method under the special ACPI Platform Firmware +Runtime Update device (INTC1080), and the actual firmware update is +carried out by the low-level Management Mode code in the platform +firmware. + +This change allows certain pieces of the platform firmware to be +updated on the fly while the system is running (runtime) without the +need to restart it, which is key in the cases when the system needs to +be available 100% of the time and it cannot afford the downtime related +to restarting it, or when the work carried out by the system is +particularly important, so it cannot be interrupted, and it is not +practical to wait until it is complete. + +Link: https://uefi.org/sites/default/files/resources/Intel_MM_OS_Interface_Spec_Rev100.pdf # [1] +Tested-by: Hongyu Ning +Signed-off-by: Chen Yu +[ rjw: Subject and changelog edits ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + Documentation/userspace-api/ioctl/ioctl-number.rst | 1 + drivers/acpi/Kconfig | 18 + drivers/acpi/Makefile | 1 + drivers/acpi/pfr_update.c | 575 +++++++++++++++++++++ + include/uapi/linux/pfrut.h | 174 ++++++ + 5 files changed, 769 insertions(+) + create mode 100644 drivers/acpi/pfr_update.c + create mode 100644 include/uapi/linux/pfrut.h + +--- a/Documentation/userspace-api/ioctl/ioctl-number.rst ++++ b/Documentation/userspace-api/ioctl/ioctl-number.rst +@@ -365,6 +365,7 @@ Code Seq# Include File + + 0xE5 00-3F linux/fuse.h + 0xEC 00-01 drivers/platform/chrome/cros_ec_dev.h ChromeOS EC driver ++0xEE 00-09 uapi/linux/pfrut.h Platform Firmware Runtime Update and Telemetry + 0xF3 00-3F drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development) + + 0xF6 all LTTng Linux Trace Toolkit Next Generation +--- a/drivers/acpi/Kconfig ++++ b/drivers/acpi/Kconfig +@@ -520,6 +520,24 @@ config ACPI_CONFIGFS + userspace. The configurable ACPI groups will be visible under + /config/acpi, assuming configfs is mounted under /config. + ++config ACPI_PFRUT ++ tristate "ACPI Platform Firmware Runtime Update and Telemetry" ++ depends on 64BIT ++ help ++ This mechanism allows certain pieces of the platform firmware ++ to be updated on the fly while the system is running (runtime) ++ without the need to restart it, which is key in the cases when ++ the system needs to be available 100% of the time and it cannot ++ afford the downtime related to restarting it, or when the work ++ carried out by the system is particularly important, so it cannot ++ be interrupted, and it is not practical to wait until it is complete. ++ ++ The existing firmware code can be modified (driver update) or ++ extended by adding new code to the firmware (code injection). ++ ++ To compile this driver as module, choose M here: ++ the module will be called pfr_update. ++ + if ARM64 + source "drivers/acpi/arm64/Kconfig" + +--- a/drivers/acpi/Makefile ++++ b/drivers/acpi/Makefile +@@ -102,6 +102,7 @@ obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi + obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o + obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o + obj-$(CONFIG_ACPI_PPTT) += pptt.o ++obj-$(CONFIG_ACPI_PFRUT) += pfr_update.o + + # processor has its own "processor." module_param namespace + processor-y := processor_driver.o +--- /dev/null ++++ b/drivers/acpi/pfr_update.c +@@ -0,0 +1,575 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * ACPI Platform Firmware Runtime Update Device driver ++ * ++ * Copyright (C) 2021 Intel Corporation ++ * Author: Chen Yu ++ * ++ * pfr_update driver is used for Platform Firmware Runtime ++ * Update, which includes the code injection and driver update. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define PFRU_FUNC_STANDARD_QUERY 0 ++#define PFRU_FUNC_QUERY_UPDATE_CAP 1 ++#define PFRU_FUNC_QUERY_BUF 2 ++#define PFRU_FUNC_START 3 ++ ++#define PFRU_CODE_INJECT_TYPE 1 ++#define PFRU_DRIVER_UPDATE_TYPE 2 ++ ++#define PFRU_REVID_1 1 ++#define PFRU_REVID_2 2 ++#define PFRU_DEFAULT_REV_ID PFRU_REVID_1 ++ ++enum cap_index { ++ CAP_STATUS_IDX = 0, ++ CAP_UPDATE_IDX = 1, ++ CAP_CODE_TYPE_IDX = 2, ++ CAP_FW_VER_IDX = 3, ++ CAP_CODE_RT_VER_IDX = 4, ++ CAP_DRV_TYPE_IDX = 5, ++ CAP_DRV_RT_VER_IDX = 6, ++ CAP_DRV_SVN_IDX = 7, ++ CAP_PLAT_ID_IDX = 8, ++ CAP_OEM_ID_IDX = 9, ++ CAP_OEM_INFO_IDX = 10, ++ CAP_NR_IDX ++}; ++ ++enum buf_index { ++ BUF_STATUS_IDX = 0, ++ BUF_EXT_STATUS_IDX = 1, ++ BUF_ADDR_LOW_IDX = 2, ++ BUF_ADDR_HI_IDX = 3, ++ BUF_SIZE_IDX = 4, ++ BUF_NR_IDX ++}; ++ ++enum update_index { ++ UPDATE_STATUS_IDX = 0, ++ UPDATE_EXT_STATUS_IDX = 1, ++ UPDATE_AUTH_TIME_LOW_IDX = 2, ++ UPDATE_AUTH_TIME_HI_IDX = 3, ++ UPDATE_EXEC_TIME_LOW_IDX = 4, ++ UPDATE_EXEC_TIME_HI_IDX = 5, ++ UPDATE_NR_IDX ++}; ++ ++enum pfru_start_action { ++ START_STAGE = 0, ++ START_ACTIVATE = 1, ++ START_STAGE_ACTIVATE = 2, ++}; ++ ++struct pfru_device { ++ u32 rev_id, index; ++ struct device *parent_dev; ++ struct miscdevice miscdev; ++}; ++ ++static DEFINE_IDA(pfru_ida); ++ ++/* ++ * Manual reference: ++ * https://uefi.org/sites/default/files/resources/Intel_MM_OS_Interface_Spec_Rev100.pdf ++ * ++ * pfru_guid is the parameter for _DSM method ++ */ ++static const guid_t pfru_guid = ++ GUID_INIT(0xECF9533B, 0x4A3C, 0x4E89, 0x93, 0x9E, 0xC7, 0x71, ++ 0x12, 0x60, 0x1C, 0x6D); ++ ++/* pfru_code_inj_guid is the UUID to identify code injection EFI capsule file */ ++static const guid_t pfru_code_inj_guid = ++ GUID_INIT(0xB2F84B79, 0x7B6E, 0x4E45, 0x88, 0x5F, 0x3F, 0xB9, ++ 0xBB, 0x18, 0x54, 0x02); ++ ++/* pfru_drv_update_guid is the UUID to identify driver update EFI capsule file */ ++static const guid_t pfru_drv_update_guid = ++ GUID_INIT(0x4569DD8C, 0x75F1, 0x429A, 0xA3, 0xD6, 0x24, 0xDE, ++ 0x80, 0x97, 0xA0, 0xDF); ++ ++static inline int pfru_valid_revid(u32 id) ++{ ++ return id == PFRU_REVID_1 || id == PFRU_REVID_2; ++} ++ ++static inline struct pfru_device *to_pfru_dev(struct file *file) ++{ ++ return container_of(file->private_data, struct pfru_device, miscdev); ++} ++ ++static int query_capability(struct pfru_update_cap_info *cap_hdr, ++ struct pfru_device *pfru_dev) ++{ ++ acpi_handle handle = ACPI_HANDLE(pfru_dev->parent_dev); ++ union acpi_object *out_obj; ++ int ret = -EINVAL; ++ ++ out_obj = acpi_evaluate_dsm_typed(handle, &pfru_guid, ++ pfru_dev->rev_id, ++ PFRU_FUNC_QUERY_UPDATE_CAP, ++ NULL, ACPI_TYPE_PACKAGE); ++ if (!out_obj) ++ return ret; ++ ++ if (out_obj->package.count < CAP_NR_IDX || ++ out_obj->package.elements[CAP_STATUS_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[CAP_UPDATE_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[CAP_CODE_TYPE_IDX].type != ACPI_TYPE_BUFFER || ++ out_obj->package.elements[CAP_FW_VER_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[CAP_CODE_RT_VER_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[CAP_DRV_TYPE_IDX].type != ACPI_TYPE_BUFFER || ++ out_obj->package.elements[CAP_DRV_RT_VER_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[CAP_DRV_SVN_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[CAP_PLAT_ID_IDX].type != ACPI_TYPE_BUFFER || ++ out_obj->package.elements[CAP_OEM_ID_IDX].type != ACPI_TYPE_BUFFER || ++ out_obj->package.elements[CAP_OEM_INFO_IDX].type != ACPI_TYPE_BUFFER) ++ goto free_acpi_buffer; ++ ++ cap_hdr->status = out_obj->package.elements[CAP_STATUS_IDX].integer.value; ++ if (cap_hdr->status != DSM_SUCCEED) { ++ ret = -EBUSY; ++ dev_dbg(pfru_dev->parent_dev, "Error Status:%d\n", cap_hdr->status); ++ goto free_acpi_buffer; ++ } ++ ++ cap_hdr->update_cap = out_obj->package.elements[CAP_UPDATE_IDX].integer.value; ++ memcpy(&cap_hdr->code_type, ++ out_obj->package.elements[CAP_CODE_TYPE_IDX].buffer.pointer, ++ out_obj->package.elements[CAP_CODE_TYPE_IDX].buffer.length); ++ cap_hdr->fw_version = ++ out_obj->package.elements[CAP_FW_VER_IDX].integer.value; ++ cap_hdr->code_rt_version = ++ out_obj->package.elements[CAP_CODE_RT_VER_IDX].integer.value; ++ memcpy(&cap_hdr->drv_type, ++ out_obj->package.elements[CAP_DRV_TYPE_IDX].buffer.pointer, ++ out_obj->package.elements[CAP_DRV_TYPE_IDX].buffer.length); ++ cap_hdr->drv_rt_version = ++ out_obj->package.elements[CAP_DRV_RT_VER_IDX].integer.value; ++ cap_hdr->drv_svn = ++ out_obj->package.elements[CAP_DRV_SVN_IDX].integer.value; ++ memcpy(&cap_hdr->platform_id, ++ out_obj->package.elements[CAP_PLAT_ID_IDX].buffer.pointer, ++ out_obj->package.elements[CAP_PLAT_ID_IDX].buffer.length); ++ memcpy(&cap_hdr->oem_id, ++ out_obj->package.elements[CAP_OEM_ID_IDX].buffer.pointer, ++ out_obj->package.elements[CAP_OEM_ID_IDX].buffer.length); ++ cap_hdr->oem_info_len = ++ out_obj->package.elements[CAP_OEM_INFO_IDX].buffer.length; ++ ++ ret = 0; ++ ++free_acpi_buffer: ++ kfree(out_obj); ++ ++ return ret; ++} ++ ++static int query_buffer(struct pfru_com_buf_info *info, ++ struct pfru_device *pfru_dev) ++{ ++ acpi_handle handle = ACPI_HANDLE(pfru_dev->parent_dev); ++ union acpi_object *out_obj; ++ int ret = -EINVAL; ++ ++ out_obj = acpi_evaluate_dsm_typed(handle, &pfru_guid, ++ pfru_dev->rev_id, PFRU_FUNC_QUERY_BUF, ++ NULL, ACPI_TYPE_PACKAGE); ++ if (!out_obj) ++ return ret; ++ ++ if (out_obj->package.count < BUF_NR_IDX || ++ out_obj->package.elements[BUF_STATUS_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[BUF_EXT_STATUS_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[BUF_ADDR_LOW_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[BUF_ADDR_HI_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[BUF_SIZE_IDX].type != ACPI_TYPE_INTEGER) ++ goto free_acpi_buffer; ++ ++ info->status = out_obj->package.elements[BUF_STATUS_IDX].integer.value; ++ info->ext_status = ++ out_obj->package.elements[BUF_EXT_STATUS_IDX].integer.value; ++ if (info->status != DSM_SUCCEED) { ++ ret = -EBUSY; ++ dev_dbg(pfru_dev->parent_dev, "Error Status:%d\n", info->status); ++ dev_dbg(pfru_dev->parent_dev, "Error Extended Status:%d\n", info->ext_status); ++ ++ goto free_acpi_buffer; ++ } ++ ++ info->addr_lo = ++ out_obj->package.elements[BUF_ADDR_LOW_IDX].integer.value; ++ info->addr_hi = ++ out_obj->package.elements[BUF_ADDR_HI_IDX].integer.value; ++ info->buf_size = out_obj->package.elements[BUF_SIZE_IDX].integer.value; ++ ++ ret = 0; ++ ++free_acpi_buffer: ++ kfree(out_obj); ++ ++ return ret; ++} ++ ++static int get_image_type(const struct efi_manage_capsule_image_header *img_hdr, ++ struct pfru_device *pfru_dev) ++{ ++ const efi_guid_t *image_type_id = &img_hdr->image_type_id; ++ ++ /* check whether this is a code injection or driver update */ ++ if (guid_equal(image_type_id, &pfru_code_inj_guid)) ++ return PFRU_CODE_INJECT_TYPE; ++ ++ if (guid_equal(image_type_id, &pfru_drv_update_guid)) ++ return PFRU_DRIVER_UPDATE_TYPE; ++ ++ return -EINVAL; ++} ++ ++static int adjust_efi_size(const struct efi_manage_capsule_image_header *img_hdr, ++ int size) ++{ ++ /* ++ * The (u64 hw_ins) was introduced in UEFI spec version 2, ++ * and (u64 capsule_support) was introduced in version 3. ++ * The size needs to be adjusted accordingly. That is to ++ * say, version 1 should subtract the size of hw_ins+capsule_support, ++ * and version 2 should sbstract the size of capsule_support. ++ */ ++ size += sizeof(struct efi_manage_capsule_image_header); ++ switch (img_hdr->ver) { ++ case 1: ++ return size - 2 * sizeof(u64); ++ ++ case 2: ++ return size - sizeof(u64); ++ ++ default: ++ /* only support version 1 and 2 */ ++ return -EINVAL; ++ } ++} ++ ++static bool applicable_image(const void *data, struct pfru_update_cap_info *cap, ++ struct pfru_device *pfru_dev) ++{ ++ struct pfru_payload_hdr *payload_hdr; ++ const efi_capsule_header_t *cap_hdr = data; ++ const struct efi_manage_capsule_header *m_hdr; ++ const struct efi_manage_capsule_image_header *m_img_hdr; ++ const struct efi_image_auth *auth; ++ int type, size; ++ ++ /* ++ * If the code in the capsule is older than the current ++ * firmware code, the update will be rejected by the firmware, ++ * so check the version of it upfront without engaging the ++ * Management Mode update mechanism which may be costly. ++ */ ++ size = cap_hdr->headersize; ++ m_hdr = data + size; ++ /* ++ * Current data structure size plus variable array indicated ++ * by number of (emb_drv_cnt + payload_cnt) ++ */ ++ size += offsetof(struct efi_manage_capsule_header, offset_list) + ++ (m_hdr->emb_drv_cnt + m_hdr->payload_cnt) * sizeof(u64); ++ m_img_hdr = data + size; ++ ++ type = get_image_type(m_img_hdr, pfru_dev); ++ if (type < 0) ++ return false; ++ ++ size = adjust_efi_size(m_img_hdr, size); ++ if (size < 0) ++ return false; ++ ++ auth = data + size; ++ size += sizeof(u64) + auth->auth_info.hdr.len; ++ payload_hdr = (struct pfru_payload_hdr *)(data + size); ++ ++ /* finally compare the version */ ++ if (type == PFRU_CODE_INJECT_TYPE) ++ return payload_hdr->rt_ver >= cap->code_rt_version; ++ ++ return payload_hdr->rt_ver >= cap->drv_rt_version; ++} ++ ++static void print_update_debug_info(struct pfru_updated_result *result, ++ struct pfru_device *pfru_dev) ++{ ++ dev_dbg(pfru_dev->parent_dev, "Update result:\n"); ++ dev_dbg(pfru_dev->parent_dev, "Authentication Time Low:%lld\n", ++ result->low_auth_time); ++ dev_dbg(pfru_dev->parent_dev, "Authentication Time High:%lld\n", ++ result->high_auth_time); ++ dev_dbg(pfru_dev->parent_dev, "Execution Time Low:%lld\n", ++ result->low_exec_time); ++ dev_dbg(pfru_dev->parent_dev, "Execution Time High:%lld\n", ++ result->high_exec_time); ++} ++ ++static int start_update(int action, struct pfru_device *pfru_dev) ++{ ++ union acpi_object *out_obj, in_obj, in_buf; ++ struct pfru_updated_result update_result; ++ acpi_handle handle; ++ int ret = -EINVAL; ++ ++ memset(&in_obj, 0, sizeof(in_obj)); ++ memset(&in_buf, 0, sizeof(in_buf)); ++ in_obj.type = ACPI_TYPE_PACKAGE; ++ in_obj.package.count = 1; ++ in_obj.package.elements = &in_buf; ++ in_buf.type = ACPI_TYPE_INTEGER; ++ in_buf.integer.value = action; ++ ++ handle = ACPI_HANDLE(pfru_dev->parent_dev); ++ out_obj = acpi_evaluate_dsm_typed(handle, &pfru_guid, ++ pfru_dev->rev_id, PFRU_FUNC_START, ++ &in_obj, ACPI_TYPE_PACKAGE); ++ if (!out_obj) ++ return ret; ++ ++ if (out_obj->package.count < UPDATE_NR_IDX || ++ out_obj->package.elements[UPDATE_STATUS_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[UPDATE_EXT_STATUS_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[UPDATE_AUTH_TIME_LOW_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[UPDATE_AUTH_TIME_HI_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[UPDATE_EXEC_TIME_LOW_IDX].type != ACPI_TYPE_INTEGER || ++ out_obj->package.elements[UPDATE_EXEC_TIME_HI_IDX].type != ACPI_TYPE_INTEGER) ++ goto free_acpi_buffer; ++ ++ update_result.status = ++ out_obj->package.elements[UPDATE_STATUS_IDX].integer.value; ++ update_result.ext_status = ++ out_obj->package.elements[UPDATE_EXT_STATUS_IDX].integer.value; ++ ++ if (update_result.status != DSM_SUCCEED) { ++ ret = -EBUSY; ++ dev_dbg(pfru_dev->parent_dev, "Error Status:%d\n", update_result.status); ++ dev_dbg(pfru_dev->parent_dev, "Error Extended Status:%d\n", ++ update_result.ext_status); ++ ++ goto free_acpi_buffer; ++ } ++ ++ update_result.low_auth_time = ++ out_obj->package.elements[UPDATE_AUTH_TIME_LOW_IDX].integer.value; ++ update_result.high_auth_time = ++ out_obj->package.elements[UPDATE_AUTH_TIME_HI_IDX].integer.value; ++ update_result.low_exec_time = ++ out_obj->package.elements[UPDATE_EXEC_TIME_LOW_IDX].integer.value; ++ update_result.high_exec_time = ++ out_obj->package.elements[UPDATE_EXEC_TIME_HI_IDX].integer.value; ++ ++ print_update_debug_info(&update_result, pfru_dev); ++ ret = 0; ++ ++free_acpi_buffer: ++ kfree(out_obj); ++ ++ return ret; ++} ++ ++static long pfru_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ struct pfru_update_cap_info cap_hdr; ++ struct pfru_device *pfru_dev = to_pfru_dev(file); ++ void __user *p = (void __user *)arg; ++ u32 rev; ++ int ret; ++ ++ switch (cmd) { ++ case PFRU_IOC_QUERY_CAP: ++ ret = query_capability(&cap_hdr, pfru_dev); ++ if (ret) ++ return ret; ++ ++ if (copy_to_user(p, &cap_hdr, sizeof(cap_hdr))) ++ return -EFAULT; ++ ++ return 0; ++ ++ case PFRU_IOC_SET_REV: ++ if (copy_from_user(&rev, p, sizeof(rev))) ++ return -EFAULT; ++ ++ if (!pfru_valid_revid(rev)) ++ return -EINVAL; ++ ++ pfru_dev->rev_id = rev; ++ ++ return 0; ++ ++ case PFRU_IOC_STAGE: ++ return start_update(START_STAGE, pfru_dev); ++ ++ case PFRU_IOC_ACTIVATE: ++ return start_update(START_ACTIVATE, pfru_dev); ++ ++ case PFRU_IOC_STAGE_ACTIVATE: ++ return start_update(START_STAGE_ACTIVATE, pfru_dev); ++ ++ default: ++ return -ENOTTY; ++ } ++} ++ ++static ssize_t pfru_write(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ struct pfru_device *pfru_dev = to_pfru_dev(file); ++ struct pfru_update_cap_info cap; ++ struct pfru_com_buf_info buf_info; ++ phys_addr_t phy_addr; ++ struct iov_iter iter; ++ struct iovec iov; ++ char *buf_ptr; ++ int ret; ++ ++ ret = query_buffer(&buf_info, pfru_dev); ++ if (ret) ++ return ret; ++ ++ if (len > buf_info.buf_size) ++ return -EINVAL; ++ ++ iov.iov_base = (void __user *)buf; ++ iov.iov_len = len; ++ iov_iter_init(&iter, WRITE, &iov, 1, len); ++ ++ /* map the communication buffer */ ++ phy_addr = (phys_addr_t)((buf_info.addr_hi << 32) | buf_info.addr_lo); ++ buf_ptr = memremap(phy_addr, buf_info.buf_size, MEMREMAP_WB); ++ if (IS_ERR(buf_ptr)) ++ return PTR_ERR(buf_ptr); ++ ++ if (!copy_from_iter_full(buf_ptr, len, &iter)) { ++ ret = -EINVAL; ++ goto unmap; ++ } ++ ++ /* check if the capsule header has a valid version number */ ++ ret = query_capability(&cap, pfru_dev); ++ if (ret) ++ goto unmap; ++ ++ if (!applicable_image(buf_ptr, &cap, pfru_dev)) ++ ret = -EINVAL; ++ ++unmap: ++ memunmap(buf_ptr); ++ ++ return ret ?: len; ++} ++ ++static const struct file_operations acpi_pfru_fops = { ++ .owner = THIS_MODULE, ++ .write = pfru_write, ++ .unlocked_ioctl = pfru_ioctl, ++ .llseek = noop_llseek, ++}; ++ ++static int acpi_pfru_remove(struct platform_device *pdev) ++{ ++ struct pfru_device *pfru_dev = platform_get_drvdata(pdev); ++ ++ misc_deregister(&pfru_dev->miscdev); ++ ++ return 0; ++} ++ ++static void pfru_put_idx(void *data) ++{ ++ struct pfru_device *pfru_dev = data; ++ ++ ida_free(&pfru_ida, pfru_dev->index); ++} ++ ++static int acpi_pfru_probe(struct platform_device *pdev) ++{ ++ acpi_handle handle = ACPI_HANDLE(&pdev->dev); ++ struct pfru_device *pfru_dev; ++ int ret; ++ ++ if (!acpi_has_method(handle, "_DSM")) { ++ dev_dbg(&pdev->dev, "Missing _DSM\n"); ++ return -ENODEV; ++ } ++ ++ pfru_dev = devm_kzalloc(&pdev->dev, sizeof(*pfru_dev), GFP_KERNEL); ++ if (!pfru_dev) ++ return -ENOMEM; ++ ++ ret = ida_alloc(&pfru_ida, GFP_KERNEL); ++ if (ret < 0) ++ return ret; ++ ++ pfru_dev->index = ret; ++ ret = devm_add_action_or_reset(&pdev->dev, pfru_put_idx, pfru_dev); ++ if (ret) ++ return ret; ++ ++ pfru_dev->rev_id = PFRU_DEFAULT_REV_ID; ++ pfru_dev->parent_dev = &pdev->dev; ++ ++ pfru_dev->miscdev.minor = MISC_DYNAMIC_MINOR; ++ pfru_dev->miscdev.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "pfru%d", pfru_dev->index); ++ if (!pfru_dev->miscdev.name) ++ return -ENOMEM; ++ ++ pfru_dev->miscdev.nodename = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "acpi_pfr_update%d", pfru_dev->index); ++ if (!pfru_dev->miscdev.nodename) ++ return -ENOMEM; ++ ++ pfru_dev->miscdev.fops = &acpi_pfru_fops; ++ pfru_dev->miscdev.parent = &pdev->dev; ++ ++ ret = misc_register(&pfru_dev->miscdev); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, pfru_dev); ++ ++ return 0; ++} ++ ++static const struct acpi_device_id acpi_pfru_ids[] = { ++ {"INTC1080"}, ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, acpi_pfru_ids); ++ ++static struct platform_driver acpi_pfru_driver = { ++ .driver = { ++ .name = "pfr_update", ++ .acpi_match_table = acpi_pfru_ids, ++ }, ++ .probe = acpi_pfru_probe, ++ .remove = acpi_pfru_remove, ++}; ++module_platform_driver(acpi_pfru_driver); ++ ++MODULE_DESCRIPTION("Platform Firmware Runtime Update device driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/include/uapi/linux/pfrut.h +@@ -0,0 +1,174 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * Platform Firmware Runtime Update header ++ * ++ * Copyright(c) 2021 Intel Corporation. All rights reserved. ++ */ ++#ifndef __PFRUT_H__ ++#define __PFRUT_H__ ++ ++#include ++#include ++ ++#define PFRUT_IOCTL_MAGIC 0xEE ++ ++/** ++ * PFRU_IOC_SET_REV - _IOW(PFRUT_IOCTL_MAGIC, 0x01, unsigned int) ++ * ++ * Return: ++ * * 0 - success ++ * * -EFAULT - fail to read the revision id ++ * * -EINVAL - user provides an invalid revision id ++ * ++ * Set the Revision ID for Platform Firmware Runtime Update. ++ */ ++#define PFRU_IOC_SET_REV _IOW(PFRUT_IOCTL_MAGIC, 0x01, unsigned int) ++ ++/** ++ * PFRU_IOC_STAGE - _IOW(PFRUT_IOCTL_MAGIC, 0x02, unsigned int) ++ * ++ * Return: ++ * * 0 - success ++ * * -EINVAL - stage phase returns invalid result ++ * ++ * Stage a capsule image from communication buffer and perform authentication. ++ */ ++#define PFRU_IOC_STAGE _IOW(PFRUT_IOCTL_MAGIC, 0x02, unsigned int) ++ ++/** ++ * PFRU_IOC_ACTIVATE - _IOW(PFRUT_IOCTL_MAGIC, 0x03, unsigned int) ++ * ++ * Return: ++ * * 0 - success ++ * * -EINVAL - activate phase returns invalid result ++ * ++ * Activate a previously staged capsule image. ++ */ ++#define PFRU_IOC_ACTIVATE _IOW(PFRUT_IOCTL_MAGIC, 0x03, unsigned int) ++ ++/** ++ * PFRU_IOC_STAGE_ACTIVATE - _IOW(PFRUT_IOCTL_MAGIC, 0x04, unsigned int) ++ * ++ * Return: ++ * * 0 - success ++ * * -EINVAL - stage/activate phase returns invalid result. ++ * ++ * Perform both stage and activation action. ++ */ ++#define PFRU_IOC_STAGE_ACTIVATE _IOW(PFRUT_IOCTL_MAGIC, 0x04, unsigned int) ++ ++/** ++ * PFRU_IOC_QUERY_CAP - _IOR(PFRUT_IOCTL_MAGIC, 0x05, ++ * struct pfru_update_cap_info) ++ * ++ * Return: ++ * * 0 - success ++ * * -EINVAL - query phase returns invalid result ++ * * -EFAULT - the result fails to be copied to userspace ++ * ++ * Retrieve information on the Platform Firmware Runtime Update capability. ++ * The information is a struct pfru_update_cap_info. ++ */ ++#define PFRU_IOC_QUERY_CAP _IOR(PFRUT_IOCTL_MAGIC, 0x05, struct pfru_update_cap_info) ++ ++/** ++ * struct pfru_payload_hdr - Capsule file payload header. ++ * ++ * @sig: Signature of this capsule file. ++ * @hdr_version: Revision of this header structure. ++ * @hdr_size: Size of this header, including the OemHeader bytes. ++ * @hw_ver: The supported firmware version. ++ * @rt_ver: Version of the code injection image. ++ * @platform_id: A platform specific GUID to specify the platform what ++ * this capsule image support. ++ */ ++struct pfru_payload_hdr { ++ __u32 sig; ++ __u32 hdr_version; ++ __u32 hdr_size; ++ __u32 hw_ver; ++ __u32 rt_ver; ++ __u8 platform_id[16]; ++}; ++ ++enum pfru_dsm_status { ++ DSM_SUCCEED = 0, ++ DSM_FUNC_NOT_SUPPORT = 1, ++ DSM_INVAL_INPUT = 2, ++ DSM_HARDWARE_ERR = 3, ++ DSM_RETRY_SUGGESTED = 4, ++ DSM_UNKNOWN = 5, ++ DSM_FUNC_SPEC_ERR = 6, ++}; ++ ++/** ++ * struct pfru_update_cap_info - Runtime update capability information. ++ * ++ * @status: Indicator of whether this query succeed. ++ * @update_cap: Bitmap to indicate whether the feature is supported. ++ * @code_type: A buffer containing an image type GUID. ++ * @fw_version: Platform firmware version. ++ * @code_rt_version: Code injection runtime version for anti-rollback. ++ * @drv_type: A buffer containing an image type GUID. ++ * @drv_rt_version: The version of the driver update runtime code. ++ * @drv_svn: The secure version number(SVN) of the driver update runtime code. ++ * @platform_id: A buffer containing a platform ID GUID. ++ * @oem_id: A buffer containing an OEM ID GUID. ++ * @oem_info_len: Length of the buffer containing the vendor specific information. ++ */ ++struct pfru_update_cap_info { ++ __u32 status; ++ __u32 update_cap; ++ ++ __u8 code_type[16]; ++ __u32 fw_version; ++ __u32 code_rt_version; ++ ++ __u8 drv_type[16]; ++ __u32 drv_rt_version; ++ __u32 drv_svn; ++ ++ __u8 platform_id[16]; ++ __u8 oem_id[16]; ++ ++ __u32 oem_info_len; ++}; ++ ++/** ++ * struct pfru_com_buf_info - Communication buffer information. ++ * ++ * @status: Indicator of whether this query succeed. ++ * @ext_status: Implementation specific query result. ++ * @addr_lo: Low 32bit physical address of the communication buffer to hold ++ * a runtime update package. ++ * @addr_hi: High 32bit physical address of the communication buffer to hold ++ * a runtime update package. ++ * @buf_size: Maximum size in bytes of the communication buffer. ++ */ ++struct pfru_com_buf_info { ++ __u32 status; ++ __u32 ext_status; ++ __u64 addr_lo; ++ __u64 addr_hi; ++ __u32 buf_size; ++}; ++ ++/** ++ * struct pfru_updated_result - Platform firmware runtime update result information. ++ * @status: Indicator of whether this update succeed. ++ * @ext_status: Implementation specific update result. ++ * @low_auth_time: Low 32bit value of image authentication time in nanosecond. ++ * @high_auth_time: High 32bit value of image authentication time in nanosecond. ++ * @low_exec_time: Low 32bit value of image execution time in nanosecond. ++ * @high_exec_time: High 32bit value of image execution time in nanosecond. ++ */ ++struct pfru_updated_result { ++ __u32 status; ++ __u32 ext_status; ++ __u64 low_auth_time; ++ __u64 high_auth_time; ++ __u64 low_exec_time; ++ __u64 high_exec_time; ++}; ++ ++#endif /* __PFRUT_H__ */ diff --git a/patches.suse/ACPI-Keep-sub-table-parsing-infrastructure-available.patch b/patches.suse/ACPI-Keep-sub-table-parsing-infrastructure-available.patch new file mode 100644 index 0000000..b63537c --- /dev/null +++ b/patches.suse/ACPI-Keep-sub-table-parsing-infrastructure-available.patch @@ -0,0 +1,160 @@ +From: Dan Williams +Date: Fri, 29 Oct 2021 12:51:32 -0700 +Subject: ACPI: Keep sub-table parsing infrastructure available for modules +Patch-mainline: v5.17-rc1 +Git-commit: f64bd790b750dd281406964af40d16adfc88a074 +References: jsc#PED-1408 + +The NFIT driver and now the CXL ACPI driver have both open-coded ACPI +table parsing. Before another instance is added arrange for the core +ACPI sub-table parsing to be optionally available to drivers via the +CONFIG_ACPI_TABLE_LIB symbol. If no drivers select the symbol then the +infrastructure reverts back to being tagged __init via the +__init_or_acpilib annotation. + +For now, only tag the core sub-table routines and data that the CEDT parsing in +the cxl_acpi driver would want to reuse, a CEDT parsing helper is added +in a later change. + +Cc: "Rafael J. Wysocki" +Cc: Len Brown +Cc: Alison Schofield +Acked-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/163553709227.2509508.8215196520233473814.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/Kconfig | 3 +++ + drivers/acpi/tables.c | 27 +++++++++++++-------------- + include/linux/acpi.h | 22 +++++++++++++++------- + 3 files changed, 31 insertions(+), 21 deletions(-) + +--- a/drivers/acpi/Kconfig ++++ b/drivers/acpi/Kconfig +@@ -59,6 +59,9 @@ config ACPI_SYSTEM_POWER_STATES_SUPPORT + config ACPI_CCA_REQUIRED + bool + ++config ACPI_TABLE_LIB ++ bool ++ + config ACPI_DEBUGGER + bool "AML debugger interface" + select ACPI_DEBUG +--- a/drivers/acpi/tables.c ++++ b/drivers/acpi/tables.c +@@ -34,7 +34,7 @@ static char *mps_inti_flags_trigger[] = + + static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; + +-static int acpi_apic_instance __initdata; ++static int acpi_apic_instance __initdata_or_acpilib; + + enum acpi_subtable_type { + ACPI_SUBTABLE_COMMON, +@@ -51,7 +51,7 @@ struct acpi_subtable_entry { + * Disable table checksum verification for the early stage due to the size + * limitation of the current x86 early mapping implementation. + */ +-static bool acpi_verify_table_checksum __initdata = false; ++static bool acpi_verify_table_checksum __initdata_or_acpilib = false; + + void acpi_table_print_madt_entry(struct acpi_subtable_header *header) + { +@@ -215,7 +215,7 @@ void acpi_table_print_madt_entry(struct + } + } + +-static unsigned long __init ++static unsigned long __init_or_acpilib + acpi_get_entry_type(struct acpi_subtable_entry *entry) + { + switch (entry->type) { +@@ -229,7 +229,7 @@ acpi_get_entry_type(struct acpi_subtable + return 0; + } + +-static unsigned long __init ++static unsigned long __init_or_acpilib + acpi_get_entry_length(struct acpi_subtable_entry *entry) + { + switch (entry->type) { +@@ -243,7 +243,7 @@ acpi_get_entry_length(struct acpi_subtab + return 0; + } + +-static unsigned long __init ++static unsigned long __init_or_acpilib + acpi_get_subtable_header_length(struct acpi_subtable_entry *entry) + { + switch (entry->type) { +@@ -257,7 +257,7 @@ acpi_get_subtable_header_length(struct a + return 0; + } + +-static enum acpi_subtable_type __init ++static enum acpi_subtable_type __init_or_acpilib + acpi_get_subtable_type(char *id) + { + if (strncmp(id, ACPI_SIG_HMAT, 4) == 0) +@@ -290,10 +290,10 @@ acpi_get_subtable_type(char *id) + * On success returns sum of all matching entries for all proc handlers. + * Otherwise, -ENODEV or -EINVAL is returned. + */ +-static int __init acpi_parse_entries_array(char *id, unsigned long table_size, +- struct acpi_table_header *table_header, +- struct acpi_subtable_proc *proc, int proc_num, +- unsigned int max_entries) ++static int __init_or_acpilib acpi_parse_entries_array( ++ char *id, unsigned long table_size, ++ struct acpi_table_header *table_header, struct acpi_subtable_proc *proc, ++ int proc_num, unsigned int max_entries) + { + struct acpi_subtable_entry entry; + unsigned long table_end, subtable_len, entry_len; +@@ -351,10 +351,9 @@ static int __init acpi_parse_entries_arr + return errs ? -EINVAL : count; + } + +-int __init acpi_table_parse_entries_array(char *id, +- unsigned long table_size, +- struct acpi_subtable_proc *proc, int proc_num, +- unsigned int max_entries) ++int __init_or_acpilib acpi_table_parse_entries_array( ++ char *id, unsigned long table_size, struct acpi_subtable_proc *proc, ++ int proc_num, unsigned int max_entries) + { + struct acpi_table_header *table_header = NULL; + int count; +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -232,14 +232,22 @@ int acpi_locate_initial_tables (void); + void acpi_reserve_initial_tables (void); + void acpi_table_init_complete (void); + int acpi_table_init (void); ++ ++#ifdef CONFIG_ACPI_TABLE_LIB ++#define __init_or_acpilib ++#define __initdata_or_acpilib ++#else ++#define __init_or_acpilib __init ++#define __initdata_or_acpilib __initdata ++#endif ++ + int acpi_table_parse(char *id, acpi_tbl_table_handler handler); +-int __init acpi_table_parse_entries(char *id, unsigned long table_size, +- int entry_id, +- acpi_tbl_entry_handler handler, +- unsigned int max_entries); +-int __init acpi_table_parse_entries_array(char *id, unsigned long table_size, +- struct acpi_subtable_proc *proc, int proc_num, +- unsigned int max_entries); ++int __init_or_acpilib acpi_table_parse_entries(char *id, ++ unsigned long table_size, int entry_id, ++ acpi_tbl_entry_handler handler, unsigned int max_entries); ++int __init_or_acpilib acpi_table_parse_entries_array(char *id, ++ unsigned long table_size, struct acpi_subtable_proc *proc, ++ int proc_num, unsigned int max_entries); + int acpi_table_parse_madt(enum acpi_madt_type id, + acpi_tbl_entry_handler handler, + unsigned int max_entries); diff --git a/patches.suse/ACPI-NFIT-Import-GUID-before-use.patch b/patches.suse/ACPI-NFIT-Import-GUID-before-use.patch new file mode 100644 index 0000000..da845e8 --- /dev/null +++ b/patches.suse/ACPI-NFIT-Import-GUID-before-use.patch @@ -0,0 +1,35 @@ +From: Andy Shevchenko +Date: Mon, 13 Dec 2021 22:46:32 +0200 +Subject: ACPI: NFIT: Import GUID before use +Patch-mainline: v5.17-rc1 +Git-commit: abc14eb1e01286819a671019e78a23542685eee2 +References: jsc#PED-1408 + +Strictly speaking the comparison between guid_t and raw buffer +is not correct. Import GUID to variable of guid_t type and then +compare. + +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20211213204632.56735-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Dan Williams +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/nfit/core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/nfit/core.c ++++ b/drivers/acpi/nfit/core.c +@@ -678,10 +678,12 @@ static const char *spa_type_name(u16 typ + + int nfit_spa_type(struct acpi_nfit_system_address *spa) + { ++ guid_t guid; + int i; + ++ import_guid(&guid, spa->range_guid); + for (i = 0; i < NFIT_UUID_MAX; i++) +- if (guid_equal(to_nfit_uuid(i), (guid_t *)&spa->range_guid)) ++ if (guid_equal(to_nfit_uuid(i), &guid)) + return i; + return -1; + } diff --git a/patches.suse/ACPI-NUMA-Process-hotpluggable-memblocks-when-CONFIG.patch b/patches.suse/ACPI-NUMA-Process-hotpluggable-memblocks-when-CONFIG.patch new file mode 100644 index 0000000..08c112e --- /dev/null +++ b/patches.suse/ACPI-NUMA-Process-hotpluggable-memblocks-when-CONFIG.patch @@ -0,0 +1,41 @@ +From: Vitaly Kuznetsov +Date: Thu, 16 Dec 2021 10:58:26 +0100 +Subject: ACPI: NUMA: Process hotpluggable memblocks when + !CONFIG_MEMORY_HOTPLUG +Patch-mainline: v5.17-rc1 +Git-commit: bcf6f1759adff0ec3f73ab7b4a873405ee26ff5c +References: jsc#PED-1408 + +Some systems (e.g. Hyper-V guests) have all their memory marked as +hotpluggable in SRAT. acpi_numa_memory_affinity_init(), however, +ignores all such regions when !CONFIG_MEMORY_HOTPLUG and this is +unfortunate as memory affinity (NUMA) information gets lost. + +'Hot Pluggable' flag in SRAT only means that "system hardware supports +hot-add and hot-remove of this memory region", it doesn't prevent +memory from being cold-plugged there. + +Ignore 'Hot Pluggable' bit instead of skipping the whole memory +affinity information when !CONFIG_MEMORY_HOTPLUG. + +Signed-off-by: Vitaly Kuznetsov +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/numa/srat.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/acpi/numa/srat.c ++++ b/drivers/acpi/numa/srat.c +@@ -254,9 +254,8 @@ acpi_numa_memory_affinity_init(struct ac + } + if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) + goto out_err; +- hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE; +- if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG)) +- goto out_err; ++ hotpluggable = IS_ENABLED(CONFIG_MEMORY_HOTPLUG) && ++ (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE); + + start = ma->base_address; + end = start + ma->length; diff --git a/patches.suse/ACPI-PM-Avoid-CPU-cache-flush-when-entering-S4.patch b/patches.suse/ACPI-PM-Avoid-CPU-cache-flush-when-entering-S4.patch new file mode 100644 index 0000000..b93c2a4 --- /dev/null +++ b/patches.suse/ACPI-PM-Avoid-CPU-cache-flush-when-entering-S4.patch @@ -0,0 +1,31 @@ +From: "Kirill A. Shutemov" +Date: Mon, 6 Dec 2021 15:29:52 +0300 +Subject: ACPI: PM: Avoid CPU cache flush when entering S4 +Patch-mainline: v5.17-rc1 +Git-commit: 53d01e2016d77ff647fb2056c39c67df18ee86bf +References: jsc#PED-1408 + +According to ACPI 6.4, Section 16.2, the CPU cache flushing is +required on entering to S1, S2, and S3. + +No need to flush the caches during hibernation (S4). + +Signed-off-by: Kirill A. Shutemov +[ rjw: Subject and changelog edits ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/sleep.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -903,8 +903,6 @@ static int acpi_hibernation_enter(void) + { + acpi_status status = AE_OK; + +- ACPI_FLUSH_CPU_CACHE(); +- + /* This shouldn't return. If it returns, we have a problem */ + status = acpi_enter_sleep_state(ACPI_STATE_S4); + /* Reprogram control registers */ diff --git a/patches.suse/ACPI-PM-Emit-debug-messages-when-enabling-disabling-.patch b/patches.suse/ACPI-PM-Emit-debug-messages-when-enabling-disabling-.patch new file mode 100644 index 0000000..769ecc0 --- /dev/null +++ b/patches.suse/ACPI-PM-Emit-debug-messages-when-enabling-disabling-.patch @@ -0,0 +1,63 @@ +From: "Rafael J. Wysocki" +Date: Tue, 16 Nov 2021 21:06:17 +0100 +Subject: ACPI: PM: Emit debug messages when enabling/disabling wakeup power +Patch-mainline: v5.17-rc1 +Git-commit: 5b6a8f1445bc86e221da85bb67f389c3ab6d2037 +References: jsc#PED-1408 + +Print additional debug messages when enabling and disabling wakeup +power for an ACPI device object to facilitate more fine-grained +debugging of problems in that area. + +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/power.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/acpi/power.c ++++ b/drivers/acpi/power.c +@@ -716,6 +716,9 @@ int acpi_enable_wakeup_device_power(stru + + mutex_lock(&acpi_device_lock); + ++ dev_dbg(&dev->dev, "Enabling wakeup power (count %d)\n", ++ dev->wakeup.prepare_count); ++ + if (dev->wakeup.prepare_count++) + goto out; + +@@ -734,8 +737,11 @@ int acpi_enable_wakeup_device_power(stru + if (err) { + acpi_power_off_list(&dev->wakeup.resources); + dev->wakeup.prepare_count = 0; ++ goto out; + } + ++ dev_dbg(&dev->dev, "Wakeup power enabled\n"); ++ + out: + mutex_unlock(&acpi_device_lock); + return err; +@@ -757,6 +763,9 @@ int acpi_disable_wakeup_device_power(str + + mutex_lock(&acpi_device_lock); + ++ dev_dbg(&dev->dev, "Disabling wakeup power (count %d)\n", ++ dev->wakeup.prepare_count); ++ + /* Do nothing if wakeup power has not been enabled for this device. */ + if (dev->wakeup.prepare_count <= 0) + goto out; +@@ -782,8 +791,11 @@ int acpi_disable_wakeup_device_power(str + if (err) { + dev_err(&dev->dev, "Cannot turn off wakeup power resources\n"); + dev->wakeup.flags.valid = 0; ++ goto out; + } + ++ dev_dbg(&dev->dev, "Wakeup power disabled\n"); ++ + out: + mutex_unlock(&acpi_device_lock); + return err; diff --git a/patches.suse/ACPI-PM-Remove-redundant-cache-flushing.patch b/patches.suse/ACPI-PM-Remove-redundant-cache-flushing.patch new file mode 100644 index 0000000..795630a --- /dev/null +++ b/patches.suse/ACPI-PM-Remove-redundant-cache-flushing.patch @@ -0,0 +1,60 @@ +From: "Kirill A. Shutemov" +Date: Thu, 9 Dec 2021 16:08:02 +0300 +Subject: ACPI: PM: Remove redundant cache flushing +Patch-mainline: v5.17-rc1 +Git-commit: 3c89857a66ef15bcf54c8fd255a1fd70dbc823a6 +References: jsc#PED-1408 + +ACPICA code takes care about cache flushing on S1/S2/S3 in +acpi_hw_extended_sleep() and acpi_hw_legacy_sleep(). + +acpi_suspend_enter() calls into ACPICA code via acpi_enter_sleep_state() +for S1 or x86_acpi_suspend_lowlevel() for S3. + +acpi_sleep_prepare() call tree: + __acpi_pm_prepare() + acpi_pm_prepare() + acpi_suspend_ops::prepare_late() + acpi_hibernation_ops::pre_snapshot() + acpi_hibernation_ops::prepare() + acpi_suspend_begin_old() + acpi_suspend_begin_old::begin() + acpi_hibernation_begin_old() + acpi_hibernation_ops_old::acpi_hibernation_begin_old() + acpi_power_off_prepare() + pm_power_off_prepare() + +Hibernation (S4) and Power Off (S5) don't require cache flushing, so +the only interesting callsites are acpi_suspend_ops::prepare_late() +and acpi_suspend_begin_old::begin(). Both of them have cache flush +on ->enter() operation in acpi_suspend_enter(). + +Remove redundant ACPI_FLUSH_CPU_CACHE() in acpi_sleep_prepare() and +acpi_suspend_enter(). + +Signed-off-by: Kirill A. Shutemov +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/sleep.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -73,7 +73,6 @@ static int acpi_sleep_prepare(u32 acpi_s + acpi_set_waking_vector(acpi_wakeup_address); + + } +- ACPI_FLUSH_CPU_CACHE(); + #endif + pr_info("Preparing to enter system sleep state S%d\n", acpi_state); + acpi_enable_wakeup_devices(acpi_state); +@@ -566,8 +565,6 @@ static int acpi_suspend_enter(suspend_st + u32 acpi_state = acpi_target_sleep_state; + int error; + +- ACPI_FLUSH_CPU_CACHE(); +- + trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true); + switch (acpi_state) { + case ACPI_STATE_S1: diff --git a/patches.suse/ACPI-PMIC-allow-drivers-to-provide-a-custom-lpat_raw.patch b/patches.suse/ACPI-PMIC-allow-drivers-to-provide-a-custom-lpat_raw.patch new file mode 100644 index 0000000..a29320d --- /dev/null +++ b/patches.suse/ACPI-PMIC-allow-drivers-to-provide-a-custom-lpat_raw.patch @@ -0,0 +1,120 @@ +From: Hans de Goede +Date: Fri, 26 Nov 2021 16:21:08 +0100 +Subject: ACPI: PMIC: allow drivers to provide a custom lpat_raw_to_temp() + function +Patch-mainline: v5.17-rc1 +Git-commit: c5200609c9176482ea96ac73e52bd466b622f385 +References: jsc#PED-1408 + +The LPAT tables used in the DSDT for some PMICs require special handling, +allow the PMIC OpRegion drivers to provide an alternative implementation +by adding a lpat_raw_to_temp function pointer to struct pmic_table; +and initialize this to the default acpi_lpat_raw_to_temp function +for all PMICs. + +Signed-off-by: Hans de Goede +Reviewed-by: Andy Shevchenko +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/pmic/intel_pmic.c | 2 +- + drivers/acpi/pmic/intel_pmic.h | 4 ++++ + drivers/acpi/pmic/intel_pmic_bxtwc.c | 1 + + drivers/acpi/pmic/intel_pmic_bytcrc.c | 1 + + drivers/acpi/pmic/intel_pmic_chtcrc.c | 1 + + drivers/acpi/pmic/intel_pmic_chtdc_ti.c | 1 + + drivers/acpi/pmic/intel_pmic_chtwc.c | 1 + + drivers/acpi/pmic/intel_pmic_xpower.c | 1 + + 8 files changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/pmic/intel_pmic.c ++++ b/drivers/acpi/pmic/intel_pmic.c +@@ -95,7 +95,7 @@ static int pmic_read_temp(struct intel_p + return 0; + } + +- temp = acpi_lpat_raw_to_temp(opregion->lpat_table, raw_temp); ++ temp = opregion->data->lpat_raw_to_temp(opregion->lpat_table, raw_temp); + if (temp < 0) + return temp; + +--- a/drivers/acpi/pmic/intel_pmic.h ++++ b/drivers/acpi/pmic/intel_pmic.h +@@ -2,6 +2,8 @@ + #ifndef __INTEL_PMIC_H + #define __INTEL_PMIC_H + ++#include ++ + struct pmic_table { + int address; /* operation region address */ + int reg; /* corresponding thermal register */ +@@ -17,6 +19,8 @@ struct intel_pmic_opregion_data { + int (*update_policy)(struct regmap *r, int reg, int bit, int enable); + int (*exec_mipi_pmic_seq_element)(struct regmap *r, u16 i2c_address, + u32 reg_address, u32 value, u32 mask); ++ int (*lpat_raw_to_temp)(struct acpi_lpat_conversion_table *lpat_table, ++ int raw); + struct pmic_table *power_table; + int power_table_count; + struct pmic_table *thermal_table; +--- a/drivers/acpi/pmic/intel_pmic_bxtwc.c ++++ b/drivers/acpi/pmic/intel_pmic_bxtwc.c +@@ -376,6 +376,7 @@ static const struct intel_pmic_opregion_ + .update_aux = intel_bxtwc_pmic_update_aux, + .get_policy = intel_bxtwc_pmic_get_policy, + .update_policy = intel_bxtwc_pmic_update_policy, ++ .lpat_raw_to_temp = acpi_lpat_raw_to_temp, + .power_table = power_table, + .power_table_count = ARRAY_SIZE(power_table), + .thermal_table = thermal_table, +--- a/drivers/acpi/pmic/intel_pmic_bytcrc.c ++++ b/drivers/acpi/pmic/intel_pmic_bytcrc.c +@@ -278,6 +278,7 @@ static const struct intel_pmic_opregion_ + .update_aux = intel_crc_pmic_update_aux, + .get_policy = intel_crc_pmic_get_policy, + .update_policy = intel_crc_pmic_update_policy, ++ .lpat_raw_to_temp = acpi_lpat_raw_to_temp, + .power_table = power_table, + .power_table_count= ARRAY_SIZE(power_table), + .thermal_table = thermal_table, +--- a/drivers/acpi/pmic/intel_pmic_chtcrc.c ++++ b/drivers/acpi/pmic/intel_pmic_chtcrc.c +@@ -24,6 +24,7 @@ + * CHT Crystal Cove PMIC. + */ + static const struct intel_pmic_opregion_data intel_chtcrc_pmic_opregion_data = { ++ .lpat_raw_to_temp = acpi_lpat_raw_to_temp, + .pmic_i2c_address = 0x6e, + }; + +--- a/drivers/acpi/pmic/intel_pmic_chtdc_ti.c ++++ b/drivers/acpi/pmic/intel_pmic_chtdc_ti.c +@@ -98,6 +98,7 @@ static const struct intel_pmic_opregion_ + .get_power = chtdc_ti_pmic_get_power, + .update_power = chtdc_ti_pmic_update_power, + .get_raw_temp = chtdc_ti_pmic_get_raw_temp, ++ .lpat_raw_to_temp = acpi_lpat_raw_to_temp, + .power_table = chtdc_ti_power_table, + .power_table_count = ARRAY_SIZE(chtdc_ti_power_table), + .thermal_table = chtdc_ti_thermal_table, +--- a/drivers/acpi/pmic/intel_pmic_chtwc.c ++++ b/drivers/acpi/pmic/intel_pmic_chtwc.c +@@ -257,6 +257,7 @@ static const struct intel_pmic_opregion_ + .get_power = intel_cht_wc_pmic_get_power, + .update_power = intel_cht_wc_pmic_update_power, + .exec_mipi_pmic_seq_element = intel_cht_wc_exec_mipi_pmic_seq_element, ++ .lpat_raw_to_temp = acpi_lpat_raw_to_temp, + .power_table = power_table, + .power_table_count = ARRAY_SIZE(power_table), + }; +--- a/drivers/acpi/pmic/intel_pmic_xpower.c ++++ b/drivers/acpi/pmic/intel_pmic_xpower.c +@@ -298,6 +298,7 @@ static const struct intel_pmic_opregion_ + .update_power = intel_xpower_pmic_update_power, + .get_raw_temp = intel_xpower_pmic_get_raw_temp, + .exec_mipi_pmic_seq_element = intel_xpower_exec_mipi_pmic_seq_element, ++ .lpat_raw_to_temp = acpi_lpat_raw_to_temp, + .power_table = power_table, + .power_table_count = ARRAY_SIZE(power_table), + .thermal_table = thermal_table, diff --git a/patches.suse/ACPI-PMIC-constify-all-struct-intel_pmic_opregion_da.patch b/patches.suse/ACPI-PMIC-constify-all-struct-intel_pmic_opregion_da.patch new file mode 100644 index 0000000..9ac4ae3 --- /dev/null +++ b/patches.suse/ACPI-PMIC-constify-all-struct-intel_pmic_opregion_da.patch @@ -0,0 +1,159 @@ +From: Hans de Goede +Date: Fri, 26 Nov 2021 16:21:07 +0100 +Subject: ACPI: PMIC: constify all struct intel_pmic_opregion_data declarations +Patch-mainline: v5.17-rc1 +Git-commit: e172e650eda3274964df3a74cf12d210eae9a044 +References: jsc#PED-1408 + +The struct intel_pmic_opregion_data declarations never change, +constify them all. + +Signed-off-by: Hans de Goede +Reviewed-by: Andy Shevchenko +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/pmic/intel_pmic.c | 12 ++++++------ + drivers/acpi/pmic/intel_pmic.h | 4 +++- + drivers/acpi/pmic/intel_pmic_bxtwc.c | 2 +- + drivers/acpi/pmic/intel_pmic_bytcrc.c | 2 +- + drivers/acpi/pmic/intel_pmic_chtcrc.c | 2 +- + drivers/acpi/pmic/intel_pmic_chtdc_ti.c | 2 +- + drivers/acpi/pmic/intel_pmic_chtwc.c | 2 +- + drivers/acpi/pmic/intel_pmic_xpower.c | 2 +- + 8 files changed, 15 insertions(+), 13 deletions(-) + +--- a/drivers/acpi/pmic/intel_pmic.c ++++ b/drivers/acpi/pmic/intel_pmic.c +@@ -25,7 +25,7 @@ struct intel_pmic_opregion { + struct mutex lock; + struct acpi_lpat_conversion_table *lpat_table; + struct regmap *regmap; +- struct intel_pmic_opregion_data *data; ++ const struct intel_pmic_opregion_data *data; + struct intel_pmic_regs_handler_ctx ctx; + }; + +@@ -53,7 +53,7 @@ static acpi_status intel_pmic_power_hand + { + struct intel_pmic_opregion *opregion = region_context; + struct regmap *regmap = opregion->regmap; +- struct intel_pmic_opregion_data *d = opregion->data; ++ const struct intel_pmic_opregion_data *d = opregion->data; + int reg, bit, result; + + if (bits != 32 || !value64) +@@ -135,7 +135,7 @@ static int pmic_thermal_aux(struct intel + static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg, + int bit, u32 function, u64 *value) + { +- struct intel_pmic_opregion_data *d = opregion->data; ++ const struct intel_pmic_opregion_data *d = opregion->data; + struct regmap *regmap = opregion->regmap; + + if (!d->get_policy || !d->update_policy) +@@ -171,7 +171,7 @@ static acpi_status intel_pmic_thermal_ha + void *handler_context, void *region_context) + { + struct intel_pmic_opregion *opregion = region_context; +- struct intel_pmic_opregion_data *d = opregion->data; ++ const struct intel_pmic_opregion_data *d = opregion->data; + int reg, bit, result; + + if (bits != 32 || !value64) +@@ -255,7 +255,7 @@ static acpi_status intel_pmic_regs_handl + + int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, + struct regmap *regmap, +- struct intel_pmic_opregion_data *d) ++ const struct intel_pmic_opregion_data *d) + { + acpi_status status = AE_OK; + struct intel_pmic_opregion *opregion; +@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(intel_pmic_install_opr + int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address, + u32 value, u32 mask) + { +- struct intel_pmic_opregion_data *d; ++ const struct intel_pmic_opregion_data *d; + int ret; + + if (!intel_pmic_opregion) { +--- a/drivers/acpi/pmic/intel_pmic.h ++++ b/drivers/acpi/pmic/intel_pmic.h +@@ -25,6 +25,8 @@ struct intel_pmic_opregion_data { + int pmic_i2c_address; + }; + +-int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, struct regmap *regmap, struct intel_pmic_opregion_data *d); ++int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, ++ struct regmap *regmap, ++ const struct intel_pmic_opregion_data *d); + + #endif +--- a/drivers/acpi/pmic/intel_pmic_bxtwc.c ++++ b/drivers/acpi/pmic/intel_pmic_bxtwc.c +@@ -369,7 +369,7 @@ intel_bxtwc_pmic_update_policy(struct re + return regmap_update_bits(regmap, reg, mask, val); + } + +-static struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = { ++static const struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = { + .get_power = intel_bxtwc_pmic_get_power, + .update_power = intel_bxtwc_pmic_update_power, + .get_raw_temp = intel_bxtwc_pmic_get_raw_temp, +--- a/drivers/acpi/pmic/intel_pmic_bytcrc.c ++++ b/drivers/acpi/pmic/intel_pmic_bytcrc.c +@@ -271,7 +271,7 @@ static int intel_crc_pmic_update_policy( + return 0; + } + +-static struct intel_pmic_opregion_data intel_crc_pmic_opregion_data = { ++static const struct intel_pmic_opregion_data intel_crc_pmic_opregion_data = { + .get_power = intel_crc_pmic_get_power, + .update_power = intel_crc_pmic_update_power, + .get_raw_temp = intel_crc_pmic_get_raw_temp, +--- a/drivers/acpi/pmic/intel_pmic_chtcrc.c ++++ b/drivers/acpi/pmic/intel_pmic_chtcrc.c +@@ -23,7 +23,7 @@ + * intel_soc_pmic_exec_mipi_pmic_seq_element work on devices with a + * CHT Crystal Cove PMIC. + */ +-static struct intel_pmic_opregion_data intel_chtcrc_pmic_opregion_data = { ++static const struct intel_pmic_opregion_data intel_chtcrc_pmic_opregion_data = { + .pmic_i2c_address = 0x6e, + }; + +--- a/drivers/acpi/pmic/intel_pmic_chtdc_ti.c ++++ b/drivers/acpi/pmic/intel_pmic_chtdc_ti.c +@@ -94,7 +94,7 @@ static int chtdc_ti_pmic_get_raw_temp(st + return ((buf[0] & 0x03) << 8) | buf[1]; + } + +-static struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = { ++static const struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = { + .get_power = chtdc_ti_pmic_get_power, + .update_power = chtdc_ti_pmic_update_power, + .get_raw_temp = chtdc_ti_pmic_get_raw_temp, +--- a/drivers/acpi/pmic/intel_pmic_chtwc.c ++++ b/drivers/acpi/pmic/intel_pmic_chtwc.c +@@ -253,7 +253,7 @@ static int intel_cht_wc_exec_mipi_pmic_s + * The thermal table and ops are empty, we do not support the Thermal opregion + * (DPTF) due to lacking documentation. + */ +-static struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = { ++static const struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = { + .get_power = intel_cht_wc_pmic_get_power, + .update_power = intel_cht_wc_pmic_update_power, + .exec_mipi_pmic_seq_element = intel_cht_wc_exec_mipi_pmic_seq_element, +--- a/drivers/acpi/pmic/intel_pmic_xpower.c ++++ b/drivers/acpi/pmic/intel_pmic_xpower.c +@@ -293,7 +293,7 @@ static int intel_xpower_exec_mipi_pmic_s + return ret; + } + +-static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { ++static const struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { + .get_power = intel_xpower_pmic_get_power, + .update_power = intel_xpower_pmic_update_power, + .get_raw_temp = intel_xpower_pmic_get_raw_temp, diff --git a/patches.suse/ACPI-PMIC-xpower-Fix-_TMP-ACPI-errors.patch b/patches.suse/ACPI-PMIC-xpower-Fix-_TMP-ACPI-errors.patch new file mode 100644 index 0000000..1d09f4d --- /dev/null +++ b/patches.suse/ACPI-PMIC-xpower-Fix-_TMP-ACPI-errors.patch @@ -0,0 +1,73 @@ +From: Hans de Goede +Date: Fri, 26 Nov 2021 16:21:09 +0100 +Subject: ACPI: PMIC: xpower: Fix _TMP ACPI errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Patch-mainline: v5.17-rc1 +Git-commit: 5f96ba56552121f4297874d0accf29b9b4a1ae93 +References: jsc#PED-1408 + +On some devices with a X-Powers AXP288 PMIC the LPAT tables in the ACPI +node for the AXP288 PMIC for some reason only describe a small temperature +range, e.g. 27° - 37° Celcius (assuming the entries are in millidegrees). + +When the tablet is idle in a room at 21° degrees this is causing values +outside the LPAT table to be read, causing e.g. the following 2 errors +to get spammed to the logs every 4 seconds! : + +[ 7512.791316] ACPI Error: AE_ERROR, Returned by Handler for [UserDefinedRegion] (20210930/evregion-281) +[ 7512.791611] ACPI Error: Aborting method \_SB.SXP1._TMP due to previous error (AE_ERROR) (20210930/psparse-529) + +Fix this by clamping the raw value to the LPAT table range before +passing it to acpi_lpat_raw_to_temp(). + +Note clamping has been chosen rather then extrapolating because it is +unknown how other parts of the ACPI tables will respond to temperature +values outside of the LPAT range. + +Signed-off-by: Hans de Goede +Reviewed-by: Andy Shevchenko +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/pmic/intel_pmic_xpower.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/pmic/intel_pmic_xpower.c ++++ b/drivers/acpi/pmic/intel_pmic_xpower.c +@@ -293,12 +293,33 @@ static int intel_xpower_exec_mipi_pmic_s + return ret; + } + ++static int intel_xpower_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table, ++ int raw) ++{ ++ struct acpi_lpat first = lpat_table->lpat[0]; ++ struct acpi_lpat last = lpat_table->lpat[lpat_table->lpat_count - 1]; ++ ++ /* ++ * Some LPAT tables in the ACPI Device for the AXP288 PMIC for some ++ * reason only describe a small temperature range, e.g. 27° - 37° ++ * Celcius. Resulting in errors when the tablet is idle in a cool room. ++ * ++ * To avoid these errors clamp the raw value to be inside the LPAT. ++ */ ++ if (first.raw < last.raw) ++ raw = clamp(raw, first.raw, last.raw); ++ else ++ raw = clamp(raw, last.raw, first.raw); ++ ++ return acpi_lpat_raw_to_temp(lpat_table, raw); ++} ++ + static const struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { + .get_power = intel_xpower_pmic_get_power, + .update_power = intel_xpower_pmic_update_power, + .get_raw_temp = intel_xpower_pmic_get_raw_temp, + .exec_mipi_pmic_seq_element = intel_xpower_exec_mipi_pmic_seq_element, +- .lpat_raw_to_temp = acpi_lpat_raw_to_temp, ++ .lpat_raw_to_temp = intel_xpower_lpat_raw_to_temp, + .power_table = power_table, + .power_table_count = ARRAY_SIZE(power_table), + .thermal_table = thermal_table, diff --git a/patches.suse/ACPI-SPCR-check-if-table-serial_port.access_width-is.patch b/patches.suse/ACPI-SPCR-check-if-table-serial_port.access_width-is.patch new file mode 100644 index 0000000..c454570 --- /dev/null +++ b/patches.suse/ACPI-SPCR-check-if-table-serial_port.access_width-is.patch @@ -0,0 +1,42 @@ +From: Mark Langsdorf +Date: Wed, 5 Jan 2022 11:47:14 -0600 +Subject: ACPI: SPCR: check if table->serial_port.access_width is too wide +Patch-mainline: v5.17-rc1 +Git-commit: ee3fe99ff0a27108ac38d9766ac0e92f5ec35692 +References: jsc#PED-1408 + +If table->serial_port.access_width is more than 29, it causes +undefined behavior when ACPI_ACCESS_BIT_WIDTH shifts it to +(1 << ((size) + 2)): + +[ 0.000000] UBSAN: Undefined behaviour in drivers/acpi/spcr.c:114:11 +[ 0.000000] shift exponent 102 is too large for 32-bit type 'int' + +Use the new ACPI_ACCESS_ defines to test that serial_port.access_width +is less than 30 and set it to 6 if it is not. + +Signed-off-by: Mark Langsdorf +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/spcr.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/acpi/spcr.c ++++ b/drivers/acpi/spcr.c +@@ -107,8 +107,13 @@ int __init acpi_parse_spcr(bool enable_e + pr_info("SPCR table version %d\n", table->header.revision); + + if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { +- switch (ACPI_ACCESS_BIT_WIDTH(( +- table->serial_port.access_width))) { ++ u32 bit_width = table->serial_port.access_width; ++ ++ if (bit_width > ACPI_ACCESS_BIT_MAX) { ++ pr_err("Unacceptable wide SPCR Access Width. Defaulting to byte size\n"); ++ bit_width = ACPI_ACCESS_BIT_DEFAULT; ++ } ++ switch (ACPI_ACCESS_BIT_WIDTH((bit_width))) { + default: + pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n"); + fallthrough; diff --git a/patches.suse/ACPI-Teach-ACPI-table-parsing-about-the-CEDT-header-.patch b/patches.suse/ACPI-Teach-ACPI-table-parsing-about-the-CEDT-header-.patch new file mode 100644 index 0000000..e854bca --- /dev/null +++ b/patches.suse/ACPI-Teach-ACPI-table-parsing-about-the-CEDT-header-.patch @@ -0,0 +1,79 @@ +From: Dan Williams +Date: Fri, 29 Oct 2021 12:51:37 -0700 +Subject: ACPI: Teach ACPI table parsing about the CEDT header format +Patch-mainline: v5.17-rc1 +Git-commit: ad2f63971e9655e3987db32dac85aa50658790eb +References: jsc#PED-1408 + +The CEDT adds yet one more unique subtable header type where the length +is a 16-bit value. Extend the subtable helpers to detect this scenario. + +Cc: "Rafael J. Wysocki" +Cc: Len Brown +Tested-by: Alison Schofield +Reviewed-by: Alison Schofield +Acked-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/163553709742.2509508.5177761945441327574.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/tables.c | 9 +++++++++ + include/linux/acpi.h | 1 + + 2 files changed, 10 insertions(+) + +--- a/drivers/acpi/tables.c ++++ b/drivers/acpi/tables.c +@@ -40,6 +40,7 @@ enum acpi_subtable_type { + ACPI_SUBTABLE_COMMON, + ACPI_SUBTABLE_HMAT, + ACPI_SUBTABLE_PRMT, ++ ACPI_SUBTABLE_CEDT, + }; + + struct acpi_subtable_entry { +@@ -225,6 +226,8 @@ acpi_get_entry_type(struct acpi_subtable + return entry->hdr->hmat.type; + case ACPI_SUBTABLE_PRMT: + return 0; ++ case ACPI_SUBTABLE_CEDT: ++ return entry->hdr->cedt.type; + } + return 0; + } +@@ -239,6 +242,8 @@ acpi_get_entry_length(struct acpi_subtab + return entry->hdr->hmat.length; + case ACPI_SUBTABLE_PRMT: + return entry->hdr->prmt.length; ++ case ACPI_SUBTABLE_CEDT: ++ return entry->hdr->cedt.length; + } + return 0; + } +@@ -253,6 +258,8 @@ acpi_get_subtable_header_length(struct a + return sizeof(entry->hdr->hmat); + case ACPI_SUBTABLE_PRMT: + return sizeof(entry->hdr->prmt); ++ case ACPI_SUBTABLE_CEDT: ++ return sizeof(entry->hdr->cedt); + } + return 0; + } +@@ -264,6 +271,8 @@ acpi_get_subtable_type(char *id) + return ACPI_SUBTABLE_HMAT; + if (strncmp(id, ACPI_SIG_PRMT, 4) == 0) + return ACPI_SUBTABLE_PRMT; ++ if (strncmp(id, ACPI_SIG_CEDT, 4) == 0) ++ return ACPI_SUBTABLE_CEDT; + return ACPI_SUBTABLE_COMMON; + } + +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -133,6 +133,7 @@ union acpi_subtable_headers { + struct acpi_subtable_header common; + struct acpi_hmat_structure hmat; + struct acpi_prmt_module_header prmt; ++ struct acpi_cedt_header cedt; + }; + + typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table); diff --git a/patches.suse/ACPI-Use-acpi_fetch_acpi_dev-instead-of-acpi_bus_get.patch b/patches.suse/ACPI-Use-acpi_fetch_acpi_dev-instead-of-acpi_bus_get.patch new file mode 100644 index 0000000..af80f1b --- /dev/null +++ b/patches.suse/ACPI-Use-acpi_fetch_acpi_dev-instead-of-acpi_bus_get.patch @@ -0,0 +1,367 @@ +From: "Rafael J. Wysocki" +Date: Fri, 3 Dec 2021 17:37:10 +0100 +Subject: ACPI: Use acpi_fetch_acpi_dev() instead of acpi_bus_get_device() +Patch-mainline: v5.17-rc1 +Git-commit: 99ece713773bfa17fdb4ee2a1fb3b7bee82e4b1a +References: jsc#PED-1408 + +Modify the ACPI code to use acpi_fetch_acpi_dev() instead of +acpi_bus_get_device() where applicable. + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Mika Westerberg +Reviewed-by: Hans de Goede +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpi_video.c | 5 ++--- + drivers/acpi/device_pm.c | 31 +++++++++++++------------------ + drivers/acpi/dock.c | 3 +-- + drivers/acpi/pci_link.c | 12 ++++-------- + drivers/acpi/pci_root.c | 10 ++++------ + drivers/acpi/power.c | 7 +++---- + drivers/acpi/processor_driver.c | 10 +++++++--- + drivers/acpi/processor_idle.c | 2 +- + drivers/acpi/property.c | 11 +++++------ + drivers/acpi/resource.c | 4 ++-- + drivers/acpi/thermal.c | 9 ++++----- + drivers/acpi/video_detect.c | 6 ++---- + drivers/acpi/x86/s2idle.c | 4 ++-- + 13 files changed, 50 insertions(+), 64 deletions(-) + +--- a/drivers/acpi/acpi_video.c ++++ b/drivers/acpi/acpi_video.c +@@ -1733,13 +1733,12 @@ acpi_video_bus_match(acpi_handle handle, + { + struct acpi_device *device = context; + struct acpi_device *sibling; +- int result; + + if (handle == device->handle) + return AE_CTRL_TERMINATE; + +- result = acpi_bus_get_device(handle, &sibling); +- if (result) ++ sibling = acpi_fetch_acpi_dev(handle); ++ if (!sibling) + return AE_OK; + + if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) +--- a/drivers/acpi/device_pm.c ++++ b/drivers/acpi/device_pm.c +@@ -285,14 +285,12 @@ EXPORT_SYMBOL(acpi_device_set_power); + + int acpi_bus_set_power(acpi_handle handle, int state) + { +- struct acpi_device *device; +- int result; ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + +- result = acpi_bus_get_device(handle, &device); +- if (result) +- return result; ++ if (device) ++ return acpi_device_set_power(device, state); + +- return acpi_device_set_power(device, state); ++ return -ENODEV; + } + EXPORT_SYMBOL(acpi_bus_set_power); + +@@ -410,21 +408,20 @@ EXPORT_SYMBOL_GPL(acpi_device_update_pow + + int acpi_bus_update_power(acpi_handle handle, int *state_p) + { +- struct acpi_device *device; +- int result; ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + +- result = acpi_bus_get_device(handle, &device); +- return result ? result : acpi_device_update_power(device, state_p); ++ if (device) ++ return acpi_device_update_power(device, state_p); ++ ++ return -ENODEV; + } + EXPORT_SYMBOL_GPL(acpi_bus_update_power); + + bool acpi_bus_power_manageable(acpi_handle handle) + { +- struct acpi_device *device; +- int result; ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + +- result = acpi_bus_get_device(handle, &device); +- return result ? false : device->flags.power_manageable; ++ return device && device->flags.power_manageable; + } + EXPORT_SYMBOL(acpi_bus_power_manageable); + +@@ -543,11 +540,9 @@ acpi_status acpi_remove_pm_notifier(stru + + bool acpi_bus_can_wakeup(acpi_handle handle) + { +- struct acpi_device *device; +- int result; ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + +- result = acpi_bus_get_device(handle, &device); +- return result ? false : device->wakeup.flags.valid; ++ return device && device->wakeup.flags.valid; + } + EXPORT_SYMBOL(acpi_bus_can_wakeup); + +--- a/drivers/acpi/dock.c ++++ b/drivers/acpi/dock.c +@@ -489,9 +489,8 @@ static ssize_t docked_show(struct device + struct device_attribute *attr, char *buf) + { + struct dock_station *dock_station = dev->platform_data; +- struct acpi_device *adev = NULL; ++ struct acpi_device *adev = acpi_fetch_acpi_dev(dock_station->handle); + +- acpi_bus_get_device(dock_station->handle, &adev); + return sysfs_emit(buf, "%u\n", acpi_device_enumerated(adev)); + } + static DEVICE_ATTR_RO(docked); +--- a/drivers/acpi/pci_link.c ++++ b/drivers/acpi/pci_link.c +@@ -606,12 +606,10 @@ static int acpi_pci_link_allocate(struct + int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, + int *polarity, char **name) + { +- int result; +- struct acpi_device *device; ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + struct acpi_pci_link *link; + +- result = acpi_bus_get_device(handle, &device); +- if (result) { ++ if (!device) { + acpi_handle_err(handle, "Invalid link device\n"); + return -1; + } +@@ -658,12 +656,10 @@ int acpi_pci_link_allocate_irq(acpi_hand + */ + int acpi_pci_link_free_irq(acpi_handle handle) + { +- struct acpi_device *device; ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + struct acpi_pci_link *link; +- acpi_status result; + +- result = acpi_bus_get_device(handle, &device); +- if (result) { ++ if (!device) { + acpi_handle_err(handle, "Invalid link device\n"); + return -1; + } +--- a/drivers/acpi/pci_root.c ++++ b/drivers/acpi/pci_root.c +@@ -67,11 +67,10 @@ static struct acpi_scan_handler pci_root + */ + int acpi_is_root_bridge(acpi_handle handle) + { ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + int ret; +- struct acpi_device *device; + +- ret = acpi_bus_get_device(handle, &device); +- if (ret) ++ if (!device) + return 0; + + ret = acpi_match_device_ids(device, root_device_ids); +@@ -215,11 +214,10 @@ static acpi_status acpi_pci_query_osc(st + + struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) + { ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + struct acpi_pci_root *root; +- struct acpi_device *device; + +- if (acpi_bus_get_device(handle, &device) || +- acpi_match_device_ids(device, root_device_ids)) ++ if (!device || acpi_match_device_ids(device, root_device_ids)) + return NULL; + + root = acpi_driver_data(device); +--- a/drivers/acpi/power.c ++++ b/drivers/acpi/power.c +@@ -81,9 +81,9 @@ struct acpi_power_resource *to_power_res + + static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle) + { +- struct acpi_device *device; ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + +- if (acpi_bus_get_device(handle, &device)) ++ if (!device) + return NULL; + + return to_power_resource(device); +@@ -916,15 +916,14 @@ static void acpi_power_add_resource_to_l + + struct acpi_device *acpi_add_power_resource(acpi_handle handle) + { ++ struct acpi_device *device = acpi_fetch_acpi_dev(handle); + struct acpi_power_resource *resource; +- struct acpi_device *device = NULL; + union acpi_object acpi_object; + struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; + acpi_status status; + u8 state_dummy; + int result; + +- acpi_bus_get_device(handle, &device); + if (device) + return device; + +--- a/drivers/acpi/processor_driver.c ++++ b/drivers/acpi/processor_driver.c +@@ -98,8 +98,13 @@ static int acpi_soft_cpu_online(unsigned + struct acpi_processor *pr = per_cpu(processors, cpu); + struct acpi_device *device; + +- if (!pr || acpi_bus_get_device(pr->handle, &device)) ++ if (!pr) + return 0; ++ ++ device = acpi_fetch_acpi_dev(pr->handle); ++ if (!device) ++ return 0; ++ + /* + * CPU got physically hotplugged and onlined for the first time: + * Initialize missing things. +@@ -125,9 +130,8 @@ static int acpi_soft_cpu_online(unsigned + static int acpi_soft_cpu_dead(unsigned int cpu) + { + struct acpi_processor *pr = per_cpu(processors, cpu); +- struct acpi_device *device; + +- if (!pr || acpi_bus_get_device(pr->handle, &device)) ++ if (!pr || !acpi_fetch_acpi_dev(pr->handle)) + return 0; + + acpi_processor_reevaluate_tstate(pr, true); +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -1101,7 +1101,7 @@ static int acpi_processor_get_lpi_info(s + + status = acpi_get_parent(handle, &pr_ahandle); + while (ACPI_SUCCESS(status)) { +- acpi_bus_get_device(pr_ahandle, &d); ++ d = acpi_fetch_acpi_dev(pr_ahandle); + handle = pr_ahandle; + + if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID)) +--- a/drivers/acpi/property.c ++++ b/drivers/acpi/property.c +@@ -687,9 +687,9 @@ int __acpi_node_get_property_reference(c + if (index) + return -EINVAL; + +- ret = acpi_bus_get_device(obj->reference.handle, &device); +- if (ret) +- return ret == -ENODEV ? -EINVAL : ret; ++ device = acpi_fetch_acpi_dev(obj->reference.handle); ++ if (!device) ++ return -EINVAL; + + args->fwnode = acpi_fwnode_handle(device); + args->nargs = 0; +@@ -719,9 +719,8 @@ int __acpi_node_get_property_reference(c + if (element->type == ACPI_TYPE_LOCAL_REFERENCE) { + struct fwnode_handle *ref_fwnode; + +- ret = acpi_bus_get_device(element->reference.handle, +- &device); +- if (ret) ++ device = acpi_fetch_acpi_dev(element->reference.handle); ++ if (!device) + return -EINVAL; + + nargs = 0; +--- a/drivers/acpi/resource.c ++++ b/drivers/acpi/resource.c +@@ -791,9 +791,9 @@ static acpi_status acpi_res_consumer_cb( + { + struct resource *res = context; + struct acpi_device **consumer = (struct acpi_device **) ret; +- struct acpi_device *adev; ++ struct acpi_device *adev = acpi_fetch_acpi_dev(handle); + +- if (acpi_bus_get_device(handle, &adev)) ++ if (!adev) + return AE_OK; + + if (acpi_dev_consumes_res(adev, res)) { +--- a/drivers/acpi/thermal.c ++++ b/drivers/acpi/thermal.c +@@ -697,7 +697,6 @@ static int acpi_thermal_cooling_device_c + struct acpi_device *device = cdev->devdata; + struct acpi_thermal *tz = thermal->devdata; + struct acpi_device *dev; +- acpi_status status; + acpi_handle handle; + int i; + int j; +@@ -715,8 +714,8 @@ static int acpi_thermal_cooling_device_c + for (i = 0; i < tz->trips.passive.devices.count; + i++) { + handle = tz->trips.passive.devices.handles[i]; +- status = acpi_bus_get_device(handle, &dev); +- if (ACPI_FAILURE(status) || dev != device) ++ dev = acpi_fetch_acpi_dev(handle); ++ if (dev != device) + continue; + if (bind) + result = +@@ -741,8 +740,8 @@ static int acpi_thermal_cooling_device_c + j < tz->trips.active[i].devices.count; + j++) { + handle = tz->trips.active[i].devices.handles[j]; +- status = acpi_bus_get_device(handle, &dev); +- if (ACPI_FAILURE(status) || dev != device) ++ dev = acpi_fetch_acpi_dev(handle); ++ if (dev != device) + continue; + if (bind) + result = thermal_zone_bind_cooling_device +--- a/drivers/acpi/video_detect.c ++++ b/drivers/acpi/video_detect.c +@@ -59,18 +59,16 @@ static void acpi_video_parse_cmdline(voi + static acpi_status + find_video(acpi_handle handle, u32 lvl, void *context, void **rv) + { ++ struct acpi_device *acpi_dev = acpi_fetch_acpi_dev(handle); + long *cap = context; + struct pci_dev *dev; +- struct acpi_device *acpi_dev; + + static const struct acpi_device_id video_ids[] = { + {ACPI_VIDEO_HID, 0}, + {"", 0}, + }; +- if (acpi_bus_get_device(handle, &acpi_dev)) +- return AE_OK; + +- if (!acpi_match_device_ids(acpi_dev, video_ids)) { ++ if (acpi_dev && !acpi_match_device_ids(acpi_dev, video_ids)) { + dev = acpi_get_pci_dev(handle); + if (!dev) + return AE_OK; +--- a/drivers/acpi/x86/s2idle.c ++++ b/drivers/acpi/x86/s2idle.c +@@ -293,9 +293,9 @@ static void lpi_check_constraints(void) + + for (i = 0; i < lpi_constraints_table_size; ++i) { + acpi_handle handle = lpi_constraints_table[i].handle; +- struct acpi_device *adev; ++ struct acpi_device *adev = acpi_fetch_acpi_dev(handle); + +- if (!handle || acpi_bus_get_device(handle, &adev)) ++ if (!adev) + continue; + + acpi_handle_debug(handle, diff --git a/patches.suse/ACPI-battery-Add-the-ThinkPad-Not-Charging-quirk.patch b/patches.suse/ACPI-battery-Add-the-ThinkPad-Not-Charging-quirk.patch index 36890c4..5522016 100644 --- a/patches.suse/ACPI-battery-Add-the-ThinkPad-Not-Charging-quirk.patch +++ b/patches.suse/ACPI-battery-Add-the-ThinkPad-Not-Charging-quirk.patch @@ -23,22 +23,20 @@ Signed-off-by: Rafael J. Wysocki Acked-by: Takashi Iwai --- - drivers/acpi/battery.c | 22 ++++++++++++++++++++++ + drivers/acpi/battery.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) -diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c -index 8afa85d6eb6a..ead0114f27c9 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c -@@ -53,6 +53,7 @@ static int battery_bix_broken_package; +@@ -52,6 +52,7 @@ static bool battery_driver_registered; + static int battery_bix_broken_package; static int battery_notification_delay_ms; static int battery_ac_is_broken; - static int battery_check_pmic = 1; +static int battery_quirk_notcharging; static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -@@ -217,6 +218,8 @@ static int acpi_battery_get_property(struct power_supply *psy, +@@ -211,6 +212,8 @@ static int acpi_battery_get_property(str val->intval = POWER_SUPPLY_STATUS_CHARGING; else if (acpi_battery_is_charged(battery)) val->intval = POWER_SUPPLY_STATUS_FULL; @@ -47,7 +45,7 @@ index 8afa85d6eb6a..ead0114f27c9 100644 else val->intval = POWER_SUPPLY_STATUS_UNKNOWN; break; -@@ -1111,6 +1114,12 @@ battery_do_not_check_pmic_quirk(const struct dmi_system_id *d) +@@ -1098,6 +1101,12 @@ battery_ac_is_broken_quirk(const struct return 0; } @@ -60,8 +58,8 @@ index 8afa85d6eb6a..ead0114f27c9 100644 static const struct dmi_system_id bat_dmi_table[] __initconst = { { /* NEC LZ750/LS */ -@@ -1155,6 +1164,19 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), +@@ -1126,6 +1135,19 @@ static const struct dmi_system_id bat_dm + DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), }, }, + { @@ -80,6 +78,3 @@ index 8afa85d6eb6a..ead0114f27c9 100644 {}, }; --- -2.31.1 - diff --git a/patches.suse/ACPI-delay-enumeration-of-devices-with-a-_DEP-pointi.patch b/patches.suse/ACPI-delay-enumeration-of-devices-with-a-_DEP-pointi.patch new file mode 100644 index 0000000..feccd7e --- /dev/null +++ b/patches.suse/ACPI-delay-enumeration-of-devices-with-a-_DEP-pointi.patch @@ -0,0 +1,182 @@ +From: Hans de Goede +Date: Fri, 3 Dec 2021 11:28:44 +0100 +Subject: ACPI: delay enumeration of devices with a _DEP pointing to an INT3472 + device +Patch-mainline: v5.17-rc1 +Git-commit: 9d9bcae47fd5a0b827521f65ab7d10a218eacc37 +References: jsc#PED-1408 + +The clk and regulator frameworks expect clk/regulator consumer-devices +to have info about the consumed clks/regulators described in the device's +fw_node. + +To work around cases where this info is not present in the firmware tables, +which is often the case on x86/ACPI devices, both frameworks allow the +provider-driver to attach info about consumers to the clks/regulators +when registering these. + +This causes problems with the probe ordering wrt drivers for consumers +of these clks/regulators. Since the lookups are only registered when the +provider-driver binds, trying to get these clks/regulators before then +results in a -ENOENT error for clks and a dummy regulator for regulators. + +One case where we hit this issue is camera sensors such as e.g. the OV8865 +sensor found on the Microsoft Surface Go. The sensor uses clks, regulators +and GPIOs provided by a TPS68470 PMIC which is described in an INT3472 +ACPI device. There is special platform code handling this and setting +platform_data with the necessary consumer info on the MFD cells +instantiated for the PMIC under: drivers/platform/x86/intel/int3472. + +For this to work properly the ov8865 driver must not bind to the I2C-client +for the OV8865 sensor until after the TPS68470 PMIC gpio, regulator and +clk MFD cells have all been fully setup. + +The OV8865 on the Microsoft Surface Go is just one example, all X86 +devices using the Intel IPU3 camera block found on recent Intel SoCs +have similar issues where there is an INT3472 HID ACPI-device, which +describes the clks and regulators, and the driver for this INT3472 device +must be fully initialized before the sensor driver (any sensor driver) +binds for things to work properly. + +On these devices the ACPI nodes describing the sensors all have a _DEP +dependency on the matching INT3472 ACPI device (there is one per sensor). + +This allows solving the probe-ordering problem by delaying the enumeration +(instantiation of the I2C-client in the ov8865 example) of ACPI-devices +which have a _DEP dependency on an INT3472 device. + +The new acpi_dev_ready_for_enumeration() helper used for this is also +exported because for devices, which have the enumeration_by_parent flag +set, the parent-driver will do its own scan of child ACPI devices and +it will try to enumerate those during its probe(). Code doing this such +as e.g. the i2c-core-acpi.c code must call this new helper to ensure +that it too delays the enumeration until all the _DEP dependencies are +met on devices which have the new honor_deps flag set. + +Acked-by: Rafael J. Wysocki +Reviewed-by: Andy Shevchenko +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20211203102857.44539-2-hdegoede@redhat.com +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/scan.c | 37 +++++++++++++++++++++++++++++++++---- + include/acpi/acpi_bus.h | 5 ++++- + 2 files changed, 37 insertions(+), 5 deletions(-) + +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -797,6 +797,12 @@ static const char * const acpi_ignore_de + NULL + }; + ++/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */ ++static const char * const acpi_honor_dep_ids[] = { ++ "INT3472", /* Camera sensor PMIC / clk and regulator info */ ++ NULL ++}; ++ + static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) + { + struct acpi_device *device = NULL; +@@ -1762,8 +1768,12 @@ static void acpi_scan_dep_init(struct ac + struct acpi_dep_data *dep; + + list_for_each_entry(dep, &acpi_dep_list, node) { +- if (dep->consumer == adev->handle) ++ if (dep->consumer == adev->handle) { ++ if (dep->honor_dep) ++ adev->flags.honor_deps = 1; ++ + adev->dep_unmet++; ++ } + } + } + +@@ -1967,7 +1977,7 @@ static u32 acpi_scan_check_dep(acpi_hand + for (count = 0, i = 0; i < dep_devices.count; i++) { + struct acpi_device_info *info; + struct acpi_dep_data *dep; +- bool skip; ++ bool skip, honor_dep; + + status = acpi_get_object_info(dep_devices.handles[i], &info); + if (ACPI_FAILURE(status)) { +@@ -1976,6 +1986,7 @@ static u32 acpi_scan_check_dep(acpi_hand + } + + skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids); ++ honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids); + kfree(info); + + if (skip) +@@ -1989,6 +2000,7 @@ static u32 acpi_scan_check_dep(acpi_hand + + dep->supplier = dep_devices.handles[i]; + dep->consumer = handle; ++ dep->honor_dep = honor_dep; + + mutex_lock(&acpi_dep_list_lock); + list_add_tail(&dep->node , &acpi_dep_list); +@@ -2155,8 +2167,8 @@ static void acpi_bus_attach(struct acpi_ + register_dock_dependent_device(device, ejd); + + acpi_bus_get_status(device); +- /* Skip devices that are not present. */ +- if (!acpi_device_is_present(device)) { ++ /* Skip devices that are not ready for enumeration (e.g. not present) */ ++ if (!acpi_dev_ready_for_enumeration(device)) { + device->flags.initialized = false; + acpi_device_clear_enumerated(device); + device->flags.power_manageable = 0; +@@ -2319,6 +2331,23 @@ void acpi_dev_clear_dependencies(struct + EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies); + + /** ++ * acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration ++ * @device: Pointer to the &struct acpi_device to check ++ * ++ * Check if the device is present and has no unmet dependencies. ++ * ++ * Return true if the device is ready for enumeratino. Otherwise, return false. ++ */ ++bool acpi_dev_ready_for_enumeration(const struct acpi_device *device) ++{ ++ if (device->flags.honor_deps && device->dep_unmet) ++ return false; ++ ++ return acpi_device_is_present(device); ++} ++EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration); ++ ++/** + * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier + * @supplier: Pointer to the dependee device + * +--- a/include/acpi/acpi_bus.h ++++ b/include/acpi/acpi_bus.h +@@ -202,7 +202,8 @@ struct acpi_device_flags { + u32 coherent_dma:1; + u32 cca_seen:1; + u32 enumeration_by_parent:1; +- u32 reserved:19; ++ u32 honor_deps:1; ++ u32 reserved:18; + }; + + /* File System */ +@@ -285,6 +286,7 @@ struct acpi_dep_data { + struct list_head node; + acpi_handle supplier; + acpi_handle consumer; ++ bool honor_dep; + }; + + /* Performance Management */ +@@ -693,6 +695,7 @@ static inline bool acpi_device_can_power + bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2); + + void acpi_dev_clear_dependencies(struct acpi_device *supplier); ++bool acpi_dev_ready_for_enumeration(const struct acpi_device *device); + struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier); + struct acpi_device * + acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv); diff --git a/patches.suse/ACPI-pfr_telemetry-Fix-info-leak-in-pfrt_log_ioctl.patch b/patches.suse/ACPI-pfr_telemetry-Fix-info-leak-in-pfrt_log_ioctl.patch new file mode 100644 index 0000000..74c2a6b --- /dev/null +++ b/patches.suse/ACPI-pfr_telemetry-Fix-info-leak-in-pfrt_log_ioctl.patch @@ -0,0 +1,29 @@ +From: Dan Carpenter +Date: Fri, 7 Jan 2022 10:34:07 +0300 +Subject: ACPI: pfr_telemetry: Fix info leak in pfrt_log_ioctl() +Patch-mainline: v5.17-rc1 +Git-commit: 7bf2e4d5ca1c94a9b0f730498b3d01768a72dcbd +References: jsc#PED-1408 + +The "data_info" struct is copied to the user. It has a 4 byte struct +hole after the last struct member so we need to memset that to avoid +copying uninitialized stack data to the user. + +Fixes: b0013e037a8b ("ACPI: Introduce Platform Firmware Runtime Telemetry driver") +Signed-off-by: Dan Carpenter +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/pfr_telemetry.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/acpi/pfr_telemetry.c ++++ b/drivers/acpi/pfr_telemetry.c +@@ -83,6 +83,7 @@ static int get_pfrt_log_data_info(struct + union acpi_object *out_obj, in_obj, in_buf; + int ret = -EBUSY; + ++ memset(data_info, 0, sizeof(*data_info)); + memset(&in_obj, 0, sizeof(in_obj)); + memset(&in_buf, 0, sizeof(in_buf)); + in_obj.type = ACPI_TYPE_PACKAGE; diff --git a/patches.suse/ACPI-pfr_update-Fix-return-value-check-in-pfru_write.patch b/patches.suse/ACPI-pfr_update-Fix-return-value-check-in-pfru_write.patch new file mode 100644 index 0000000..22c0342 --- /dev/null +++ b/patches.suse/ACPI-pfr_update-Fix-return-value-check-in-pfru_write.patch @@ -0,0 +1,34 @@ +From: Yang Yingliang +Date: Thu, 6 Jan 2022 15:54:48 +0800 +Subject: ACPI: pfr_update: Fix return value check in pfru_write() +Patch-mainline: v5.17-rc1 +Git-commit: 31834aaa4e2a26d8d1f6b36703bb35cfdb8fc98c +References: jsc#PED-1408 + +In case of error, memremap() returns NULL pointer not +ERR_PTR(). The IS_ERR() test in the return value check +should be replaced with NULL test. + +Fixes: 0db89fa243e5 ("ACPI: Introduce Platform Firmware Runtime Update device driver") +Reported-by: Hulk Robot +Signed-off-by: Yang Yingliang +Acked-by: Chen Yu +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/pfr_update.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/acpi/pfr_update.c ++++ b/drivers/acpi/pfr_update.c +@@ -460,8 +460,8 @@ static ssize_t pfru_write(struct file *f + /* map the communication buffer */ + phy_addr = (phys_addr_t)((buf_info.addr_hi << 32) | buf_info.addr_lo); + buf_ptr = memremap(phy_addr, buf_info.buf_size, MEMREMAP_WB); +- if (IS_ERR(buf_ptr)) +- return PTR_ERR(buf_ptr); ++ if (!buf_ptr) ++ return -ENOMEM; + + if (!copy_from_iter_full(buf_ptr, len, &iter)) { + ret = -EINVAL; diff --git a/patches.suse/ACPI-processor-Replace-kernel.h-with-the-necessary-i.patch b/patches.suse/ACPI-processor-Replace-kernel.h-with-the-necessary-i.patch new file mode 100644 index 0000000..866aec1 --- /dev/null +++ b/patches.suse/ACPI-processor-Replace-kernel.h-with-the-necessary-i.patch @@ -0,0 +1,50 @@ +From: Andy Shevchenko +Date: Wed, 10 Nov 2021 13:16:40 +0200 +Subject: ACPI: processor: Replace kernel.h with the necessary inclusions +Patch-mainline: v5.17-rc1 +Git-commit: 6fd13452c1a2e6dfe5b9a4c84c1144383cc55472 +References: jsc#PED-1408 + +When kernel.h is used in the headers it adds a lot into dependency hell, +especially when there are circular dependencies are involved. + +Replace kernel.h inclusion with the list of what is really being used. + +Signed-off-by: Andy Shevchenko +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/acpi/acpi_numa.h | 1 - + include/acpi/processor.h | 7 ++++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- a/include/acpi/acpi_numa.h ++++ b/include/acpi/acpi_numa.h +@@ -3,7 +3,6 @@ + #define __ACPI_NUMA_H + + #ifdef CONFIG_ACPI_NUMA +-#include + #include + + /* Proximity bitmap length */ +--- a/include/acpi/processor.h ++++ b/include/acpi/processor.h +@@ -2,11 +2,16 @@ + #ifndef __ACPI_PROCESSOR_H + #define __ACPI_PROCESSOR_H + +-#include + #include + #include + #include ++#include ++#include ++#include + #include ++#include ++#include ++ + #include + + #define ACPI_PROCESSOR_CLASS "processor" diff --git a/patches.suse/ACPI-processor-idle-Only-flush-cache-on-entering-C3.patch b/patches.suse/ACPI-processor-idle-Only-flush-cache-on-entering-C3.patch new file mode 100644 index 0000000..7a647d7 --- /dev/null +++ b/patches.suse/ACPI-processor-idle-Only-flush-cache-on-entering-C3.patch @@ -0,0 +1,32 @@ +From: "Kirill A. Shutemov" +Date: Mon, 6 Dec 2021 15:29:51 +0300 +Subject: ACPI: processor: idle: Only flush cache on entering C3 +Patch-mainline: v5.17-rc1 +Git-commit: 87ebbb8c612b1214f227ebb8f25442c6d163e802 +References: jsc#PED-1408 + +According to ACPI 6.4, Section 8.2, CPU cache flushing required on +entering the C3 power state. + +Avoid flushing the cache on entering other C-states. + +Signed-off-by: Kirill A. Shutemov +[ rjw: Changelog edits ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/processor_idle.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -565,7 +565,8 @@ static int acpi_idle_play_dead(struct cp + { + struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); + +- ACPI_FLUSH_CPU_CACHE(); ++ if (cx->type == ACPI_STATE_C3) ++ ACPI_FLUSH_CPU_CACHE(); + + while (1) { + diff --git a/patches.suse/ACPI-processor-idle-Use-swap-instead-of-open-coding-.patch b/patches.suse/ACPI-processor-idle-Use-swap-instead-of-open-coding-.patch new file mode 100644 index 0000000..48d3dcc --- /dev/null +++ b/patches.suse/ACPI-processor-idle-Use-swap-instead-of-open-coding-.patch @@ -0,0 +1,48 @@ +From: Guo Zhengkui +Date: Tue, 9 Nov 2021 15:50:51 +0800 +Subject: ACPI: processor idle: Use swap() instead of open coding it +Patch-mainline: v5.17-rc1 +Git-commit: 0e6078c3c6737df7d0bd0c890fbadf24a27fffbb +References: jsc#PED-1408 + +Address the following coccicheck warning: + +./drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c:914:40-41: +WARNING opportunity for swap(). + +by using swap() for the swapping of variable values and drop +the tmp variable that is not needed any more. + +Signed-off-by: Guo Zhengkui +[ rjw: Subject and changelog rewrite ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/processor_idle.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + + /* +@@ -400,13 +401,10 @@ static int acpi_cst_latency_cmp(const vo + static void acpi_cst_latency_swap(void *a, void *b, int n) + { + struct acpi_processor_cx *x = a, *y = b; +- u32 tmp; + + if (!(x->valid && y->valid)) + return; +- tmp = x->latency; +- x->latency = y->latency; +- y->latency = tmp; ++ swap(x->latency, y->latency); + } + + static int acpi_processor_power_verify(struct acpi_processor *pr) diff --git a/patches.suse/ACPI-processor-thermal-avoid-cpufreq_get_policy.patch b/patches.suse/ACPI-processor-thermal-avoid-cpufreq_get_policy.patch new file mode 100644 index 0000000..1656627 --- /dev/null +++ b/patches.suse/ACPI-processor-thermal-avoid-cpufreq_get_policy.patch @@ -0,0 +1,45 @@ +From: Manfred Spraul +Date: Wed, 22 Dec 2021 15:09:31 +0100 +Subject: ACPI: processor: thermal: avoid cpufreq_get_policy() +Patch-mainline: v5.17-rc1 +Git-commit: 8120832d8f82aa7316c578fbccf11e385a5b3601 +References: jsc#PED-1408 + +cpu_has_cpufreq() stores a 'struct cpufreq_policy' on the stack. +Unfortunately, with debugging options enabled, the structure can be +larger than 1024 bytes, which causes a compiler warning/error. + +(actually observed: 1184 bytes). + +Therefore: Switch to cpufreq_cpu_get(). + +Signed-off-by: Manfred Spraul +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/processor_thermal.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/acpi/processor_thermal.c ++++ b/drivers/acpi/processor_thermal.c +@@ -53,10 +53,17 @@ static int phys_package_first_cpu(int cp + + static int cpu_has_cpufreq(unsigned int cpu) + { +- struct cpufreq_policy policy; +- if (!acpi_processor_cpufreq_init || cpufreq_get_policy(&policy, cpu)) ++ struct cpufreq_policy *policy; ++ ++ if (!acpi_processor_cpufreq_init) + return 0; +- return 1; ++ ++ policy = cpufreq_cpu_get(cpu); ++ if (policy) { ++ cpufreq_cpu_put(policy); ++ return 1; ++ } ++ return 0; + } + + static int cpufreq_get_max_state(unsigned int cpu) diff --git a/patches.suse/ACPI-properties-Consistently-return-ENOENT-if-there-.patch b/patches.suse/ACPI-properties-Consistently-return-ENOENT-if-there-.patch index 78ebbb9..e5e005b 100644 --- a/patches.suse/ACPI-properties-Consistently-return-ENOENT-if-there-.patch +++ b/patches.suse/ACPI-properties-Consistently-return-ENOENT-if-there-.patch @@ -32,5 +32,5 @@ Acked-by: Takashi Iwai - return -EINVAL; + return -ENOENT; - ret = acpi_bus_get_device(obj->reference.handle, &device); - if (ret) + device = acpi_fetch_acpi_dev(obj->reference.handle); + if (!device) diff --git a/patches.suse/ACPI-require-CRC32-to-build.patch b/patches.suse/ACPI-require-CRC32-to-build.patch new file mode 100644 index 0000000..20d5235 --- /dev/null +++ b/patches.suse/ACPI-require-CRC32-to-build.patch @@ -0,0 +1,36 @@ +From: Randy Dunlap +Date: Sun, 30 Jan 2022 14:38:18 -0800 +Subject: ACPI: require CRC32 to build +Patch-mainline: v5.17-rc3 +Git-commit: 04662bac0067e2fd7f243d6abaa4d779bce14114 +References: jsc#PED-1408 + +ACPI core now requires crc32() but the kernel build can fail when +CRC32 is not set/enabled, so select it in the ACPI Kconfig entry. + +Fixes this build error: + +ia64-linux-ld: drivers/acpi/scan.o: in function `acpi_store_pld_crc': +include/acpi/platform/aclinuxex.h:62: undefined reference to `crc32_le' + +Fixes: 882c982dada4 ("acpi: Store CRC-32 hash of the _PLD in struct acpi_device") +Signed-off-by: Randy Dunlap +Reported-by: Guenter Roeck +Reviewed-by: Guenter Roeck +Tested-by: Guenter Roeck +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/acpi/Kconfig ++++ b/drivers/acpi/Kconfig +@@ -11,6 +11,7 @@ menuconfig ACPI + depends on ARCH_SUPPORTS_ACPI + select PNP + select NLS ++ select CRC32 + default y if X86 + help + Advanced Configuration and Power Interface (ACPI) support for diff --git a/patches.suse/ACPI-scan-Change-acpi_scan_init-return-value-type-to.patch b/patches.suse/ACPI-scan-Change-acpi_scan_init-return-value-type-to.patch new file mode 100644 index 0000000..79dc604 --- /dev/null +++ b/patches.suse/ACPI-scan-Change-acpi_scan_init-return-value-type-to.patch @@ -0,0 +1,78 @@ +From: "Rafael J. Wysocki" +Date: Tue, 11 Jan 2022 17:50:22 +0100 +Subject: ACPI: scan: Change acpi_scan_init() return value type to void +Patch-mainline: v5.17-rc1 +Git-commit: b6c55b162bcee62c43c18e59f38a4590be543032 +References: jsc#PED-1408 + +The only caller of acpi_scan_init(), acpi_init(), doesn't check its +return value, so turn it into a void function. + +This avoids complaints from the Smatch static checker that the +function should return a negative error code when it fails, which +is not really a problem in this particular case. + +No intentional functional impact. + +Link: https://lore.kernel.org/linux-acpi/20220106082317.GA9123@kili/ +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Mika Westerberg +Reviewed-by: Hans de Goede +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/internal.h | 2 +- + drivers/acpi/scan.c | 10 +++------- + 2 files changed, 4 insertions(+), 8 deletions(-) + +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -14,7 +14,7 @@ + int early_acpi_osi_init(void); + int acpi_osi_init(void); + acpi_status acpi_os_initialize1(void); +-int acpi_scan_init(void); ++void acpi_scan_init(void); + #ifdef CONFIG_PCI + void acpi_pci_root_init(void); + void acpi_pci_link_init(void); +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -2558,9 +2558,8 @@ static void __init acpi_get_spcr_uart_ad + + static bool acpi_scan_initialized; + +-int __init acpi_scan_init(void) ++void __init acpi_scan_init(void) + { +- int result; + acpi_status status; + struct acpi_table_stao *stao_ptr; + +@@ -2610,8 +2609,7 @@ int __init acpi_scan_init(void) + /* + * Enumerate devices in the ACPI namespace. + */ +- result = acpi_bus_scan(ACPI_ROOT_OBJECT); +- if (result) ++ if (acpi_bus_scan(ACPI_ROOT_OBJECT)) + goto out; + + acpi_root = acpi_fetch_acpi_dev(ACPI_ROOT_OBJECT); +@@ -2620,8 +2618,7 @@ int __init acpi_scan_init(void) + + /* Fixed feature devices do not exist on HW-reduced platform */ + if (!acpi_gbl_reduced_hardware) { +- result = acpi_bus_scan_fixed(); +- if (result) { ++ if (acpi_bus_scan_fixed()) { + acpi_detach_data(acpi_root->handle, + acpi_scan_drop_device); + acpi_device_del(acpi_root); +@@ -2636,7 +2633,6 @@ int __init acpi_scan_init(void) + + out: + mutex_unlock(&acpi_scan_lock); +- return result; + } + + static struct acpi_probe_entry *ape; diff --git a/patches.suse/ACPI-scan-Do-not-add-device-IDs-from-_CID-if-_HID-is.patch b/patches.suse/ACPI-scan-Do-not-add-device-IDs-from-_CID-if-_HID-is.patch new file mode 100644 index 0000000..897ea64 --- /dev/null +++ b/patches.suse/ACPI-scan-Do-not-add-device-IDs-from-_CID-if-_HID-is.patch @@ -0,0 +1,39 @@ +From: "Rafael J. Wysocki" +Date: Tue, 26 Oct 2021 20:57:31 +0200 +Subject: ACPI: scan: Do not add device IDs from _CID if _HID is not valid +Patch-mainline: v5.17-rc1 +Git-commit: e38f9ff63e6d403f8e52302d223e3c5c110872ee +References: jsc#PED-1408 + +Section 6.1.2 of ACPI 6.4 explicitly requires _HID to be present for +_CID to be defined, so don't add device IDs from _CID to the device +IDs list of a device if _HID is not valid. + +Link: https://uefi.org/specs/ACPI/6.4/06_Device_Configuration/Device_Configuration.html#cid-compatible-id +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Andy Shevchenko +Reviewed-by: Hans de Goede +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/scan.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -1346,11 +1346,11 @@ static void acpi_set_pnp_ids(acpi_handle + if (info->valid & ACPI_VALID_HID) { + acpi_add_id(pnp, info->hardware_id.string); + pnp->type.platform_id = 1; +- } +- if (info->valid & ACPI_VALID_CID) { +- cid_list = &info->compatible_id_list; +- for (i = 0; i < cid_list->count; i++) +- acpi_add_id(pnp, cid_list->ids[i].string); ++ if (info->valid & ACPI_VALID_CID) { ++ cid_list = &info->compatible_id_list; ++ for (i = 0; i < cid_list->count; i++) ++ acpi_add_id(pnp, cid_list->ids[i].string); ++ } + } + if (info->valid & ACPI_VALID_ADR) { + pnp->bus_address = info->address; diff --git a/patches.suse/ACPI-scan-Rename-label-in-acpi_scan_init.patch b/patches.suse/ACPI-scan-Rename-label-in-acpi_scan_init.patch new file mode 100644 index 0000000..fc878ee --- /dev/null +++ b/patches.suse/ACPI-scan-Rename-label-in-acpi_scan_init.patch @@ -0,0 +1,45 @@ +From: "Rafael J. Wysocki" +Date: Tue, 11 Jan 2022 17:53:29 +0100 +Subject: ACPI: scan: Rename label in acpi_scan_init() +Patch-mainline: v5.17-rc1 +Git-commit: c96f195deeefecd8ef95c5aa508671dd246bf119 +References: jsc#PED-1408 + +Rename the "out" label in acpi_scan_init() to "unlock", which is +a better match for its purpose, and fix up its alignment. + +No functional impact. + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Mika Westerberg +Reviewed-by: Hans de Goede +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/scan.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -2601,11 +2601,11 @@ void __init acpi_scan_init(void) + * Enumerate devices in the ACPI namespace. + */ + if (acpi_bus_scan(ACPI_ROOT_OBJECT)) +- goto out; ++ goto unlock; + + acpi_root = acpi_fetch_acpi_dev(ACPI_ROOT_OBJECT); + if (!acpi_root) +- goto out; ++ goto unlock; + + /* Fixed feature devices do not exist on HW-reduced platform */ + if (!acpi_gbl_reduced_hardware) +@@ -2615,7 +2615,7 @@ void __init acpi_scan_init(void) + + acpi_scan_initialized = true; + +- out: ++unlock: + mutex_unlock(&acpi_scan_lock); + } + diff --git a/patches.suse/ACPI-scan-Simplify-initialization-of-power-and-sleep.patch b/patches.suse/ACPI-scan-Simplify-initialization-of-power-and-sleep.patch new file mode 100644 index 0000000..0e2eee6 --- /dev/null +++ b/patches.suse/ACPI-scan-Simplify-initialization-of-power-and-sleep.patch @@ -0,0 +1,110 @@ +From: "Rafael J. Wysocki" +Date: Tue, 11 Jan 2022 17:52:00 +0100 +Subject: ACPI: scan: Simplify initialization of power and sleep buttons +Patch-mainline: v5.17-rc1 +Git-commit: 681e7187aef46f8d4e0fd0ddd2f888e3e5533cb2 +References: jsc#PED-1408 + +It should be perfectly fine to use ACPI if the "fixed" power or sleep +buttons cannot be initialized. Moreover, running acpi_bus_scan() +successfully on ACPI_ROOT_OBJECT generally causes many devices to +be enumerated and probed, possibly including the entire PCI bus, so +unregistering acpi_root if the registration of the "fixed" buttons +fails is rather unhelpful. + +For this reason, do not fail acpi_scan_init() when +acpi_bus_scan_fixed() fails and turn the latter into a void function. + +While at it, drop the outdated and misleading comment from +acpi_bus_scan_fixed(). + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Mika Westerberg +Reviewed-by: Hans de Goede +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/scan.c | 58 ++++++++++++++++++---------------------------------- + 1 file changed, 21 insertions(+), 37 deletions(-) + +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -2502,42 +2502,33 @@ int acpi_bus_register_early_device(int t + } + EXPORT_SYMBOL_GPL(acpi_bus_register_early_device); + +-static int acpi_bus_scan_fixed(void) ++static void acpi_bus_scan_fixed(void) + { +- int result = 0; +- +- /* +- * Enumerate all fixed-feature devices. +- */ + if (!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { +- struct acpi_device *device = NULL; ++ struct acpi_device *adev = NULL; + +- result = acpi_add_single_object(&device, NULL, +- ACPI_BUS_TYPE_POWER_BUTTON, false); +- if (result) +- return result; +- +- device->flags.match_driver = true; +- result = device_attach(&device->dev); +- if (result < 0) +- return result; +- +- device_init_wakeup(&device->dev, true); ++ acpi_add_single_object(&adev, NULL, ACPI_BUS_TYPE_POWER_BUTTON, ++ false); ++ if (adev) { ++ adev->flags.match_driver = true; ++ if (device_attach(&adev->dev) >= 0) ++ device_init_wakeup(&adev->dev, true); ++ else ++ dev_dbg(&adev->dev, "No driver\n"); ++ } + } + + if (!(acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON)) { +- struct acpi_device *device = NULL; ++ struct acpi_device *adev = NULL; + +- result = acpi_add_single_object(&device, NULL, +- ACPI_BUS_TYPE_SLEEP_BUTTON, false); +- if (result) +- return result; +- +- device->flags.match_driver = true; +- result = device_attach(&device->dev); ++ acpi_add_single_object(&adev, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, ++ false); ++ if (adev) { ++ adev->flags.match_driver = true; ++ if (device_attach(&adev->dev) < 0) ++ dev_dbg(&adev->dev, "No driver\n"); ++ } + } +- +- return result < 0 ? result : 0; + } + + static void __init acpi_get_spcr_uart_addr(void) +@@ -2617,15 +2608,8 @@ void __init acpi_scan_init(void) + goto out; + + /* Fixed feature devices do not exist on HW-reduced platform */ +- if (!acpi_gbl_reduced_hardware) { +- if (acpi_bus_scan_fixed()) { +- acpi_detach_data(acpi_root->handle, +- acpi_scan_drop_device); +- acpi_device_del(acpi_root); +- acpi_bus_put_acpi_device(acpi_root); +- goto out; +- } +- } ++ if (!acpi_gbl_reduced_hardware) ++ acpi_bus_scan_fixed(); + + acpi_turn_off_unused_power_resources(); + diff --git a/patches.suse/ACPI-sysfs-use-default_groups-in-kobj_type.patch b/patches.suse/ACPI-sysfs-use-default_groups-in-kobj_type.patch new file mode 100644 index 0000000..ef513ef --- /dev/null +++ b/patches.suse/ACPI-sysfs-use-default_groups-in-kobj_type.patch @@ -0,0 +1,72 @@ +From: Greg Kroah-Hartman +Date: Tue, 28 Dec 2021 14:14:23 +0100 +Subject: ACPI: sysfs: use default_groups in kobj_type +Patch-mainline: v5.17-rc1 +Git-commit: 17f18417d6da07bbaafce84f80fa25d860b6e6d1 +References: jsc#PED-1408 + +There are currently 2 ways to create a set of sysfs files for a +kobj_type, through the default_attrs field, and the default_groups +field. Move the ACPI sysfs code to use default_groups field which has +been the preferred way since aa30f47cf666 ("kobject: Add support for +default attribute groups to kobj_type") so that we can soon get rid of +the obsolete default_attrs field. + +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/cppc_acpi.c | 3 ++- + drivers/acpi/device_sysfs.c | 3 ++- + drivers/acpi/sysfs.c | 3 ++- + 3 files changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -179,10 +179,11 @@ static struct attribute *cppc_attrs[] = + &lowest_freq.attr, + NULL + }; ++ATTRIBUTE_GROUPS(cppc); + + static struct kobj_type cppc_ktype = { + .sysfs_ops = &kobj_sysfs_ops, +- .default_attrs = cppc_attrs, ++ .default_groups = cppc_groups, + }; + + static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit) +--- a/drivers/acpi/device_sysfs.c ++++ b/drivers/acpi/device_sysfs.c +@@ -53,6 +53,7 @@ static struct attribute *acpi_data_node_ + &data_node_path.attr, + NULL + }; ++ATTRIBUTE_GROUPS(acpi_data_node_default); + + #define to_data_node(k) container_of(k, struct acpi_data_node, kobj) + #define to_attr(a) container_of(a, struct acpi_data_node_attr, attr) +@@ -79,7 +80,7 @@ static void acpi_data_node_release(struc + + static struct kobj_type acpi_data_node_ktype = { + .sysfs_ops = &acpi_data_node_sysfs_ops, +- .default_attrs = acpi_data_node_default_attrs, ++ .default_groups = acpi_data_node_default_groups, + .release = acpi_data_node_release, + }; + +--- a/drivers/acpi/sysfs.c ++++ b/drivers/acpi/sysfs.c +@@ -939,10 +939,11 @@ static struct attribute *hotplug_profile + &hotplug_enabled_attr.attr, + NULL + }; ++ATTRIBUTE_GROUPS(hotplug_profile); + + static struct kobj_type acpi_hotplug_profile_ktype = { + .sysfs_ops = &kobj_sysfs_ops, +- .default_attrs = hotplug_profile_attrs, ++ .default_groups = hotplug_profile_groups, + }; + + void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, diff --git a/patches.suse/ACPI-tables-Add-AEST-to-the-list-of-known-table-sign.patch b/patches.suse/ACPI-tables-Add-AEST-to-the-list-of-known-table-sign.patch new file mode 100644 index 0000000..266577d --- /dev/null +++ b/patches.suse/ACPI-tables-Add-AEST-to-the-list-of-known-table-sign.patch @@ -0,0 +1,30 @@ +From: Shuuichirou Ishii +Date: Mon, 29 Nov 2021 15:10:44 +0900 +Subject: ACPI: tables: Add AEST to the list of known table signatures +Patch-mainline: v5.17-rc1 +Git-commit: 7e29a225c7508f858ac1c900675390ec4ef01aed +References: jsc#PED-1408 + +Add AEST to the list of known ACPI table signatures to allow the +kernel to recognize it when upgrading tables via initrd. + +Signed-off-by: Shuuichirou Ishii +Acked-by: Hanjun Guo +[ rjw: New subject and changelog ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/tables.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/acpi/tables.c ++++ b/drivers/acpi/tables.c +@@ -499,7 +499,7 @@ static const char table_sigs[][ACPI_NAME + ACPI_SIG_WDDT, ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, + ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, + ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT, +- ACPI_SIG_NHLT }; ++ ACPI_SIG_NHLT, ACPI_SIG_AEST }; + + #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) + diff --git a/patches.suse/ACPI-tables-Quiet-ACPI-table-not-found-warning.patch b/patches.suse/ACPI-tables-Quiet-ACPI-table-not-found-warning.patch new file mode 100644 index 0000000..c088565 --- /dev/null +++ b/patches.suse/ACPI-tables-Quiet-ACPI-table-not-found-warning.patch @@ -0,0 +1,33 @@ +From: Dan Williams +Date: Tue, 15 Feb 2022 10:54:23 -0800 +Subject: ACPI: tables: Quiet ACPI table not found warning +Patch-mainline: v5.17-rc5 +Git-commit: f98da1d66298882b1d2061051ea14ddc15c58884 +References: jsc#PED-1408 + +Paul reports that the ACPI core complains on every boot about a missing +CEDT table. Unlike the standard NUMA tables (SRAT, MADT, and SLIT) that +are critical to NUMA init, CEDT is only expected on CXL platforms. Given +the notice is not actionable lower its severity to debug. + +Link: https://lore.kernel.org/r/55f5c077-061c-7e53-b02d-53dde1dd654f@molgen.mpg.de +Fixes: fd49f99c1809 ("ACPI: NUMA: Add a node and memblk for each CFMWS not in SRAT") +Reported-by: Paul Menzel +Signed-off-by: Dan Williams +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/tables.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/acpi/tables.c ++++ b/drivers/acpi/tables.c +@@ -399,7 +399,7 @@ int __init_or_acpilib acpi_table_parse_e + + acpi_get_table(id, instance, &table_header); + if (!table_header) { +- pr_warn("%4.4s not present\n", id); ++ pr_debug("%4.4s not present\n", id); + return -ENODEV; + } + diff --git a/patches.suse/ACPI-tools-Introduce-utility-for-firmware-updates-te.patch b/patches.suse/ACPI-tools-Introduce-utility-for-firmware-updates-te.patch new file mode 100644 index 0000000..f2431e5 --- /dev/null +++ b/patches.suse/ACPI-tools-Introduce-utility-for-firmware-updates-te.patch @@ -0,0 +1,671 @@ +From: Chen Yu +Date: Wed, 22 Dec 2021 12:32:34 +0800 +Subject: ACPI: tools: Introduce utility for firmware updates/telemetry +Patch-mainline: v5.17-rc1 +Git-commit: 53e8558837be58c1d44d50ad87247a8c56c95c13 +References: jsc#PED-1408 + +Introduce a user space tool to make use of the interface exposed by +Platform Firmware Runtime Update and Telemetry drivers. + +It can be used for firmware code injection, driver updates and +to retrieve platform firmware telemetry data. + +Tested-by: Hongyu Ning +Signed-off-by: Chen Yu +[ rjw: Subject and changelog edits ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + tools/power/acpi/.gitignore | 1 + tools/power/acpi/Makefile | 16 - + tools/power/acpi/Makefile.rules | 2 + tools/power/acpi/man/pfrut.8 | 137 ++++++++++ + tools/power/acpi/tools/pfrut/Makefile | 23 + + tools/power/acpi/tools/pfrut/pfrut.c | 424 ++++++++++++++++++++++++++++++++++ + 6 files changed, 594 insertions(+), 9 deletions(-) + create mode 100644 tools/power/acpi/man/pfrut.8 + create mode 100644 tools/power/acpi/tools/pfrut/Makefile + create mode 100644 tools/power/acpi/tools/pfrut/pfrut.c + +--- a/tools/power/acpi/.gitignore ++++ b/tools/power/acpi/.gitignore +@@ -2,4 +2,5 @@ + /acpidbg + /acpidump + /ec ++/pfrut + /include/ +--- a/tools/power/acpi/Makefile ++++ b/tools/power/acpi/Makefile +@@ -9,18 +9,18 @@ include ../../scripts/Makefile.include + + .NOTPARALLEL: + +-all: acpidbg acpidump ec +-clean: acpidbg_clean acpidump_clean ec_clean +-install: acpidbg_install acpidump_install ec_install +-uninstall: acpidbg_uninstall acpidump_uninstall ec_uninstall ++all: acpidbg acpidump ec pfrut ++clean: acpidbg_clean acpidump_clean ec_clean pfrut_clean ++install: acpidbg_install acpidump_install ec_install pfrut_install ++uninstall: acpidbg_uninstall acpidump_uninstall ec_uninstall pfrut_uninstall + +-acpidbg acpidump ec: FORCE ++acpidbg acpidump ec pfrut: FORCE + $(call descend,tools/$@,all) +-acpidbg_clean acpidump_clean ec_clean: ++acpidbg_clean acpidump_clean ec_clean pfrut_clean: + $(call descend,tools/$(@:_clean=),clean) +-acpidbg_install acpidump_install ec_install: ++acpidbg_install acpidump_install ec_install pfrut_install: + $(call descend,tools/$(@:_install=),install) +-acpidbg_uninstall acpidump_uninstall ec_uninstall: ++acpidbg_uninstall acpidump_uninstall ec_uninstall pfrut_uninstall: + $(call descend,tools/$(@:_uninstall=),uninstall) + + .PHONY: FORCE +--- a/tools/power/acpi/Makefile.rules ++++ b/tools/power/acpi/Makefile.rules +@@ -9,7 +9,7 @@ objdir := $(OUTPUT)tools/$(TOOL)/ + toolobjs := $(addprefix $(objdir),$(TOOL_OBJS)) + $(OUTPUT)$(TOOL): $(toolobjs) FORCE + $(ECHO) " LD " $(subst $(OUTPUT),,$@) +- $(QUIET) $(LD) $(CFLAGS) $(LDFLAGS) $(toolobjs) -L$(OUTPUT) -o $@ ++ $(QUIET) $(LD) $(CFLAGS) $(toolobjs) $(LDFLAGS) -L$(OUTPUT) -o $@ + $(ECHO) " STRIP " $(subst $(OUTPUT),,$@) + $(QUIET) $(STRIPCMD) $@ + +--- /dev/null ++++ b/tools/power/acpi/man/pfrut.8 +@@ -0,0 +1,137 @@ ++.TH "PFRUT" "8" "October 2021" "pfrut 1.0" "" ++.hy ++.SH Name ++.PP ++pfrut \- Platform Firmware Runtime Update and Telemetry tool ++.SH SYNOPSIS ++.PP ++\f[B]pfrut\f[R] [\f[I]Options\f[R]] ++.SH DESCRIPTION ++.PP ++The PFRUT(Platform Firmware Runtime Update and Telemetry) kernel interface is designed ++to ++.PD 0 ++.P ++.PD ++interact with the platform firmware interface defined in the ++.PD 0 ++.P ++.PD ++Management Mode Firmware Runtime ++Update (https://uefi.org/sites/default/files/resources/Intel_MM_OS_Interface_Spec_Rev100.pdf) ++.PD 0 ++.P ++.PD ++\f[B]pfrut\f[R] is the tool to interact with the kernel interface. ++.PD 0 ++.P ++.PD ++.SH OPTIONS ++.TP ++.B \f[B]\-h\f[R], \f[B]\-\-help\f[R] ++Display helper information. ++.TP ++.B \f[B]\-l\f[R], \f[B]\-\-load\f[R] ++Load the capsule file into the system. ++To be more specific, the capsule file will be copied to the ++communication buffer. ++.TP ++.B \f[B]\-s\f[R], \f[B]\-\-stage\f[R] ++Stage the capsule image from communication buffer into Management Mode ++and perform authentication. ++.TP ++.B \f[B]\-a\f[R], \f[B]\-\-activate\f[R] ++Activate a previous staged capsule image. ++.TP ++.B \f[B]\-u\f[R], \f[B]\-\-update\f[R] ++Perform both stage and activation actions. ++.TP ++.B \f[B]\-q\f[R], \f[B]\-\-query\f[R] ++Query the update capability. ++.TP ++.B \f[B]\-d\f[R], \f[B]\-\-setrev\f[R] ++Set the revision ID of code injection/driver update. ++.TP ++.B \f[B]\-D\f[R], \f[B]\-\-setrevlog\f[R] ++Set the revision ID of telemetry. ++.TP ++.B \f[B]\-G\f[R], \f[B]\-\-getloginfo\f[R] ++Get telemetry log information and print it out. ++.TP ++.B \f[B]\-T\f[R], \f[B]\-\-type\f[R] ++Set the telemetry log data type. ++.TP ++.B \f[B]\-L\f[R], \f[B]\-\-level\f[R] ++Set the telemetry log level. ++.TP ++.B \f[B]\-R\f[R], \f[B]\-\-read\f[R] ++Read all the telemetry data and print it out. ++.SH EXAMPLES ++.PP ++\f[B]pfrut \-G\f[R] ++.PP ++log_level:4 ++.PD 0 ++.P ++.PD ++log_type:0 ++.PD 0 ++.P ++.PD ++log_revid:2 ++.PD 0 ++.P ++.PD ++max_data_size:65536 ++.PD 0 ++.P ++.PD ++chunk1_size:0 ++.PD 0 ++.P ++.PD ++chunk2_size:1401 ++.PD 0 ++.P ++.PD ++rollover_cnt:0 ++.PD 0 ++.P ++.PD ++reset_cnt:4 ++.PP ++\f[B]pfru \-q\f[R] ++.PP ++code injection image type:794bf8b2\-6e7b\-454e\-885f\-3fb9bb185402 ++.PD 0 ++.P ++.PD ++fw_version:0 ++.PD 0 ++.P ++.PD ++code_rt_version:1 ++.PD 0 ++.P ++.PD ++driver update image type:0e5f0b14\-f849\-7945\-ad81\-bc7b6d2bb245 ++.PD 0 ++.P ++.PD ++drv_rt_version:0 ++.PD 0 ++.P ++.PD ++drv_svn:0 ++.PD 0 ++.P ++.PD ++platform id:39214663\-b1a8\-4eaa\-9024\-f2bb53ea4723 ++.PD 0 ++.P ++.PD ++oem id:a36db54f\-ea2a\-e14e\-b7c4\-b5780e51ba3d ++.PP ++\f[B]pfrut \-l yours.cap \-u \-T 1 \-L 4\f[R] ++.SH AUTHORS ++Chen Yu. +--- /dev/null ++++ b/tools/power/acpi/tools/pfrut/Makefile +@@ -0,0 +1,23 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++ ++include ../../Makefile.config ++ ++TOOL = pfrut ++EXTRA_INSTALL = install-man ++EXTRA_UNINSTALL = uninstall-man ++ ++CFLAGS += -Wall -O2 ++CFLAGS += -DPFRUT_HEADER='"../../../../../include/uapi/linux/pfrut.h"' ++LDFLAGS += -luuid ++ ++TOOL_OBJS = \ ++ pfrut.o ++ ++include ../../Makefile.rules ++ ++install-man: $(srctree)/man/pfrut.8 ++ $(ECHO) " INST " pfrut.8 ++ $(QUIET) $(INSTALL_DATA) -D $< $(DESTDIR)$(mandir)/man8/pfrut.8 ++uninstall-man: ++ $(ECHO) " UNINST " pfrut.8 ++ $(QUIET) rm -f $(DESTDIR)$(mandir)/man8/pfrut.8 +--- /dev/null ++++ b/tools/power/acpi/tools/pfrut/pfrut.c +@@ -0,0 +1,424 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Platform Firmware Runtime Update tool to do Management ++ * Mode code injection/driver update and telemetry retrieval. ++ * ++ * This tool uses the interfaces provided by pfr_update and ++ * pfr_telemetry drivers. These interfaces are exposed via ++ * /dev/pfr_update and /dev/pfr_telemetry. Write operation ++ * on the /dev/pfr_update is to load the EFI capsule into ++ * kernel space. Mmap/read operations on /dev/pfr_telemetry ++ * could be used to read the telemetry data to user space. ++ */ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include PFRUT_HEADER ++ ++char *capsule_name; ++int action, query_cap, log_type, log_level, log_read, log_getinfo, ++ revid, log_revid; ++int set_log_level, set_log_type, ++ set_revid, set_log_revid; ++ ++char *progname; ++ ++#define LOG_ERR 0 ++#define LOG_WARN 1 ++#define LOG_INFO 2 ++#define LOG_VERB 4 ++#define LOG_EXEC_IDX 0 ++#define LOG_HISTORY_IDX 1 ++#define REVID_1 1 ++#define REVID_2 2 ++ ++static int valid_log_level(int level) ++{ ++ return level == LOG_ERR || level == LOG_WARN || ++ level == LOG_INFO || level == LOG_VERB; ++} ++ ++static int valid_log_type(int type) ++{ ++ return type == LOG_EXEC_IDX || type == LOG_HISTORY_IDX; ++} ++ ++static inline int valid_log_revid(int id) ++{ ++ return id == REVID_1 || id == REVID_2; ++} ++ ++static void help(void) ++{ ++ fprintf(stderr, ++ "usage: %s [OPTIONS]\n" ++ " code injection:\n" ++ " -l, --load\n" ++ " -s, --stage\n" ++ " -a, --activate\n" ++ " -u, --update [stage and activate]\n" ++ " -q, --query\n" ++ " -d, --revid update\n" ++ " telemetry:\n" ++ " -G, --getloginfo\n" ++ " -T, --type(0:execution, 1:history)\n" ++ " -L, --level(0, 1, 2, 4)\n" ++ " -R, --read\n" ++ " -D, --revid log\n", ++ progname); ++} ++ ++char *option_string = "l:sauqd:GT:L:RD:h"; ++static struct option long_options[] = { ++ {"load", required_argument, 0, 'l'}, ++ {"stage", no_argument, 0, 's'}, ++ {"activate", no_argument, 0, 'a'}, ++ {"update", no_argument, 0, 'u'}, ++ {"query", no_argument, 0, 'q'}, ++ {"getloginfo", no_argument, 0, 'G'}, ++ {"type", required_argument, 0, 'T'}, ++ {"level", required_argument, 0, 'L'}, ++ {"read", no_argument, 0, 'R'}, ++ {"setrev", required_argument, 0, 'd'}, ++ {"setrevlog", required_argument, 0, 'D'}, ++ {"help", no_argument, 0, 'h'}, ++ {} ++}; ++ ++static void parse_options(int argc, char **argv) ++{ ++ int option_index = 0; ++ char *pathname; ++ int opt; ++ ++ pathname = strdup(argv[0]); ++ progname = basename(pathname); ++ ++ while ((opt = getopt_long_only(argc, argv, option_string, ++ long_options, &option_index)) != -1) { ++ switch (opt) { ++ case 'l': ++ capsule_name = optarg; ++ break; ++ case 's': ++ action = 1; ++ break; ++ case 'a': ++ action = 2; ++ break; ++ case 'u': ++ action = 3; ++ break; ++ case 'q': ++ query_cap = 1; ++ break; ++ case 'G': ++ log_getinfo = 1; ++ break; ++ case 'T': ++ log_type = atoi(optarg); ++ set_log_type = 1; ++ break; ++ case 'L': ++ log_level = atoi(optarg); ++ set_log_level = 1; ++ break; ++ case 'R': ++ log_read = 1; ++ break; ++ case 'd': ++ revid = atoi(optarg); ++ set_revid = 1; ++ break; ++ case 'D': ++ log_revid = atoi(optarg); ++ set_log_revid = 1; ++ break; ++ case 'h': ++ help(); ++ exit(0); ++ default: ++ break; ++ } ++ } ++} ++ ++void print_cap(struct pfru_update_cap_info *cap) ++{ ++ char *uuid; ++ ++ uuid = malloc(37); ++ if (!uuid) { ++ perror("Can not allocate uuid buffer\n"); ++ exit(1); ++ } ++ ++ uuid_unparse(cap->code_type, uuid); ++ printf("code injection image type:%s\n", uuid); ++ printf("fw_version:%d\n", cap->fw_version); ++ printf("code_rt_version:%d\n", cap->code_rt_version); ++ ++ uuid_unparse(cap->drv_type, uuid); ++ printf("driver update image type:%s\n", uuid); ++ printf("drv_rt_version:%d\n", cap->drv_rt_version); ++ printf("drv_svn:%d\n", cap->drv_svn); ++ ++ uuid_unparse(cap->platform_id, uuid); ++ printf("platform id:%s\n", uuid); ++ uuid_unparse(cap->oem_id, uuid); ++ printf("oem id:%s\n", uuid); ++ printf("oem information length:%d\n", cap->oem_info_len); ++ ++ free(uuid); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int fd_update, fd_update_log, fd_capsule; ++ struct pfrt_log_data_info data_info; ++ struct pfrt_log_info info; ++ struct pfru_update_cap_info cap; ++ void *addr_map_capsule; ++ struct stat st; ++ char *log_buf; ++ int ret = 0; ++ ++ if (getuid() != 0) { ++ printf("Please run the tool as root - Exiting.\n"); ++ return 1; ++ } ++ ++ parse_options(argc, argv); ++ ++ fd_update = open("/dev/acpi_pfr_update0", O_RDWR); ++ if (fd_update < 0) { ++ printf("PFRU device not supported - Quit...\n"); ++ return 1; ++ } ++ ++ fd_update_log = open("/dev/acpi_pfr_telemetry0", O_RDWR); ++ if (fd_update_log < 0) { ++ printf("PFRT device not supported - Quit...\n"); ++ return 1; ++ } ++ ++ if (query_cap) { ++ ret = ioctl(fd_update, PFRU_IOC_QUERY_CAP, &cap); ++ if (ret) ++ perror("Query Update Capability info failed."); ++ else ++ print_cap(&cap); ++ ++ close(fd_update); ++ close(fd_update_log); ++ ++ return ret; ++ } ++ ++ if (log_getinfo) { ++ ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_DATA_INFO, &data_info); ++ if (ret) { ++ perror("Get telemetry data info failed."); ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_INFO, &info); ++ if (ret) { ++ perror("Get telemetry info failed."); ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ printf("log_level:%d\n", info.log_level); ++ printf("log_type:%d\n", info.log_type); ++ printf("log_revid:%d\n", info.log_revid); ++ printf("max_data_size:%d\n", data_info.max_data_size); ++ printf("chunk1_size:%d\n", data_info.chunk1_size); ++ printf("chunk2_size:%d\n", data_info.chunk2_size); ++ printf("rollover_cnt:%d\n", data_info.rollover_cnt); ++ printf("reset_cnt:%d\n", data_info.reset_cnt); ++ ++ return 0; ++ } ++ ++ info.log_level = -1; ++ info.log_type = -1; ++ info.log_revid = -1; ++ ++ if (set_log_level) { ++ if (!valid_log_level(log_level)) { ++ printf("Invalid log level %d\n", ++ log_level); ++ } else { ++ info.log_level = log_level; ++ } ++ } ++ ++ if (set_log_type) { ++ if (!valid_log_type(log_type)) { ++ printf("Invalid log type %d\n", ++ log_type); ++ } else { ++ info.log_type = log_type; ++ } ++ } ++ ++ if (set_log_revid) { ++ if (!valid_log_revid(log_revid)) { ++ printf("Invalid log revid %d, unchanged.\n", ++ log_revid); ++ } else { ++ info.log_revid = log_revid; ++ } ++ } ++ ++ ret = ioctl(fd_update_log, PFRT_LOG_IOC_SET_INFO, &info); ++ if (ret) { ++ perror("Log information set failed.(log_level, log_type, log_revid)"); ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ if (set_revid) { ++ ret = ioctl(fd_update, PFRU_IOC_SET_REV, &revid); ++ if (ret) { ++ perror("pfru update revid set failed"); ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ printf("pfru update revid set to %d\n", revid); ++ } ++ ++ if (capsule_name) { ++ fd_capsule = open(capsule_name, O_RDONLY); ++ if (fd_capsule < 0) { ++ perror("Can not open capsule file..."); ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ if (fstat(fd_capsule, &st) < 0) { ++ perror("Can not fstat capsule file..."); ++ close(fd_capsule); ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ addr_map_capsule = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, ++ fd_capsule, 0); ++ if (addr_map_capsule == MAP_FAILED) { ++ perror("Failed to mmap capsule file."); ++ close(fd_capsule); ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ ret = write(fd_update, (char *)addr_map_capsule, st.st_size); ++ printf("Load %d bytes of capsule file into the system\n", ++ ret); ++ ++ if (ret == -1) { ++ perror("Failed to load capsule file"); ++ close(fd_capsule); ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ munmap(addr_map_capsule, st.st_size); ++ close(fd_capsule); ++ printf("Load done.\n"); ++ } ++ ++ if (action) { ++ if (action == 1) { ++ ret = ioctl(fd_update, PFRU_IOC_STAGE, NULL); ++ } else if (action == 2) { ++ ret = ioctl(fd_update, PFRU_IOC_ACTIVATE, NULL); ++ } else if (action == 3) { ++ ret = ioctl(fd_update, PFRU_IOC_STAGE_ACTIVATE, NULL); ++ } else { ++ close(fd_update); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ printf("Update finished, return %d\n", ret); ++ } ++ ++ close(fd_update); ++ ++ if (log_read) { ++ void *p_mmap; ++ int max_data_sz; ++ ++ ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_DATA_INFO, &data_info); ++ if (ret) { ++ perror("Get telemetry data info failed."); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ max_data_sz = data_info.max_data_size; ++ if (!max_data_sz) { ++ printf("No telemetry data available.\n"); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ log_buf = malloc(max_data_sz + 1); ++ if (!log_buf) { ++ perror("log_buf allocate failed."); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ p_mmap = mmap(NULL, max_data_sz, PROT_READ, MAP_SHARED, fd_update_log, 0); ++ if (p_mmap == MAP_FAILED) { ++ perror("mmap error."); ++ close(fd_update_log); ++ ++ return 1; ++ } ++ ++ memcpy(log_buf, p_mmap, max_data_sz); ++ log_buf[max_data_sz] = '\0'; ++ printf("%s\n", log_buf); ++ free(log_buf); ++ ++ munmap(p_mmap, max_data_sz); ++ } ++ ++ close(fd_update_log); ++ ++ return 0; ++} diff --git a/patches.suse/ACPI-x86-Add-PWM2-on-the-Xiaomi-Mi-Pad-2-to-the-alwa.patch b/patches.suse/ACPI-x86-Add-PWM2-on-the-Xiaomi-Mi-Pad-2-to-the-alwa.patch new file mode 100644 index 0000000..121de08 --- /dev/null +++ b/patches.suse/ACPI-x86-Add-PWM2-on-the-Xiaomi-Mi-Pad-2-to-the-alwa.patch @@ -0,0 +1,36 @@ +From: Hans de Goede +Date: Mon, 22 Nov 2021 18:05:34 +0100 +Subject: ACPI / x86: Add PWM2 on the Xiaomi Mi Pad 2 to the always_present + list +Patch-mainline: v5.17-rc1 +Git-commit: b72cd8e0fa34d5491232c64b88e3eda35436eb57 +References: jsc#PED-1408 + +The Xiaomi Mi Pad 2 has backlit LEDs behind the capacitive menu, home +and back buttons below the screen which are controlled by the PWM2 +controller of the CHT SoC. This PWM2 controller gets hidden by the +firmware, add it to the always_present_ids table so that we can use +the PWM controller to control the backlighting of the buttons. + +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/x86/utils.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/acpi/x86/utils.c ++++ b/drivers/acpi/x86/utils.c +@@ -72,6 +72,12 @@ static const struct override_status_id o + PRESENT_ENTRY_HID("80860F09", "1", ATOM_SILVERMONT, {}), + PRESENT_ENTRY_HID("80862288", "1", ATOM_AIRMONT, {}), + ++ /* The Xiaomi Mi Pad 2 uses PWM2 for touchkeys backlight control */ ++ PRESENT_ENTRY_HID("80862289", "2", ATOM_AIRMONT, { ++ DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), ++ }), ++ + /* + * The INT0002 device is necessary to clear wakeup interrupt sources + * on Cherry Trail devices, without it we get nobody cared IRQ msgs. diff --git a/patches.suse/ACPI-x86-Add-acpi_quirk_skip_-i2c_client-serdev-_enu.patch b/patches.suse/ACPI-x86-Add-acpi_quirk_skip_-i2c_client-serdev-_enu.patch new file mode 100644 index 0000000..360bb36 --- /dev/null +++ b/patches.suse/ACPI-x86-Add-acpi_quirk_skip_-i2c_client-serdev-_enu.patch @@ -0,0 +1,190 @@ +From: Hans de Goede +Date: Thu, 30 Dec 2021 15:17:20 +0100 +Subject: ACPI / x86: Add acpi_quirk_skip_[i2c_client|serdev]_enumeration() + helpers +Patch-mainline: v5.17-rc1 +Git-commit: 35f9e773bb883a1be87410570f92c8c438e0478b +References: jsc#PED-1408 + +x86 ACPI boards which ship with only Android as their factory image usually +declare a whole bunch of bogus I2C devs in their ACPI tables and sometimes +there are issues with serdev devices on these boards too, e.g. the resource +points to the wrong serdev_controller. + +Instantiating I2C / serdev devs for these bogus devs causes various issues, +e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them. +The Android x86 kernel fork shipped on these devices has some special code +to remove the bogus I2C clients (and serdevs are ignored completely). + +Introduce acpi_quirk_skip_i2c_client_enumeration() and +acpi_quirk_skip_serdev_enumeration() helpers. Which can be used by the I2C/ +serdev code to skip instantiating any I2C or serdev devs on broken boards. + +These 2 helpers are added to drivers/acpi/x86/utils.c so that the DMI table +can be shared between the I2C and serdev code. + +Note these boards typically do actually have I2C and serdev devices, just +different ones then the ones described in their DSDT. The devices which +are actually present are manually instantiated by the +drivers/platform/x86/x86-android-tablets.c kernel module. + +The new helpers are only build if CONFIG_X86_ANDROID_TABLETS is enabled, +otherwise they are empty stubs to not unnecessarily grow the kernel size. + +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/x86/utils.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++ + include/acpi/acpi_bus.h | 16 ++++++ + 2 files changed, 127 insertions(+) + +--- a/drivers/acpi/x86/utils.c ++++ b/drivers/acpi/x86/utils.c +@@ -10,6 +10,7 @@ + + #include + #include ++#include + #include + #include + #include "../internal.h" +@@ -160,3 +161,113 @@ bool force_storage_d3(void) + { + return x86_match_cpu(storage_d3_cpu_ids); + } ++ ++#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) ++/* ++ * x86 ACPI boards which ship with only Android as their factory image usually ++ * declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes ++ * there are issues with serdev devices on these boards too, e.g. the resource ++ * points to the wrong serdev_controller. ++ * ++ * Instantiating I2C / serdev devs for these bogus devs causes various issues, ++ * e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them. ++ * The Android x86 kernel fork shipped on these devices has some special code ++ * to remove the bogus I2C clients (and AFAICT serdevs are ignored completely). ++ * ++ * The acpi_quirk_skip_*_enumeration() functions below are used by the I2C or ++ * serdev code to skip instantiating any I2C or serdev devs on broken boards. ++ * ++ * In case of I2C an exception is made for HIDs on the i2c_acpi_known_good_ids ++ * list. These are known to always be correct (and in case of the audio-codecs ++ * the drivers heavily rely on the codec being enumerated through ACPI). ++ * ++ * Note these boards typically do actually have I2C and serdev devices, ++ * just different ones then the ones described in their DSDT. The devices ++ * which are actually present are manually instantiated by the ++ * drivers/platform/x86/x86-android-tablets.c kernel module. ++ */ ++#define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0) ++#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1) ++ ++static const struct dmi_system_id acpi_skip_serial_bus_enumeration_ids[] = { ++ { ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"), ++ }, ++ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | ++ ACPI_QUIRK_UART1_TTY_UART2_SKIP), ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"), ++ }, ++ .driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS, ++ }, ++ { ++ /* Whitelabel (sold as various brands) TM800A550L */ ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), ++ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), ++ /* Above strings are too generic, also match on BIOS version */ ++ DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"), ++ }, ++ .driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS, ++ }, ++ {} ++}; ++ ++static const struct acpi_device_id i2c_acpi_known_good_ids[] = { ++ { "10EC5640", 0 }, /* RealTek ALC5640 audio codec */ ++ { "INT33F4", 0 }, /* X-Powers AXP288 PMIC */ ++ { "INT33FD", 0 }, /* Intel Crystal Cove PMIC */ ++ { "NPCE69A", 0 }, /* Asus Transformer keyboard dock */ ++ {} ++}; ++ ++bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) ++{ ++ const struct dmi_system_id *dmi_id; ++ long quirks; ++ ++ dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids); ++ if (!dmi_id) ++ return false; ++ ++ quirks = (unsigned long)dmi_id->driver_data; ++ if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS)) ++ return false; ++ ++ return acpi_match_device_ids(adev, i2c_acpi_known_good_ids); ++} ++EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration); ++ ++int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) ++{ ++ struct acpi_device *adev = ACPI_COMPANION(controller_parent); ++ const struct dmi_system_id *dmi_id; ++ long quirks = 0; ++ ++ *skip = false; ++ ++ /* !dev_is_platform() to not match on PNP enumerated debug UARTs */ ++ if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent)) ++ return 0; ++ ++ dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids); ++ if (dmi_id) ++ quirks = (unsigned long)dmi_id->driver_data; ++ ++ if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) { ++ if (!strcmp(adev->pnp.unique_id, "1")) ++ return -ENODEV; /* Create tty cdev instead of serdev */ ++ ++ if (!strcmp(adev->pnp.unique_id, "2")) ++ *skip = true; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration); ++#endif +--- a/include/acpi/acpi_bus.h ++++ b/include/acpi/acpi_bus.h +@@ -624,6 +624,22 @@ static inline bool acpi_device_always_pr + } + #endif + ++#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) ++bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev); ++int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip); ++#else ++static inline bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) ++{ ++ return false; ++} ++static inline int ++acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) ++{ ++ *skip = false; ++ return 0; ++} ++#endif ++ + #ifdef CONFIG_PM + void acpi_pm_wakeup_event(struct device *dev); + acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, diff --git a/patches.suse/ACPI-x86-Introduce-an-acpi_quirk_skip_acpi_ac_and_ba.patch b/patches.suse/ACPI-x86-Introduce-an-acpi_quirk_skip_acpi_ac_and_ba.patch new file mode 100644 index 0000000..6696a51 --- /dev/null +++ b/patches.suse/ACPI-x86-Introduce-an-acpi_quirk_skip_acpi_ac_and_ba.patch @@ -0,0 +1,373 @@ +From: Hans de Goede +Date: Thu, 30 Dec 2021 20:31:19 +0100 +Subject: ACPI / x86: Introduce an acpi_quirk_skip_acpi_ac_and_battery() helper +Patch-mainline: v5.17-rc1 +Git-commit: 57a18322227134e37b693ef8ef216ed7ce7ba7d6 +References: jsc#PED-1408 + +Some x86 ACPI boards have broken AC and battery ACPI devices in their ACPI +tables. This is often tied to these devices using certain PMICs where the +factory OS image seems to be using native charger and fuel-gauge drivers +instead. + +So far both the AC and battery drivers have almost identical checks for +these PMICs including both of them having a DMI based mechanism to force +usage of the ACPI AC and battery drivers on some boards even though one +of these PMICs is present, with the same 2 boards listed in both driver's +DMI tables for this. + +The only difference is that the AC driver checks for 2 PMICs and the +battery driver only for one. This has grown this way because the other +(Whiskey Cove) PMIC is only used on a few boards (3 known boards) and +although some of these do have non working ACPI battery devices, their +_STA method always returns 0, but that really should not be relied on. + +This patch factors out the shared checks into a new +acpi_quirk_skip_acpi_ac_and_battery() helper and moves the AC and +battery drivers over to this new helper. + +Note the DMI table is shared with acpi_quirk_skip_i2c_client_enumeration() +and acpi_quirk_skip_serdev_enumeration(), because boards needing DMI quirks +for either of these typically also have broken AC and battery ACPI devices. + +The ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY quirk is not set yet on boards +already in this DMI table, to avoid introducing any functional changes +in this refactoring patch. + +Besided sharing the code between the AC and battery drivers this +refactoring also moves this quirk handling to under #ifdef CONFIG_X86, +removing this x86 specific code from non x86 ACPI builds. + +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/ac.c | 43 +------------------------- + drivers/acpi/battery.c | 42 +------------------------ + drivers/acpi/x86/utils.c | 77 ++++++++++++++++++++++++++++++++++++++++++++--- + include/acpi/acpi_bus.h | 5 +++ + 4 files changed, 84 insertions(+), 83 deletions(-) + +--- a/drivers/acpi/ac.c ++++ b/drivers/acpi/ac.c +@@ -48,19 +48,12 @@ static const struct acpi_device_id ac_de + }; + MODULE_DEVICE_TABLE(acpi, ac_device_ids); + +-/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */ +-static const struct acpi_ac_bl acpi_ac_blacklist[] = { +- { "INT33F4", -1 }, /* X-Powers AXP288 PMIC */ +- { "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */ +-}; +- + #ifdef CONFIG_PM_SLEEP + static int acpi_ac_resume(struct device *dev); + #endif + static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); + + static int ac_sleep_before_get_state_ms; +-static int ac_check_pmic = 1; + static int ac_only; + + static struct acpi_driver acpi_ac_driver = { +@@ -200,12 +193,6 @@ static int __init thinkpad_e530_quirk(co + return 0; + } + +-static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d) +-{ +- ac_check_pmic = 0; +- return 0; +-} +- + static int __init ac_only_quirk(const struct dmi_system_id *d) + { + ac_only = 1; +@@ -215,13 +202,6 @@ static int __init ac_only_quirk(const st + /* Please keep this list alphabetically sorted */ + static const struct dmi_system_id ac_dmi_table[] __initconst = { + { +- /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */ +- .callback = ac_do_not_check_pmic_quirk, +- .matches = { +- DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), +- }, +- }, +- { + /* Kodlix GK45 returning incorrect state */ + .callback = ac_only_quirk, + .matches = { +@@ -229,15 +209,6 @@ static const struct dmi_system_id ac_dmi + }, + }, + { +- /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ +- .callback = ac_do_not_check_pmic_quirk, +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +- DMI_MATCH(DMI_PRODUCT_NAME, "80XF"), +- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), +- }, +- }, +- { + /* Lenovo Thinkpad e530, see comment in acpi_ac_notify() */ + .callback = thinkpad_e530_quirk, + .matches = { +@@ -341,23 +312,15 @@ static int acpi_ac_remove(struct acpi_de + + static int __init acpi_ac_init(void) + { +- unsigned int i; + int result; + + if (acpi_disabled) + return -ENODEV; + +- dmi_check_system(ac_dmi_table); ++ if (acpi_quirk_skip_acpi_ac_and_battery()) ++ return -ENODEV; + +- if (ac_check_pmic) { +- for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++) +- if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1", +- acpi_ac_blacklist[i].hrv)) { +- pr_info("found native %s PMIC, not loading\n", +- acpi_ac_blacklist[i].hid); +- return -ENODEV; +- } +- } ++ dmi_check_system(ac_dmi_table); + + result = acpi_bus_register_driver(&acpi_ac_driver); + if (result < 0) +--- a/drivers/acpi/battery.c ++++ b/drivers/acpi/battery.c +@@ -52,7 +52,6 @@ static bool battery_driver_registered; + static int battery_bix_broken_package; + static int battery_notification_delay_ms; + static int battery_ac_is_broken; +-static int battery_check_pmic = 1; + static unsigned int cache_time = 1000; + module_param(cache_time, uint, 0644); + MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); +@@ -64,11 +63,6 @@ static const struct acpi_device_id batte + + MODULE_DEVICE_TABLE(acpi, battery_device_ids); + +-/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */ +-static const char * const acpi_battery_blacklist[] = { +- "INT33F4", /* X-Powers AXP288 PMIC */ +-}; +- + enum { + ACPI_BATTERY_ALARM_PRESENT, + ACPI_BATTERY_XINFO_PRESENT, +@@ -1104,13 +1098,6 @@ battery_ac_is_broken_quirk(const struct + return 0; + } + +-static int __init +-battery_do_not_check_pmic_quirk(const struct dmi_system_id *d) +-{ +- battery_check_pmic = 0; +- return 0; +-} +- + static const struct dmi_system_id bat_dmi_table[] __initconst = { + { + /* NEC LZ750/LS */ +@@ -1139,22 +1126,6 @@ static const struct dmi_system_id bat_dm + DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), + }, + }, +- { +- /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */ +- .callback = battery_do_not_check_pmic_quirk, +- .matches = { +- DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), +- }, +- }, +- { +- /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ +- .callback = battery_do_not_check_pmic_quirk, +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +- DMI_MATCH(DMI_PRODUCT_NAME, "80XF"), +- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), +- }, +- }, + {}, + }; + +@@ -1279,19 +1250,12 @@ static struct acpi_driver acpi_battery_d + + static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) + { +- unsigned int i; + int result; + +- dmi_check_system(bat_dmi_table); ++ if (acpi_quirk_skip_acpi_ac_and_battery()) ++ return; + +- if (battery_check_pmic) { +- for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++) +- if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) { +- pr_info("found native %s PMIC, not loading\n", +- acpi_battery_blacklist[i]); +- return; +- } +- } ++ dmi_check_system(bat_dmi_table); + + result = acpi_bus_register_driver(&acpi_battery_driver); + battery_driver_registered = (result == 0); +--- a/drivers/acpi/x86/utils.c ++++ b/drivers/acpi/x86/utils.c +@@ -8,6 +8,8 @@ + * Copyright (C) 2013-2015 Intel Corporation. All rights reserved. + */ + ++#define pr_fmt(fmt) "ACPI: " fmt ++ + #include + #include + #include +@@ -210,7 +212,6 @@ bool force_storage_d3(void) + return x86_match_cpu(storage_d3_cpu_ids); + } + +-#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) + /* + * x86 ACPI boards which ship with only Android as their factory image usually + * declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes +@@ -236,8 +237,36 @@ bool force_storage_d3(void) + */ + #define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0) + #define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1) ++#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2) ++#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3) ++ ++static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { ++ /* ++ * 1. Devices with only the skip / don't-skip AC and battery quirks, ++ * sorted alphabetically. ++ */ ++ { ++ /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */ ++ .matches = { ++ DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), ++ }, ++ .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY ++ }, ++ { ++ /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "80XF"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), ++ }, ++ .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY ++ }, + +-static const struct dmi_system_id acpi_skip_serial_bus_enumeration_ids[] = { ++ /* ++ * 2. Devices which also have the skip i2c/serdev quirks and which ++ * need the x86-android-tablets module to properly work. ++ */ ++#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +@@ -263,9 +292,11 @@ static const struct dmi_system_id acpi_s + }, + .driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS, + }, ++#endif + {} + }; + ++#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) + static const struct acpi_device_id i2c_acpi_known_good_ids[] = { + { "10EC5640", 0 }, /* RealTek ALC5640 audio codec */ + { "INT33F4", 0 }, /* X-Powers AXP288 PMIC */ +@@ -279,7 +310,7 @@ bool acpi_quirk_skip_i2c_client_enumerat + const struct dmi_system_id *dmi_id; + long quirks; + +- dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids); ++ dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); + if (!dmi_id) + return false; + +@@ -303,7 +334,7 @@ int acpi_quirk_skip_serdev_enumeration(s + if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent)) + return 0; + +- dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids); ++ dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); + if (dmi_id) + quirks = (unsigned long)dmi_id->driver_data; + +@@ -319,3 +350,41 @@ int acpi_quirk_skip_serdev_enumeration(s + } + EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration); + #endif ++ ++/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */ ++static const struct { ++ const char *hid; ++ int hrv; ++} acpi_skip_ac_and_battery_pmic_ids[] = { ++ { "INT33F4", -1 }, /* X-Powers AXP288 PMIC */ ++ { "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */ ++}; ++ ++bool acpi_quirk_skip_acpi_ac_and_battery(void) ++{ ++ const struct dmi_system_id *dmi_id; ++ long quirks = 0; ++ int i; ++ ++ dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids); ++ if (dmi_id) ++ quirks = (unsigned long)dmi_id->driver_data; ++ ++ if (quirks & ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY) ++ return true; ++ ++ if (quirks & ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY) ++ return false; ++ ++ for (i = 0; i < ARRAY_SIZE(acpi_skip_ac_and_battery_pmic_ids); i++) { ++ if (acpi_dev_present(acpi_skip_ac_and_battery_pmic_ids[i].hid, "1", ++ acpi_skip_ac_and_battery_pmic_ids[i].hrv)) { ++ pr_info_once("found native %s PMIC, skipping ACPI AC and battery devices\n", ++ acpi_skip_ac_and_battery_pmic_ids[i].hid); ++ return true; ++ } ++ } ++ ++ return false; ++} ++EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery); +--- a/include/acpi/acpi_bus.h ++++ b/include/acpi/acpi_bus.h +@@ -617,12 +617,17 @@ int acpi_disable_wakeup_device_power(str + + #ifdef CONFIG_X86 + bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status); ++bool acpi_quirk_skip_acpi_ac_and_battery(void); + #else + static inline bool acpi_device_override_status(struct acpi_device *adev, + unsigned long long *status) + { + return false; + } ++static inline bool acpi_quirk_skip_acpi_ac_and_battery(void) ++{ ++ return false; ++} + #endif + + #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) diff --git a/patches.suse/ACPI-x86-Skip-AC-and-battery-devices-on-x86-Android-.patch b/patches.suse/ACPI-x86-Skip-AC-and-battery-devices-on-x86-Android-.patch new file mode 100644 index 0000000..72b1f62 --- /dev/null +++ b/patches.suse/ACPI-x86-Skip-AC-and-battery-devices-on-x86-Android-.patch @@ -0,0 +1,51 @@ +From: Hans de Goede +Date: Thu, 30 Dec 2021 20:31:20 +0100 +Subject: ACPI / x86: Skip AC and battery devices on x86 Android tablets with + broken DSDTs +Patch-mainline: v5.17-rc1 +Git-commit: 1b15b69800e2f9320b3d1fc0611c177c70c24424 +References: jsc#PED-1408 + +So far all of the tablets for which the skip i2c-client/serdev enumeration +quirks have been added also all have broken ACPI AC / battery devices +extend the existing quirks for these tablets to also skip the broken +AC / battery devices. + +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/x86/utils.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/acpi/x86/utils.c ++++ b/drivers/acpi/x86/utils.c +@@ -273,14 +273,16 @@ static const struct dmi_system_id acpi_q + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"), + }, + .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | +- ACPI_QUIRK_UART1_TTY_UART2_SKIP), ++ ACPI_QUIRK_UART1_TTY_UART2_SKIP | ++ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"), + }, +- .driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS, ++ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | ++ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + }, + { + /* Whitelabel (sold as various brands) TM800A550L */ +@@ -290,7 +292,8 @@ static const struct dmi_system_id acpi_q + /* Above strings are too generic, also match on BIOS version */ + DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"), + }, +- .driver_data = (void *)ACPI_QUIRK_SKIP_I2C_CLIENTS, ++ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | ++ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + }, + #endif + {} diff --git a/patches.suse/ACPICA-Add-support-for-PCC-Opregion-special-context-.patch b/patches.suse/ACPICA-Add-support-for-PCC-Opregion-special-context-.patch new file mode 100644 index 0000000..49f4189 --- /dev/null +++ b/patches.suse/ACPICA-Add-support-for-PCC-Opregion-special-context-.patch @@ -0,0 +1,62 @@ +From: Sudeep Holla +Date: Wed, 22 Dec 2021 17:32:54 +0100 +Subject: ACPICA: Add support for PCC Opregion special context data +Patch-mainline: v5.17-rc1 +Git-commit: 0acf24ad7e10f547809faefb8069f8f5482eb4d9 +References: jsc#PED-1408 + +ACPICA commit 55526e8a6133cbf5a9cc0fb75a95dbbac6eb98e6 + +PCC Opregion added in ACPIC 6.3 requires special context data similar +to GPIO and Generic Serial Bus as it needs to know the internal PCC +buffer and its length as well as the PCC channel index when the opregion +handler is being executed by the OSPM. + +Lets add support for the special context data needed by PCC Opregion. + +Link: https://github.com/acpica/acpica/commit/55526e8a +Signed-off-by: Sudeep Holla +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpica/evregion.c | 10 ++++++++++ + include/acpi/actypes.h | 8 ++++++++ + 2 files changed, 18 insertions(+) + +--- a/drivers/acpi/acpica/evregion.c ++++ b/drivers/acpi/acpica/evregion.c +@@ -162,6 +162,16 @@ acpi_ev_address_space_dispatch(union acp + return_ACPI_STATUS(AE_NOT_EXIST); + } + ++ if (region_obj->region.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) { ++ struct acpi_pcc_info *ctx = ++ handler_desc->address_space.context; ++ ++ ctx->internal_buffer = ++ field_obj->field.internal_pcc_buffer; ++ ctx->length = region_obj->region.length; ++ ctx->subspace_id = region_obj->region.address; ++ } ++ + /* + * We must exit the interpreter because the region setup will + * potentially execute control methods (for example, the _REG method +--- a/include/acpi/actypes.h ++++ b/include/acpi/actypes.h +@@ -1103,6 +1103,14 @@ struct acpi_connection_info { + u8 access_length; + }; + ++/* Special Context data for PCC Opregion (ACPI 6.3) */ ++ ++struct acpi_pcc_info { ++ u8 subspace_id; ++ u16 length; ++ u8 *internal_buffer; ++}; ++ + typedef + acpi_status (*acpi_adr_space_setup) (acpi_handle region_handle, + u32 function, diff --git a/patches.suse/ACPICA-Avoid-subobject-buffer-overflow-when-validati.patch b/patches.suse/ACPICA-Avoid-subobject-buffer-overflow-when-validati.patch new file mode 100644 index 0000000..bf3c9ae --- /dev/null +++ b/patches.suse/ACPICA-Avoid-subobject-buffer-overflow-when-validati.patch @@ -0,0 +1,42 @@ +From: Jessica Clarke +Date: Wed, 22 Dec 2021 17:24:44 +0100 +Subject: ACPICA: Avoid subobject buffer overflow when validating RSDP + signature +Patch-mainline: v5.17-rc1 +Git-commit: a3e525feaeec436cd9f82f84e345f0d18dc2638f +References: jsc#PED-1408 + +ACPICA commit 6bb72909c1e3d415aee214104a01bc9834b2d4ce + +Since the Signature member is accessed through an struct acpi_table_header, the +pointer to it is only to a 4-char array, and so trying to read past the +4th character, as will be done when it is an RSDP, reads beyond the +bounds of the accessed member. On CHERI, and thus Arm's experimental +Morello prototype architecture, pointers are represented as +capabilities, which are unforgeable bounded pointers, providing +always-on fine-grained spatial memory safety. By default, subobject +bounds enforcement is not enabled, only bounds on allocations, but it is +enabled in the cheri_BSD (a port of free_BSD) kernel as intra-object +overflow attacks are common on operating system kernels, and so this +overflow is detected there and traps. + +Link: https://github.com/acpica/acpica/commit/6bb72909 +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpica/tbprint.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/acpica/tbprint.c ++++ b/drivers/acpi/acpica/tbprint.c +@@ -101,7 +101,8 @@ acpi_tb_print_table_header(acpi_physical + ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X", + header->signature, ACPI_FORMAT_UINT64(address), + header->length)); +- } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { ++ } else if (ACPI_VALIDATE_RSDP_SIG(ACPI_CAST_PTR(struct acpi_table_rsdp, ++ header)->signature)) { + + /* RSDP has no common fields */ + diff --git a/patches.suse/ACPICA-Change-a-return_ACPI_STATUS-AE_BAD_PARAMETER.patch b/patches.suse/ACPICA-Change-a-return_ACPI_STATUS-AE_BAD_PARAMETER.patch new file mode 100644 index 0000000..751830b --- /dev/null +++ b/patches.suse/ACPICA-Change-a-return_ACPI_STATUS-AE_BAD_PARAMETER.patch @@ -0,0 +1,30 @@ +From: Bob Moore +Date: Wed, 22 Dec 2021 17:35:12 +0100 +Subject: ACPICA: Change a return_ACPI_STATUS (AE_BAD_PARAMETER) +Patch-mainline: v5.17-rc1 +Git-commit: 9f52815422a4b81dc9093fae338a9c41a9ff6657 +References: jsc#PED-1408 + +ACPICA commit ff803279dde7a3e068a6a698d8c69503cd159ad7 + +To simply return (AE_BAD_PARAMETER); to fix compilation on MSVC. + +Link: https://github.com/acpica/acpica/commit/ff803279 +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpica/tbdata.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/acpi/acpica/tbdata.c ++++ b/drivers/acpi/acpica/tbdata.c +@@ -249,7 +249,7 @@ acpi_tb_acquire_temp_table(struct acpi_t + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + if (!table) { +- return_ACPI_STATUS(AE_BAD_PARAMETER); ++ return (AE_BAD_PARAMETER); + } + + break; diff --git a/patches.suse/ACPICA-Fix-AEST-Processor-generic-resource-substruct.patch b/patches.suse/ACPICA-Fix-AEST-Processor-generic-resource-substruct.patch new file mode 100644 index 0000000..6b1efbb --- /dev/null +++ b/patches.suse/ACPICA-Fix-AEST-Processor-generic-resource-substruct.patch @@ -0,0 +1,36 @@ +From: Shuuichirou Ishii +Date: Wed, 22 Dec 2021 17:28:34 +0100 +Subject: ACPICA: Fix AEST Processor generic resource substructure data field + byte length +Patch-mainline: v5.17-rc1 +Git-commit: 00395b74d57ff81795ec392627db7e1764c94941 +References: jsc#PED-1408 + +ACPICA commit 13b9327761955f6e1e5dbf748b3112940c0dc539 + +The byte length of the Data field in the AEST Processor generic resource +substructure defined in ACPI for the Armv8 RAS Extensions 1.1 is 4Byte. +However, it is defined as a pointer type, and on a 64-bit machine, +it is interpreted as 8 bytes. Therefore, it is changed from a pointer +type unsigned integer 1 byte to an unsigned integer 4 bytes. + +Link: https://github.com/acpica/acpica/commit/13b93277 +Signed-off-by: Shuuichirou Ishii +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/acpi/actbl2.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/acpi/actbl2.h ++++ b/include/acpi/actbl2.h +@@ -154,7 +154,7 @@ typedef struct acpi_aest_processor_tlb { + /* 2R: Processor Generic Resource Substructure */ + + typedef struct acpi_aest_processor_generic { +- u8 *resource; ++ u32 resource; + + } acpi_aest_processor_generic; + diff --git a/patches.suse/ACPICA-Fixed-a-couple-of-warnings-under-MSVC.patch b/patches.suse/ACPICA-Fixed-a-couple-of-warnings-under-MSVC.patch new file mode 100644 index 0000000..b7f4a5b --- /dev/null +++ b/patches.suse/ACPICA-Fixed-a-couple-of-warnings-under-MSVC.patch @@ -0,0 +1,32 @@ +From: Bob Moore +Date: Wed, 22 Dec 2021 17:35:49 +0100 +Subject: ACPICA: Fixed a couple of warnings under MSVC +Patch-mainline: v5.17-rc1 +Git-commit: b70d6f07ed31f74b5d702a2bda1d592cc6622a02 +References: jsc#PED-1408 + +ACPICA commit 86c919d2bad08491fc91ffa53e9b169092de8622 + +Repaired with casts. + +Link: https://github.com/acpica/acpica/commit/86c919d2 +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpica/evregion.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/acpi/acpica/evregion.c ++++ b/drivers/acpi/acpica/evregion.c +@@ -168,8 +168,8 @@ acpi_ev_address_space_dispatch(union acp + + ctx->internal_buffer = + field_obj->field.internal_pcc_buffer; +- ctx->length = region_obj->region.length; +- ctx->subspace_id = region_obj->region.address; ++ ctx->length = (u16)region_obj->region.length; ++ ctx->subspace_id = (u8)region_obj->region.address; + } + + /* diff --git a/patches.suse/ACPICA-Macros-Remove-ACPI_PHYSADDR_TO_PTR.patch b/patches.suse/ACPICA-Macros-Remove-ACPI_PHYSADDR_TO_PTR.patch new file mode 100644 index 0000000..0ad9618 --- /dev/null +++ b/patches.suse/ACPICA-Macros-Remove-ACPI_PHYSADDR_TO_PTR.patch @@ -0,0 +1,33 @@ +From: Jessica Clarke +Date: Wed, 22 Dec 2021 17:23:28 +0100 +Subject: ACPICA: Macros: Remove ACPI_PHYSADDR_TO_PTR +Patch-mainline: v5.17-rc1 +Git-commit: 339651be3704f336634d90c000a7778b86e1be99 +References: jsc#PED-1408 + +ACPICA commit 52abebd410945ec55afb4dd8b7150e8a39b5c960 + +This macro was only ever used when stuffing pointers into physical +addresses and trying to later reconstruct the pointer, which is +implementation-defined as to whether that can be done. Now that all such +operations are gone, the macro is unused, and should be removed to avoid +such practices being reintroduced. + +Link: https://github.com/acpica/acpica/commit/52abebd4 +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/acpi/actypes.h | 1 - + 1 file changed, 1 deletion(-) + +--- a/include/acpi/actypes.h ++++ b/include/acpi/actypes.h +@@ -509,7 +509,6 @@ typedef u64 acpi_integer; + #define ACPI_TO_POINTER(i) ACPI_CAST_PTR (void, (acpi_size) (i)) + #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) + #define ACPI_OFFSET(d, f) ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) 0) +-#define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) + #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) + + /* Optimizations for 4-character (32-bit) acpi_name manipulation */ diff --git a/patches.suse/ACPICA-Update-version-to-20211217.patch b/patches.suse/ACPICA-Update-version-to-20211217.patch new file mode 100644 index 0000000..5cf31e3 --- /dev/null +++ b/patches.suse/ACPICA-Update-version-to-20211217.patch @@ -0,0 +1,30 @@ +From: Bob Moore +Date: Wed, 22 Dec 2021 17:38:29 +0100 +Subject: ACPICA: Update version to 20211217 +Patch-mainline: v5.17-rc1 +Git-commit: c95545a036705e1a78b40a83701c8d3868898114 +References: jsc#PED-1408 + +ACPICA commit 90088defcb99e122edf41038ae5c901206c86dc9 + +Version 20211217. + +Link: https://github.com/acpica/acpica/commit/90088def +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/acpi/acpixf.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/acpi/acpixf.h ++++ b/include/acpi/acpixf.h +@@ -12,7 +12,7 @@ + + /* Current ACPICA subsystem version in YYYYMMDD format */ + +-#define ACPI_CA_VERSION 0x20210930 ++#define ACPI_CA_VERSION 0x20211217 + + #include + #include diff --git a/patches.suse/ACPICA-Use-original-data_table_region-pointer-for-ac.patch b/patches.suse/ACPICA-Use-original-data_table_region-pointer-for-ac.patch new file mode 100644 index 0000000..51c67c8 --- /dev/null +++ b/patches.suse/ACPICA-Use-original-data_table_region-pointer-for-ac.patch @@ -0,0 +1,209 @@ +From: Jessica Clarke +Date: Wed, 22 Dec 2021 17:21:25 +0100 +Subject: ACPICA: Use original data_table_region pointer for accesses +Patch-mainline: v5.17-rc1 +Git-commit: ca25f92b72d25457653dbf2a81f322235804fb05 +References: jsc#PED-1408 + +ACPICA commit d9eb82bd7515989f0b29d79deeeb758db4d6529c + +Currently the pointer to the table is cast to acpi_physical_address and +later cast back to a pointer to be dereferenced. Whether or not this is +supported is implementation-defined. + +On CHERI, and thus Arm's experimental Morello prototype architecture, +pointers are represented as capabilities, which are unforgeable bounded +pointers, providing always-on fine-grained spatial memory safety. This +means that any pointer cast to a plain integer will lose all its +associated metadata, and when cast back to a pointer it will give a +null-derived pointer (one that has the same metadata as null but an +address equal to the integer) that will trap on any dereference. As a +result, this is an implementation where acpi_physical_address cannot be +used as a hack to store real pointers. + +Thus, add a new field to struct acpi_object_region to store the pointer for +table regions, and propagate it to acpi_ex_data_table_space_handler via the +region context, to use a more portable implementation that supports +CHERI. + +Link: https://github.com/acpica/acpica/commit/d9eb82bd +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpica/acevents.h | 5 +++ + drivers/acpi/acpica/acobject.h | 1 + drivers/acpi/acpica/dsopcode.c | 1 + drivers/acpi/acpica/evhandler.c | 2 - + drivers/acpi/acpica/evrgnini.c | 52 ++++++++++++++++++++++++++++++++++++++++ + drivers/acpi/acpica/excreate.c | 1 + drivers/acpi/acpica/exregion.c | 15 ++++++++--- + include/acpi/actypes.h | 4 +++ + 8 files changed, 76 insertions(+), 5 deletions(-) + +--- a/drivers/acpi/acpica/acevents.h ++++ b/drivers/acpi/acpica/acevents.h +@@ -224,6 +224,11 @@ acpi_ev_pci_bar_region_setup(acpi_handle + void *handler_context, void **region_context); + + acpi_status ++acpi_ev_data_table_region_setup(acpi_handle handle, ++ u32 function, ++ void *handler_context, void **region_context); ++ ++acpi_status + acpi_ev_default_region_setup(acpi_handle handle, + u32 function, + void *handler_context, void **region_context); +--- a/drivers/acpi/acpica/acobject.h ++++ b/drivers/acpi/acpica/acobject.h +@@ -138,6 +138,7 @@ struct acpi_object_region { + union acpi_operand_object *next; + acpi_physical_address address; + u32 length; ++ void *pointer; /* Only for data table regions */ + }; + + struct acpi_object_method { +--- a/drivers/acpi/acpica/dsopcode.c ++++ b/drivers/acpi/acpica/dsopcode.c +@@ -531,6 +531,7 @@ acpi_ds_eval_table_region_operands(struc + + obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); + obj_desc->region.length = table->length; ++ obj_desc->region.pointer = table; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, +--- a/drivers/acpi/acpica/evhandler.c ++++ b/drivers/acpi/acpica/evhandler.c +@@ -386,7 +386,7 @@ acpi_ev_install_space_handler(struct acp + case ACPI_ADR_SPACE_DATA_TABLE: + + handler = acpi_ex_data_table_space_handler; +- setup = NULL; ++ setup = acpi_ev_data_table_region_setup; + break; + + default: +--- a/drivers/acpi/acpica/evrgnini.c ++++ b/drivers/acpi/acpica/evrgnini.c +@@ -408,6 +408,58 @@ acpi_ev_cmos_region_setup(acpi_handle ha + + /******************************************************************************* + * ++ * FUNCTION: acpi_ev_data_table_region_setup ++ * ++ * PARAMETERS: handle - Region we are interested in ++ * function - Start or stop ++ * handler_context - Address space handler context ++ * region_context - Region specific context ++ * ++ * RETURN: Status ++ * ++ * DESCRIPTION: Setup a data_table_region ++ * ++ * MUTEX: Assumes namespace is not locked ++ * ++ ******************************************************************************/ ++ ++acpi_status ++acpi_ev_data_table_region_setup(acpi_handle handle, ++ u32 function, ++ void *handler_context, void **region_context) ++{ ++ union acpi_operand_object *region_desc = ++ (union acpi_operand_object *)handle; ++ struct acpi_data_table_space_context *local_region_context; ++ ++ ACPI_FUNCTION_TRACE(ev_data_table_region_setup); ++ ++ if (function == ACPI_REGION_DEACTIVATE) { ++ if (*region_context) { ++ ACPI_FREE(*region_context); ++ *region_context = NULL; ++ } ++ return_ACPI_STATUS(AE_OK); ++ } ++ ++ /* Create a new context */ ++ ++ local_region_context = ++ ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_data_table_space_context)); ++ if (!(local_region_context)) { ++ return_ACPI_STATUS(AE_NO_MEMORY); ++ } ++ ++ /* Save the data table pointer for use in the handler */ ++ ++ local_region_context->pointer = region_desc->region.pointer; ++ ++ *region_context = local_region_context; ++ return_ACPI_STATUS(AE_OK); ++} ++ ++/******************************************************************************* ++ * + * FUNCTION: acpi_ev_default_region_setup + * + * PARAMETERS: handle - Region we are interested in +--- a/drivers/acpi/acpica/excreate.c ++++ b/drivers/acpi/acpica/excreate.c +@@ -279,6 +279,7 @@ acpi_ex_create_region(u8 * aml_start, + obj_desc->region.space_id = space_id; + obj_desc->region.address = 0; + obj_desc->region.length = 0; ++ obj_desc->region.pointer = NULL; + obj_desc->region.node = node; + obj_desc->region.handler = NULL; + obj_desc->common.flags &= +--- a/drivers/acpi/acpica/exregion.c ++++ b/drivers/acpi/acpica/exregion.c +@@ -509,8 +509,15 @@ acpi_ex_data_table_space_handler(u32 fun + u64 *value, + void *handler_context, void *region_context) + { ++ struct acpi_data_table_space_context *mapping; ++ char *pointer; ++ + ACPI_FUNCTION_TRACE(ex_data_table_space_handler); + ++ mapping = (struct acpi_data_table_space_context *) region_context; ++ pointer = ACPI_CAST_PTR(char, mapping->pointer) + ++ (address - ACPI_PTR_TO_PHYSADDR(mapping->pointer)); ++ + /* + * Perform the memory read or write. The bit_width was already + * validated. +@@ -518,14 +525,14 @@ acpi_ex_data_table_space_handler(u32 fun + switch (function) { + case ACPI_READ: + +- memcpy(ACPI_CAST_PTR(char, value), +- ACPI_PHYSADDR_TO_PTR(address), ACPI_DIV_8(bit_width)); ++ memcpy(ACPI_CAST_PTR(char, value), pointer, ++ ACPI_DIV_8(bit_width)); + break; + + case ACPI_WRITE: + +- memcpy(ACPI_PHYSADDR_TO_PTR(address), +- ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width)); ++ memcpy(pointer, ACPI_CAST_PTR(char, value), ++ ACPI_DIV_8(bit_width)); + break; + + default: +--- a/include/acpi/actypes.h ++++ b/include/acpi/actypes.h +@@ -1221,6 +1221,10 @@ struct acpi_mem_space_context { + struct acpi_mem_mapping *first_mm; + }; + ++struct acpi_data_table_space_context { ++ void *pointer; ++}; ++ + /* + * struct acpi_memory_list is used only if the ACPICA local cache is enabled + */ diff --git a/patches.suse/ACPICA-Use-original-pointer-for-virtual-origin-table.patch b/patches.suse/ACPICA-Use-original-pointer-for-virtual-origin-table.patch new file mode 100644 index 0000000..2bfb46d --- /dev/null +++ b/patches.suse/ACPICA-Use-original-pointer-for-virtual-origin-table.patch @@ -0,0 +1,499 @@ +From: Jessica Clarke +Date: Wed, 22 Dec 2021 17:22:28 +0100 +Subject: ACPICA: Use original pointer for virtual origin tables +Patch-mainline: v5.17-rc1 +Git-commit: 5d6e59665d8bb0f8fa4d47726a93326f8ddfb448 +References: jsc#PED-1408 + +ACPICA commit dfa3feffa8f760b686207d09dc880cd2f26c72af + +Currently the pointer to the table is cast to acpi_physical_address and +later cast back to a pointer to be dereferenced. Whether or not this is +supported is implementation-defined. + +On CHERI, and thus Arm's experimental Morello prototype architecture, +pointers are represented as capabilities, which are unforgeable bounded +pointers, providing always-on fine-grained spatial memory safety. This +means that any pointer cast to a plain integer will lose all its +associated metadata, and when cast back to a pointer it will give a +null-derived pointer (one that has the same metadata as null but an +address equal to the integer) that will trap on any dereference. As a +result, this is an implementation where acpi_physical_address cannot be +used as a hack to store real pointers. + +Thus, alter the lifecycle of table descriptors. Internal physical tables +keep the current behaviour where only the address is set on install, and +the pointer is set on acquire. Virtual tables (internal and external) +now store the pointer on initialisation and use that on acquire (which +will redundantly set *table_ptr to itself, but changing that is both +unnecessary and overly complicated as acpi_tb_acquire_table is called with +both a pointer to a variable and a pointer to Table->Pointer itself). + +This requires propagating the (possible) table pointer everywhere in +order to make sure pointers make it through to acpi_tb_acquire_temp_table, +which requires a change to the acpi_install_table interface. Instead of +taking an ACPI_PHYSADDR_TYPE and a boolean indicating whether it's +physical or virtual, it is now split into acpi_install_table (that takes +an external virtual table pointer) and acpi_install_physical_table (that +takes an ACPI_PHYSADDR_TYPE for an internal physical table address). +This also has the benefit of providing a cleaner API. + +Link: https://github.com/acpica/acpica/commit/dfa3feff +Signed-off-by: Bob Moore +[ rjw: Adjust the code in tables.c to match interface changes ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpica/actables.h | 8 ++- + drivers/acpi/acpica/exconfig.c | 2 + drivers/acpi/acpica/tbdata.c | 93 +++++++++++++++++++++++++++-------------- + drivers/acpi/acpica/tbfadt.c | 6 +- + drivers/acpi/acpica/tbinstal.c | 15 ++++-- + drivers/acpi/acpica/tbutils.c | 2 + drivers/acpi/acpica/tbxfload.c | 52 ++++++++++++++++------ + drivers/acpi/tables.c | 4 - + include/acpi/acpixf.h | 6 +- + 9 files changed, 129 insertions(+), 59 deletions(-) + +--- a/drivers/acpi/acpica/actables.h ++++ b/drivers/acpi/acpica/actables.h +@@ -35,7 +35,8 @@ acpi_tb_init_table_descriptor(struct acp + + acpi_status + acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc, +- acpi_physical_address address, u8 flags); ++ acpi_physical_address address, ++ u8 flags, struct acpi_table_header *table); + + void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc); + +@@ -86,6 +87,7 @@ acpi_tb_release_table(struct acpi_table_ + acpi_status + acpi_tb_install_standard_table(acpi_physical_address address, + u8 flags, ++ struct acpi_table_header *table, + u8 reload, u8 override, u32 *table_index); + + void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc); +@@ -95,7 +97,9 @@ acpi_tb_load_table(u32 table_index, stru + + acpi_status + acpi_tb_install_and_load_table(acpi_physical_address address, +- u8 flags, u8 override, u32 *table_index); ++ u8 flags, ++ struct acpi_table_header *table, ++ u8 override, u32 *table_index); + + acpi_status acpi_tb_unload_table(u32 table_index); + +--- a/drivers/acpi/acpica/exconfig.c ++++ b/drivers/acpi/acpica/exconfig.c +@@ -411,7 +411,7 @@ acpi_ex_load_op(union acpi_operand_objec + acpi_ex_exit_interpreter(); + status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table), + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, +- TRUE, &table_index); ++ table, TRUE, &table_index); + acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + +--- a/drivers/acpi/acpica/tbdata.c ++++ b/drivers/acpi/acpica/tbdata.c +@@ -89,14 +89,27 @@ acpi_tb_init_table_descriptor(struct acp + { + + /* +- * Initialize the table descriptor. Set the pointer to NULL, since the +- * table is not fully mapped at this time. ++ * Initialize the table descriptor. Set the pointer to NULL for external ++ * tables, since the table is not fully mapped at this time. + */ + memset(table_desc, 0, sizeof(struct acpi_table_desc)); + table_desc->address = address; + table_desc->length = table->length; + table_desc->flags = flags; + ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature); ++ ++ switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { ++ case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: ++ case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: ++ ++ table_desc->pointer = table; ++ break; ++ ++ case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: ++ default: ++ ++ break; ++ } + } + + /******************************************************************************* +@@ -132,9 +145,7 @@ acpi_tb_acquire_table(struct acpi_table_ + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + +- table = ACPI_CAST_PTR(struct acpi_table_header, +- ACPI_PHYSADDR_TO_PTR(table_desc-> +- address)); ++ table = table_desc->pointer; + break; + + default: +@@ -196,6 +207,8 @@ acpi_tb_release_table(struct acpi_table_ + * PARAMETERS: table_desc - Table descriptor to be acquired + * address - Address of the table + * flags - Allocation flags of the table ++ * table - Pointer to the table (required for virtual ++ * origins, optional for physical) + * + * RETURN: Status + * +@@ -208,49 +221,52 @@ acpi_tb_release_table(struct acpi_table_ + + acpi_status + acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc, +- acpi_physical_address address, u8 flags) ++ acpi_physical_address address, ++ u8 flags, struct acpi_table_header *table) + { +- struct acpi_table_header *table_header; ++ u8 mapped_table = FALSE; + + switch (flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + /* Get the length of the full table from the header */ + +- table_header = +- acpi_os_map_memory(address, +- sizeof(struct acpi_table_header)); +- if (!table_header) { +- return (AE_NO_MEMORY); ++ if (!table) { ++ table = ++ acpi_os_map_memory(address, ++ sizeof(struct ++ acpi_table_header)); ++ if (!table) { ++ return (AE_NO_MEMORY); ++ } ++ ++ mapped_table = TRUE; + } + +- acpi_tb_init_table_descriptor(table_desc, address, flags, +- table_header); +- acpi_os_unmap_memory(table_header, +- sizeof(struct acpi_table_header)); +- return (AE_OK); ++ break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + +- table_header = ACPI_CAST_PTR(struct acpi_table_header, +- ACPI_PHYSADDR_TO_PTR(address)); +- if (!table_header) { +- return (AE_NO_MEMORY); ++ if (!table) { ++ return_ACPI_STATUS(AE_BAD_PARAMETER); + } + +- acpi_tb_init_table_descriptor(table_desc, address, flags, +- table_header); +- return (AE_OK); ++ break; + + default: + +- break; ++ /* Table is not valid yet */ ++ ++ return (AE_NO_MEMORY); + } + +- /* Table is not valid yet */ ++ acpi_tb_init_table_descriptor(table_desc, address, flags, table); ++ if (mapped_table) { ++ acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); ++ } + +- return (AE_NO_MEMORY); ++ return (AE_OK); + } + + /******************************************************************************* +@@ -335,7 +351,19 @@ void acpi_tb_invalidate_table(struct acp + + acpi_tb_release_table(table_desc->pointer, table_desc->length, + table_desc->flags); +- table_desc->pointer = NULL; ++ ++ switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { ++ case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: ++ ++ table_desc->pointer = NULL; ++ break; ++ ++ case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: ++ case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: ++ default: ++ ++ break; ++ } + + return_VOID; + } +@@ -959,6 +987,9 @@ acpi_tb_load_table(u32 table_index, stru + * + * PARAMETERS: address - Physical address of the table + * flags - Allocation flags of the table ++ * table - Pointer to the table (required for ++ * virtual origins, optional for ++ * physical) + * override - Whether override should be performed + * table_index - Where table index is returned + * +@@ -970,7 +1001,9 @@ acpi_tb_load_table(u32 table_index, stru + + acpi_status + acpi_tb_install_and_load_table(acpi_physical_address address, +- u8 flags, u8 override, u32 *table_index) ++ u8 flags, ++ struct acpi_table_header *table, ++ u8 override, u32 *table_index) + { + acpi_status status; + u32 i; +@@ -979,7 +1012,7 @@ acpi_tb_install_and_load_table(acpi_phys + + /* Install the table and load it into the namespace */ + +- status = acpi_tb_install_standard_table(address, flags, TRUE, ++ status = acpi_tb_install_standard_table(address, flags, table, TRUE, + override, &i); + if (ACPI_FAILURE(status)) { + goto exit; +--- a/drivers/acpi/acpica/tbfadt.c ++++ b/drivers/acpi/acpica/tbfadt.c +@@ -313,7 +313,7 @@ void acpi_tb_parse_fadt(void) + acpi_tb_install_standard_table((acpi_physical_address)acpi_gbl_FADT. + Xdsdt, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, +- FALSE, TRUE, &acpi_gbl_dsdt_index); ++ NULL, FALSE, TRUE, &acpi_gbl_dsdt_index); + + /* If Hardware Reduced flag is set, there is no FACS */ + +@@ -322,14 +322,14 @@ void acpi_tb_parse_fadt(void) + acpi_tb_install_standard_table((acpi_physical_address) + acpi_gbl_FADT.facs, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, +- FALSE, TRUE, ++ NULL, FALSE, TRUE, + &acpi_gbl_facs_index); + } + if (acpi_gbl_FADT.Xfacs) { + acpi_tb_install_standard_table((acpi_physical_address) + acpi_gbl_FADT.Xfacs, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, +- FALSE, TRUE, ++ NULL, FALSE, TRUE, + &acpi_gbl_xfacs_index); + } + } +--- a/drivers/acpi/acpica/tbinstal.c ++++ b/drivers/acpi/acpica/tbinstal.c +@@ -79,6 +79,8 @@ acpi_tb_install_table_with_override(stru + * PARAMETERS: address - Address of the table (might be a virtual + * address depending on the table_flags) + * flags - Flags for the table ++ * table - Pointer to the table (required for virtual ++ * origins, optional for physical) + * reload - Whether reload should be performed + * override - Whether override should be performed + * table_index - Where the table index is returned +@@ -96,6 +98,7 @@ acpi_tb_install_table_with_override(stru + acpi_status + acpi_tb_install_standard_table(acpi_physical_address address, + u8 flags, ++ struct acpi_table_header *table, + u8 reload, u8 override, u32 *table_index) + { + u32 i; +@@ -106,7 +109,8 @@ acpi_tb_install_standard_table(acpi_phys + + /* Acquire a temporary table descriptor for validation */ + +- status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); ++ status = ++ acpi_tb_acquire_temp_table(&new_table_desc, address, flags, table); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not acquire table length at %8.8X%8.8X", +@@ -209,7 +213,8 @@ void acpi_tb_override_table(struct acpi_ + if (ACPI_SUCCESS(status) && table) { + acpi_tb_acquire_temp_table(&new_table_desc, + ACPI_PTR_TO_PHYSADDR(table), +- ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); ++ ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, ++ table); + ACPI_ERROR_ONLY(override_type = "Logical"); + goto finish_override; + } +@@ -220,7 +225,8 @@ void acpi_tb_override_table(struct acpi_ + &address, &length); + if (ACPI_SUCCESS(status) && address && length) { + acpi_tb_acquire_temp_table(&new_table_desc, address, +- ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); ++ ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, ++ NULL); + ACPI_ERROR_ONLY(override_type = "Physical"); + goto finish_override; + } +@@ -289,7 +295,8 @@ void acpi_tb_uninstall_table(struct acpi + + if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { +- ACPI_FREE(ACPI_PHYSADDR_TO_PTR(table_desc->address)); ++ ACPI_FREE(table_desc->pointer); ++ table_desc->pointer = NULL; + } + + table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); +--- a/drivers/acpi/acpica/tbutils.c ++++ b/drivers/acpi/acpica/tbutils.c +@@ -328,7 +328,7 @@ acpi_tb_parse_root_table(acpi_physical_a + + status = acpi_tb_install_standard_table(address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, +- FALSE, TRUE, ++ NULL, FALSE, TRUE, + &table_index); + + if (ACPI_SUCCESS(status) && +--- a/drivers/acpi/acpica/tbxfload.c ++++ b/drivers/acpi/acpica/tbxfload.c +@@ -227,9 +227,7 @@ unlock_and_exit: + * + * FUNCTION: acpi_install_table + * +- * PARAMETERS: address - Address of the ACPI table to be installed. +- * physical - Whether the address is a physical table +- * address or not ++ * PARAMETERS: table - Pointer to the ACPI table to be installed. + * + * RETURN: Status + * +@@ -240,22 +238,17 @@ unlock_and_exit: + ******************************************************************************/ + + acpi_status ACPI_INIT_FUNCTION +-acpi_install_table(acpi_physical_address address, u8 physical) ++acpi_install_table(struct acpi_table_header *table) + { + acpi_status status; +- u8 flags; + u32 table_index; + + ACPI_FUNCTION_TRACE(acpi_install_table); + +- if (physical) { +- flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; +- } else { +- flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; +- } +- +- status = acpi_tb_install_standard_table(address, flags, +- FALSE, FALSE, &table_index); ++ status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table), ++ ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, ++ table, FALSE, FALSE, ++ &table_index); + + return_ACPI_STATUS(status); + } +@@ -264,6 +257,37 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_install_tab + + /******************************************************************************* + * ++ * FUNCTION: acpi_install_physical_table ++ * ++ * PARAMETERS: address - Address of the ACPI table to be installed. ++ * ++ * RETURN: Status ++ * ++ * DESCRIPTION: Dynamically install an ACPI table. ++ * Note: This function should only be invoked after ++ * acpi_initialize_tables() and before acpi_load_tables(). ++ * ++ ******************************************************************************/ ++acpi_status ACPI_INIT_FUNCTION ++acpi_install_physical_table(acpi_physical_address address) ++{ ++ acpi_status status; ++ u32 table_index; ++ ++ ACPI_FUNCTION_TRACE(acpi_install_physical_table); ++ ++ status = acpi_tb_install_standard_table(address, ++ ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, ++ NULL, FALSE, FALSE, ++ &table_index); ++ ++ return_ACPI_STATUS(status); ++} ++ ++ACPI_EXPORT_SYMBOL_INIT(acpi_install_physical_table) ++ ++/******************************************************************************* ++ * + * FUNCTION: acpi_load_table + * + * PARAMETERS: table - Pointer to a buffer containing the ACPI +@@ -298,7 +322,7 @@ acpi_status acpi_load_table(struct acpi_ + ACPI_INFO(("Host-directed Dynamic ACPI Table Load:")); + status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table), + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, +- FALSE, &table_index); ++ table, FALSE, &table_index); + if (table_idx) { + *table_idx = table_index; + } +--- a/drivers/acpi/tables.c ++++ b/drivers/acpi/tables.c +@@ -721,7 +721,7 @@ static void __init acpi_table_initrd_sca + /* + * Mark the table to avoid being used in + * acpi_table_initrd_override(). Though this is not possible +- * because override is disabled in acpi_install_table(). ++ * because override is disabled in acpi_install_physical_table(). + */ + if (test_and_set_bit(table_index, acpi_initrd_installed)) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); +@@ -732,7 +732,7 @@ static void __init acpi_table_initrd_sca + table->signature, table->oem_id, + table->oem_table_id); + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); +- acpi_install_table(acpi_tables_addr + table_offset, TRUE); ++ acpi_install_physical_table(acpi_tables_addr + table_offset); + next_table: + table_offset += table_length; + table_index++; +--- a/include/acpi/acpixf.h ++++ b/include/acpi/acpixf.h +@@ -454,9 +454,11 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status + * ACPI table load/unload interfaces + */ + ACPI_EXTERNAL_RETURN_STATUS(acpi_status ACPI_INIT_FUNCTION +- acpi_install_table(acpi_physical_address address, +- u8 physical)) ++ acpi_install_table(struct acpi_table_header *table)) + ++ACPI_EXTERNAL_RETURN_STATUS(acpi_status ACPI_INIT_FUNCTION ++ acpi_install_physical_table(acpi_physical_address ++ address)) + ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_load_table(struct acpi_table_header *table, + u32 *table_idx)) diff --git a/patches.suse/ACPICA-iASL-Add-TDEL-table-to-both-compiler-disassem.patch b/patches.suse/ACPICA-iASL-Add-TDEL-table-to-both-compiler-disassem.patch new file mode 100644 index 0000000..c40c897 --- /dev/null +++ b/patches.suse/ACPICA-iASL-Add-TDEL-table-to-both-compiler-disassem.patch @@ -0,0 +1,52 @@ +From: Bob Moore +Date: Wed, 22 Dec 2021 17:36:30 +0100 +Subject: ACPICA: iASL: Add TDEL table to both compiler/disassembler +Patch-mainline: v5.17-rc1 +Git-commit: 2de6bb92ebbb0e8803554bb24391514b552cb481 +References: jsc#PED-1408 + +ACPICA commit 403f9965aba7ff9d2ed5b41bbffdd2a1ed0f596f + +Added struct acpi_pcc_info to acpi_src. + +Link: https://github.com/acpica/acpica/commit/403f9965 +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/acpi/actbl2.h | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/include/acpi/actbl2.h ++++ b/include/acpi/actbl2.h +@@ -48,6 +48,7 @@ + #define ACPI_SIG_SDEI "SDEI" /* Software Delegated Exception Interface Table */ + #define ACPI_SIG_SDEV "SDEV" /* Secure Devices table */ + #define ACPI_SIG_SVKL "SVKL" /* Storage Volume Key Location Table */ ++#define ACPI_SIG_TDEL "TDEL" /* TD Event Log Table */ + + /* + * All tables must be byte-packed to match the ACPI specification, since +@@ -2467,6 +2468,22 @@ enum acpi_svkl_format { + ACPI_SVKL_FORMAT_RESERVED = 1 /* 1 and greater are reserved */ + }; + ++/******************************************************************************* ++ * ++ * TDEL - TD-Event Log ++ * From: "Guest-Host-Communication Interface (GHCI) for Intel ++ * Trust Domain Extensions (Intel TDX)". ++ * September 2020 ++ * ++ ******************************************************************************/ ++ ++struct acpi_table_tdel { ++ struct acpi_table_header header; /* Common ACPI table header */ ++ u32 reserved; ++ u64 log_area_minimum_length; ++ u64 log_area_start_address; ++}; ++ + /* Reset to default packing */ + + #pragma pack() diff --git a/patches.suse/ACPICA-iASL-Add-suppport-for-AGDI-table.patch b/patches.suse/ACPICA-iASL-Add-suppport-for-AGDI-table.patch new file mode 100644 index 0000000..c94cc3d --- /dev/null +++ b/patches.suse/ACPICA-iASL-Add-suppport-for-AGDI-table.patch @@ -0,0 +1,61 @@ +From: Ilkka Koskinen +Date: Wed, 22 Dec 2021 17:37:21 +0100 +Subject: ACPICA: iASL: Add suppport for AGDI table +Patch-mainline: v5.17-rc1 +Git-commit: 5579649e7eb756a4e3d5784b6958374e5bfc41de +References: jsc#PED-1408 + +ACPICA commit cf36a6d658ca5aa8c329c2edfc3322c095ffd844 + +Add support for Arm Generic Diagnostic Dump and Reset Interface, which is +described by "ACPI for Arm Components 1.1 Platform Design Document" +ARM DEN0093. + +Add the necessary types in the ACPICA header files and support for +compiling and decompiling the table. + +Link: https://github.com/acpica/acpica/commit/cf36a6d6 +Signed-off-by: Ilkka Koskinen +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/acpi/actbl2.h | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/include/acpi/actbl2.h ++++ b/include/acpi/actbl2.h +@@ -24,6 +24,7 @@ + * file. Useful because they make it more difficult to inadvertently type in + * the wrong signature. + */ ++#define ACPI_SIG_AGDI "AGDI" /* Arm Generic Diagnostic Dump and Reset Device Interface */ + #define ACPI_SIG_BDAT "BDAT" /* BIOS Data ACPI Table */ + #define ACPI_SIG_IORT "IORT" /* IO Remapping Table */ + #define ACPI_SIG_IVRS "IVRS" /* I/O Virtualization Reporting Structure */ +@@ -239,6 +240,25 @@ typedef struct acpi_aest_node_interrupt + #define ACPI_AEST_XRUPT_RESERVED 2 /* 2 and above are reserved */ + + /******************************************************************************* ++ * AGDI - Arm Generic Diagnostic Dump and Reset Device Interface ++ * ++ * Conforms to "ACPI for Arm Components 1.1, Platform Design Document" ++ * ARM DEN0093 v1.1 ++ * ++ ******************************************************************************/ ++struct acpi_table_agdi { ++ struct acpi_table_header header; /* Common ACPI table header */ ++ u8 flags; ++ u8 reserved[3]; ++ u32 sdei_event; ++ u32 gsiv; ++}; ++ ++/* Mask for Flags field above */ ++ ++#define ACPI_AGDI_SIGNALING_MODE (1) ++ ++/******************************************************************************* + * + * BDAT - BIOS Data ACPI Table + * diff --git a/patches.suse/ACPICA-iASL-Disassembler-Additional-support-for-NHLT.patch b/patches.suse/ACPICA-iASL-Disassembler-Additional-support-for-NHLT.patch new file mode 100644 index 0000000..b6e349d --- /dev/null +++ b/patches.suse/ACPICA-iASL-Disassembler-Additional-support-for-NHLT.patch @@ -0,0 +1,134 @@ +From: Bob Moore +Date: Wed, 22 Dec 2021 17:25:40 +0100 +Subject: ACPICA: iASL/Disassembler: Additional support for NHLT table +Patch-mainline: v5.17-rc1 +Git-commit: e4a07f5acd730802ada629d52a29c4873f9826a4 +References: jsc#PED-1408 + +ACPICA commit 0420852ffc520b81960e877852703b739c16025c + +Added support for Vendor-defined microphone arrays and SNR +(signal-to-noise) extension. + +Link: https://github.com/acpica/acpica/commit/0420852f +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/acpi/actbl2.h | 72 +++++++++++++++++++++++++++++--------------------- + 1 file changed, 42 insertions(+), 30 deletions(-) + +--- a/include/acpi/actbl2.h ++++ b/include/acpi/actbl2.h +@@ -1495,12 +1495,10 @@ struct acpi_nhlt_device_specific_config_ + + /* Values for Config Type above */ + +-#define ACPI_NHLT_TYPE_MIC_ARRAY 0x01 +-#define ACPI_NHLT_TYPE_GENERIC 0x00 +- +-/* Mask for Extension field of array_type */ +- +-#define ACPI_NHLT_ARRAY_TYPE_MASK 0x10 ++#define ACPI_NHLT_CONFIG_TYPE_GENERIC 0x00 ++#define ACPI_NHLT_CONFIG_TYPE_MIC_ARRAY 0x01 ++#define ACPI_NHLT_CONFIG_TYPE_RENDER_FEEDBACK 0x03 ++#define ACPI_NHLT_CONFIG_TYPE_RESERVED 0x04 /* 4 and above are reserved */ + + struct acpi_nhlt_device_specific_config_b { + u32 capabilities_size; +@@ -1511,6 +1509,11 @@ struct acpi_nhlt_device_specific_config_ + u8 virtual_slot; + }; + ++struct acpi_nhlt_render_device_specific_config { ++ u32 capabilities_size; ++ u8 virtual_slot; ++}; ++ + struct acpi_nhlt_wave_extensible { + u16 format_tag; + u16 channel_count; +@@ -1573,17 +1576,22 @@ struct acpi_nhlt_mic_device_specific_con + + /* Values for array_type_ext above */ + +-#define SMALL_LINEAR_2ELEMENT 0x0A +-#define BIG_LINEAR_2ELEMENT 0x0B +-#define FIRST_GEOMETRY_LINEAR_4ELEMENT 0x0C +-#define PLANAR_LSHAPED_4ELEMENT 0x0D +-#define SECOND_GEOMETRY_LINEAR_4ELEMENT 0x0E +-#define VENDOR_DEFINED 0x0F +-#define ARRAY_TYPE_MASK 0x0F +-#define ARRAY_TYPE_EXT_MASK 0x10 ++#define ACPI_NHLT_ARRAY_TYPE_RESERVED 0x09 // 9 and below are reserved ++#define ACPI_NHLT_SMALL_LINEAR_2ELEMENT 0x0A ++#define ACPI_NHLT_BIG_LINEAR_2ELEMENT 0x0B ++#define ACPI_NHLT_FIRST_GEOMETRY_LINEAR_4ELEMENT 0x0C ++#define ACPI_NHLT_PLANAR_LSHAPED_4ELEMENT 0x0D ++#define ACPI_NHLT_SECOND_GEOMETRY_LINEAR_4ELEMENT 0x0E ++#define ACPI_NHLT_VENDOR_DEFINED 0x0F ++#define ACPI_NHLT_ARRAY_TYPE_MASK 0x0F ++#define ACPI_NHLT_ARRAY_TYPE_EXT_MASK 0x10 ++ ++#define ACPI_NHLT_NO_EXTENSION 0x0 ++#define ACPI_NHLT_MIC_SNR_SENSITIVITY_EXT (1<<4) + +-#define NO_EXTENSION 0x0 +-#define MIC_SNR_SENSITIVITY_EXT 0x1 ++struct acpi_nhlt_vendor_mic_count { ++ u8 microphone_count; ++}; + + struct acpi_nhlt_vendor_mic_config { + u8 type; +@@ -1603,22 +1611,25 @@ struct acpi_nhlt_vendor_mic_config { + + /* Values for Type field above */ + +-#define MIC_OMNIDIRECTIONAL 0 +-#define MIC_SUBCARDIOID 1 +-#define MIC_CARDIOID 2 +-#define MIC_SUPER_CARDIOID 3 +-#define MIC_HYPER_CARDIOID 4 +-#define MIC_8_SHAPED 5 +-#define MIC_VENDOR_DEFINED 7 ++#define ACPI_NHLT_MIC_OMNIDIRECTIONAL 0 ++#define ACPI_NHLT_MIC_SUBCARDIOID 1 ++#define ACPI_NHLT_MIC_CARDIOID 2 ++#define ACPI_NHLT_MIC_SUPER_CARDIOID 3 ++#define ACPI_NHLT_MIC_HYPER_CARDIOID 4 ++#define ACPI_NHLT_MIC_8_SHAPED 5 ++#define ACPI_NHLT_MIC_RESERVED6 6 // 6 is reserved ++#define ACPI_NHLT_MIC_VENDOR_DEFINED 7 ++#define ACPI_NHLT_MIC_RESERVED 8 // 8 and above are reserved + + /* Values for Panel field above */ + +-#define MIC_TOP 0 +-#define MIC_BOTTOM 1 +-#define MIC_LEFT 2 +-#define MIC_RIGHT 3 +-#define MIC_FRONT 4 +-#define MIC_REAR 5 ++#define ACPI_NHLT_MIC_POSITION_TOP 0 ++#define ACPI_NHLT_MIC_POSITION_BOTTOM 1 ++#define ACPI_NHLT_MIC_POSITION_LEFT 2 ++#define ACPI_NHLT_MIC_POSITION_RIGHT 3 ++#define ACPI_NHLT_MIC_POSITION_FRONT 4 ++#define ACPI_NHLT_MIC_POSITION_BACK 5 ++#define ACPI_NHLT_MIC_POSITION_RESERVED 6 // 6 and above are reserved + + struct acpi_nhlt_vendor_mic_device_specific_config { + struct acpi_nhlt_mic_device_specific_config mic_array_device_config; +@@ -1633,8 +1644,9 @@ struct acpi_nhlt_mic_snr_sensitivity_ext + u32 sensitivity; + }; + ++/* Render device with feedback */ ++ + struct acpi_nhlt_render_feedback_device_specific_config { +- struct acpi_nhlt_device_specific_config device_config; + u8 feedback_virtual_slot; // render slot in case of capture + u16 feedback_channels; // informative only + u16 feedback_valid_bits_per_sample; diff --git a/patches.suse/ACPICA-iASL-NHLT-table-Specific-Data-field-support.patch b/patches.suse/ACPICA-iASL-NHLT-table-Specific-Data-field-support.patch new file mode 100644 index 0000000..d611410 --- /dev/null +++ b/patches.suse/ACPICA-iASL-NHLT-table-Specific-Data-field-support.patch @@ -0,0 +1,35 @@ +From: Bob Moore +Date: Wed, 22 Dec 2021 17:37:56 +0100 +Subject: ACPICA: iASL/NHLT table: "Specific Data" field support +Patch-mainline: v5.17-rc1 +Git-commit: 0c9a672729d62d27d0c9993e106707be0b0c2bc0 +References: jsc#PED-1408 + +ACPICA commit 26f8c721fb01e4a26eec8c85dffcbe950d5e61a9 + +Add support for optional "Specific Data" field for the optional +Linux-specific structure that appears at the end of an Endpoint +Descriptor. + +Link: https://github.com/acpica/acpica/commit/26f8c721 +Signed-off-by: Bob Moore +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/acpi/actbl2.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/include/acpi/actbl2.h ++++ b/include/acpi/actbl2.h +@@ -1683,7 +1683,10 @@ struct acpi_nhlt_linux_specific_data { + u8 device_id[16]; + u8 device_instance_id; + u8 device_port_id; +- u8 filler[18]; ++}; ++ ++struct acpi_nhlt_linux_specific_data_b { ++ u8 specific_data[18]; + }; + + struct acpi_nhlt_table_terminator { diff --git a/patches.suse/PM-hibernate-Allow-ACPI-hardware-signature-to-be-hon.patch b/patches.suse/PM-hibernate-Allow-ACPI-hardware-signature-to-be-hon.patch new file mode 100644 index 0000000..90cd0cb --- /dev/null +++ b/patches.suse/PM-hibernate-Allow-ACPI-hardware-signature-to-be-hon.patch @@ -0,0 +1,219 @@ +From: David Woodhouse +Date: Mon, 8 Nov 2021 16:09:41 +0000 +Subject: PM: hibernate: Allow ACPI hardware signature to be honoured +Patch-mainline: v5.17-rc1 +Git-commit: 74d9555580c48a04b2c3b742dfb0c80777aa0b26 +References: jsc#PED-1408 + +Theoretically, when the hardware signature in FACS changes, the OS +is supposed to gracefully decline to attempt to resume from S4: + + "If the signature has changed, OSPM will not restore the system + context and can boot from scratch" + +In practice, Windows doesn't do this and many laptop vendors do allow +the signature to change especially when docking/undocking, so it would +be a bad idea to simply comply with the specification by default in the +general case. + +However, there are use cases where we do want the compliant behaviour +and we know it's safe. Specifically, when resuming virtual machines where +we know the hypervisor has changed sufficiently that resume will fail. +We really want to be able to *tell* the guest kernel not to try, so it +boots cleanly and doesn't just crash. This patch provides a way to opt +in to the spec-compliant behaviour on the command line. + +A follow-up patch may do this automatically for certain "known good" +machines based on a DMI match, or perhaps just for all hypervisor +guests since there's no good reason a hypervisor would change the +hardware_signature that it exposes to guests *unless* it wants them +to obey the ACPI specification. + +Signed-off-by: David Woodhouse +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + Documentation/admin-guide/kernel-parameters.txt | 15 +++++++++++-- + arch/x86/kernel/acpi/sleep.c | 4 ++- + drivers/acpi/sleep.c | 26 +++++++++++++++++++----- + include/linux/acpi.h | 2 - + include/linux/suspend.h | 1 + kernel/power/power.h | 1 + kernel/power/swap.c | 16 ++++++++++++-- + 7 files changed, 53 insertions(+), 12 deletions(-) + +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -225,14 +225,23 @@ + For broken nForce2 BIOS resulting in XT-PIC timer. + + acpi_sleep= [HW,ACPI] Sleep options +- Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, +- old_ordering, nonvs, sci_force_enable, nobl } ++ Format: { s3_bios, s3_mode, s3_beep, s4_hwsig, ++ s4_nohwsig, old_ordering, nonvs, ++ sci_force_enable, nobl } + See Documentation/power/video.rst for information on + s3_bios and s3_mode. + s3_beep is for debugging; it makes the PC's speaker beep + as soon as the kernel's real-mode entry point is called. ++ s4_hwsig causes the kernel to check the ACPI hardware ++ signature during resume from hibernation, and gracefully ++ refuse to resume if it has changed. This complies with ++ the ACPI specification but not with reality, since ++ Windows does not do this and many laptops do change it ++ on docking. So the default behaviour is to allow resume ++ and simply warn when the signature changes, unless the ++ s4_hwsig option is enabled. + s4_nohwsig prevents ACPI hardware signature from being +- used during resume from hibernation. ++ used (or even warned about) during resume. + old_ordering causes the ACPI 1.0 ordering of the _PTS + control method, with respect to putting devices into + low power states, to be enforced (the ACPI 2.0 ordering +--- a/arch/x86/kernel/acpi/sleep.c ++++ b/arch/x86/kernel/acpi/sleep.c +@@ -139,8 +139,10 @@ static int __init acpi_sleep_setup(char + if (strncmp(str, "s3_beep", 7) == 0) + acpi_realmode_flags |= 4; + #ifdef CONFIG_HIBERNATION ++ if (strncmp(str, "s4_hwsig", 8) == 0) ++ acpi_check_s4_hw_signature(1); + if (strncmp(str, "s4_nohwsig", 10) == 0) +- acpi_no_s4_hw_signature(); ++ acpi_check_s4_hw_signature(0); + #endif + if (strncmp(str, "nonvs", 5) == 0) + acpi_nvs_nosave(); +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -874,11 +874,11 @@ static inline void acpi_sleep_syscore_in + #ifdef CONFIG_HIBERNATION + static unsigned long s4_hardware_signature; + static struct acpi_table_facs *facs; +-static bool nosigcheck; ++static int sigcheck = -1; /* Default behaviour is just to warn */ + +-void __init acpi_no_s4_hw_signature(void) ++void __init acpi_check_s4_hw_signature(int check) + { +- nosigcheck = true; ++ sigcheck = check; + } + + static int acpi_hibernation_begin(pm_message_t stage) +@@ -1004,12 +1004,28 @@ static void acpi_sleep_hibernate_setup(v + hibernation_set_ops(old_suspend_ordering ? + &acpi_hibernation_ops_old : &acpi_hibernation_ops); + sleep_states[ACPI_STATE_S4] = 1; +- if (nosigcheck) ++ if (!sigcheck) + return; + + acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs); +- if (facs) ++ if (facs) { ++ /* ++ * s4_hardware_signature is the local variable which is just ++ * used to warn about mismatch after we're attempting to ++ * resume (in violation of the ACPI specification.) ++ */ + s4_hardware_signature = facs->hardware_signature; ++ ++ if (sigcheck > 0) { ++ /* ++ * If we're actually obeying the ACPI specification ++ * then the signature is written out as part of the ++ * swsusp header, in order to allow the boot kernel ++ * to gracefully decline to resume. ++ */ ++ swsusp_hardware_signature = facs->hardware_signature; ++ } ++ } + } + #else /* !CONFIG_HIBERNATION */ + static inline void acpi_sleep_hibernate_setup(void) {} +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -506,7 +506,7 @@ acpi_status acpi_release_memory(acpi_han + int acpi_resources_are_enforced(void); + + #ifdef CONFIG_HIBERNATION +-void __init acpi_no_s4_hw_signature(void); ++void __init acpi_check_s4_hw_signature(int check); + #endif + + #ifdef CONFIG_PM_SLEEP +--- a/include/linux/suspend.h ++++ b/include/linux/suspend.h +@@ -446,6 +446,7 @@ extern unsigned long get_safe_page(gfp_t + extern asmlinkage int swsusp_arch_suspend(void); + extern asmlinkage int swsusp_arch_resume(void); + ++extern u32 swsusp_hardware_signature; + extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); + extern int hibernate(void); + extern bool system_entering_hibernation(void); +--- a/kernel/power/power.h ++++ b/kernel/power/power.h +@@ -168,6 +168,7 @@ extern int swsusp_swap_in_use(void); + #define SF_PLATFORM_MODE 1 + #define SF_NOCOMPRESS_MODE 2 + #define SF_CRC32_MODE 4 ++#define SF_HW_SIG 8 + + /* kernel/power/hibernate.c */ + extern int swsusp_check(void); +--- a/kernel/power/swap.c ++++ b/kernel/power/swap.c +@@ -36,6 +36,8 @@ + + #define HIBERNATE_SIG "S1SUSPEND" + ++u32 swsusp_hardware_signature; ++ + /* + * When reading an {un,}compressed image, we may restore pages in place, + * in which case some architectures need these pages cleaning before they +@@ -104,7 +106,8 @@ struct swap_map_handle { + + struct swsusp_header { + char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int) - +- sizeof(u32)]; ++ sizeof(u32) - sizeof(u32)]; ++ u32 hw_sig; + u32 crc32; + sector_t image; + unsigned int flags; /* Flags to pass to the "boot" kernel */ +@@ -312,7 +315,6 @@ static int hib_wait_io(struct hib_bio_ba + /* + * Saving part + */ +- + static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) + { + int error; +@@ -324,6 +326,10 @@ static int mark_swapfiles(struct swap_ma + memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10); + memcpy(swsusp_header->sig, HIBERNATE_SIG, 10); + swsusp_header->image = handle->first_sector; ++ if (swsusp_hardware_signature) { ++ swsusp_header->hw_sig = swsusp_hardware_signature; ++ flags |= SF_HW_SIG; ++ } + swsusp_header->flags = flags; + if (flags & SF_CRC32_MODE) + swsusp_header->crc32 = handle->crc32; +@@ -1537,6 +1543,12 @@ int swsusp_check(void) + } else { + error = -EINVAL; + } ++ if (!error && swsusp_header->flags & SF_HW_SIG && ++ swsusp_header->hw_sig != swsusp_hardware_signature) { ++ pr_info("Suspend image hardware signature mismatch (%08x now %08x); aborting resume.\n", ++ swsusp_header->hw_sig, swsusp_hardware_signature); ++ error = -EINVAL; ++ } + + put: + if (error) diff --git a/patches.suse/Revert-ACPI-processor-idle-Only-flush-cache-on-enter.patch b/patches.suse/Revert-ACPI-processor-idle-Only-flush-cache-on-enter.patch new file mode 100644 index 0000000..8264cf3 --- /dev/null +++ b/patches.suse/Revert-ACPI-processor-idle-Only-flush-cache-on-enter.patch @@ -0,0 +1,41 @@ +From: Akihiko Odaki +Date: Sun, 3 Apr 2022 15:23:22 +0900 +Subject: Revert "ACPI: processor: idle: Only flush cache on entering C3" +Patch-mainline: v5.18-rc2 +Git-commit: dfbba2518aac4204203b0697a894d3b2f80134d3 +References: jsc#PED-1408 + +Revert commit 87ebbb8c612b ("ACPI: processor: idle: Only flush cache +on entering C3") that broke the assumptions of the acpi_idle_play_dead() +callers. + +Namely, the CPU cache must always be flushed in acpi_idle_play_dead(), +regardless of the target C-state that is going to be requested, because +this is likely to be part of a CPU offline procedure or preparation for +entering a system-wide sleep state and the lack of synchronization +between the CPU cache and RAM may lead to problems going forward, for +example when the CPU is brought back online. + +In particular, it breaks resume from suspend-to-RAM on Lenovo ThinkPad +C13 which fails occasionally until the problematic commit is reverted. + +Signed-off-by: Akihiko Odaki +[ rjw: Changelog ] +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/processor_idle.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -570,8 +570,7 @@ static int acpi_idle_play_dead(struct cp + { + struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); + +- if (cx->type == ACPI_STATE_C3) +- ACPI_FLUSH_CPU_CACHE(); ++ ACPI_FLUSH_CPU_CACHE(); + + while (1) { + diff --git a/patches.suse/Revert-ACPI-scan-Do-not-add-device-IDs-from-_CID-if-.patch b/patches.suse/Revert-ACPI-scan-Do-not-add-device-IDs-from-_CID-if-.patch new file mode 100644 index 0000000..da6379b --- /dev/null +++ b/patches.suse/Revert-ACPI-scan-Do-not-add-device-IDs-from-_CID-if-.patch @@ -0,0 +1,39 @@ +From: "Rafael J. Wysocki" +Date: Wed, 16 Mar 2022 11:23:05 +0100 +Subject: Revert "ACPI: scan: Do not add device IDs from _CID if _HID is not + valid" +Patch-mainline: v5.17 +Git-commit: 462ccc35a750f335c8456cde9120b8b593fff60f +References: jsc#PED-1408 + +Revert commit e38f9ff63e6d ("ACPI: scan: Do not add device IDs from _CID +if _HID is not valid"), because it has introduced regressions on +multiple systems, even though it only has effect on clearly invalid +firmware. + +Reported-by: Pierre-Louis Bossart +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/scan.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -1377,11 +1377,11 @@ static void acpi_set_pnp_ids(acpi_handle + if (info->valid & ACPI_VALID_HID) { + acpi_add_id(pnp, info->hardware_id.string); + pnp->type.platform_id = 1; +- if (info->valid & ACPI_VALID_CID) { +- cid_list = &info->compatible_id_list; +- for (i = 0; i < cid_list->count; i++) +- acpi_add_id(pnp, cid_list->ids[i].string); +- } ++ } ++ if (info->valid & ACPI_VALID_CID) { ++ cid_list = &info->compatible_id_list; ++ for (i = 0; i < cid_list->count; i++) ++ acpi_add_id(pnp, cid_list->ids[i].string); + } + if (info->valid & ACPI_VALID_ADR) { + pnp->bus_address = info->address; diff --git a/patches.suse/Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch b/patches.suse/Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch new file mode 100644 index 0000000..4e37732 --- /dev/null +++ b/patches.suse/Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch @@ -0,0 +1,182 @@ +From 8e10548f7f4814e530857d2049d6af6bc78add53 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 3 Feb 2022 22:44:43 +0100 +Subject: [PATCH] Revert "usb: host: xhci: mvebu: make USB 3.0 PHY optional for + Armada 3720" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Git-commit: 8e10548f7f4814e530857d2049d6af6bc78add53 +References: jsc#PED-531 +Patch-mainline: v5.18-rc1 + +This reverts commit 3241929b67d28c83945d3191c6816a3271fd6b85. + +Armada 3720 phy driver (phy-mvebu-a3700-comphy.c) does not return +-EOPNOTSUPP from phy_power_on() callback anymore. + +So remove XHCI_SKIP_PHY_INIT flag from xhci_mvebu_a3700_plat_setup() and +then also whole xhci_mvebu_a3700_plat_setup() function which is there just +to handle -EOPNOTSUPP for XHCI_SKIP_PHY_INIT. + +xhci plat_setup callback is not used by any other xhci plat driver, so +remove this callback completely. + +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Acked-by: Miquel Raynal +Acked-by: Greg Kroah-Hartman +Link: https://lore.kernel.org/r/20220203214444.1508-5-kabel@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-mvebu.c | 42 ----------------------------------- + drivers/usb/host/xhci-mvebu.h | 6 ----- + drivers/usb/host/xhci-plat.c | 20 +---------------- + drivers/usb/host/xhci-plat.h | 1 - + 4 files changed, 1 insertion(+), 68 deletions(-) + +diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c +index 8ca1a235d164..60651a50770f 100644 +--- a/drivers/usb/host/xhci-mvebu.c ++++ b/drivers/usb/host/xhci-mvebu.c +@@ -8,7 +8,6 @@ + #include + #include + #include +-#include + + #include + #include +@@ -75,47 +74,6 @@ int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) + return 0; + } + +-int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd) +-{ +- struct xhci_hcd *xhci = hcd_to_xhci(hcd); +- struct device *dev = hcd->self.controller; +- struct phy *phy; +- int ret; +- +- /* Old bindings miss the PHY handle */ +- phy = of_phy_get(dev->of_node, "usb3-phy"); +- if (IS_ERR(phy) && PTR_ERR(phy) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- else if (IS_ERR(phy)) +- goto phy_out; +- +- ret = phy_init(phy); +- if (ret) +- goto phy_put; +- +- ret = phy_set_mode(phy, PHY_MODE_USB_HOST_SS); +- if (ret) +- goto phy_exit; +- +- ret = phy_power_on(phy); +- if (ret == -EOPNOTSUPP) { +- /* Skip initializatin of XHCI PHY when it is unsupported by firmware */ +- dev_warn(dev, "PHY unsupported by firmware\n"); +- xhci->quirks |= XHCI_SKIP_PHY_INIT; +- } +- if (ret) +- goto phy_exit; +- +- phy_power_off(phy); +-phy_exit: +- phy_exit(phy); +-phy_put: +- of_phy_put(phy); +-phy_out: +- +- return 0; +-} +- + int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) + { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); +diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h +index 01bf3fcb3eca..3be021793cc8 100644 +--- a/drivers/usb/host/xhci-mvebu.h ++++ b/drivers/usb/host/xhci-mvebu.h +@@ -12,7 +12,6 @@ struct usb_hcd; + + #if IS_ENABLED(CONFIG_USB_XHCI_MVEBU) + int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd); +-int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd); + int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd); + #else + static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) +@@ -20,11 +19,6 @@ static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) + return 0; + } + +-static inline int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd) +-{ +- return 0; +-} +- + static inline int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) + { + return 0; +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index c1edcc9b13ce..4d34f6005381 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -44,16 +44,6 @@ static void xhci_priv_plat_start(struct usb_hcd *hcd) + priv->plat_start(hcd); + } + +-static int xhci_priv_plat_setup(struct usb_hcd *hcd) +-{ +- struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); +- +- if (!priv->plat_setup) +- return 0; +- +- return priv->plat_setup(hcd); +-} +- + static int xhci_priv_init_quirk(struct usb_hcd *hcd) + { + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); +@@ -121,7 +111,6 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada = { + }; + + static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = { +- .plat_setup = xhci_mvebu_a3700_plat_setup, + .init_quirk = xhci_mvebu_a3700_init_quirk, + }; + +@@ -341,14 +330,7 @@ static int xhci_plat_probe(struct platform_device *pdev) + + hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); + xhci->shared_hcd->tpl_support = hcd->tpl_support; +- +- if (priv) { +- ret = xhci_priv_plat_setup(hcd); +- if (ret) +- goto disable_usb_phy; +- } +- +- if ((xhci->quirks & XHCI_SKIP_PHY_INIT) || (priv && (priv->quirks & XHCI_SKIP_PHY_INIT))) ++ if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) + hcd->skip_phy_initialization = 1; + + if (priv && (priv->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK)) +diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h +index 561d0b7bce09..1fb149d1fbce 100644 +--- a/drivers/usb/host/xhci-plat.h ++++ b/drivers/usb/host/xhci-plat.h +@@ -13,7 +13,6 @@ + struct xhci_plat_priv { + const char *firmware_name; + unsigned long long quirks; +- int (*plat_setup)(struct usb_hcd *); + void (*plat_start)(struct usb_hcd *); + int (*init_quirk)(struct usb_hcd *); + int (*suspend_quirk)(struct usb_hcd *); +-- +2.35.3 + diff --git a/patches.suse/arm64-Discard-.note.GNU-stack-section.patch b/patches.suse/arm64-Discard-.note.GNU-stack-section.patch new file mode 100644 index 0000000..210f52a --- /dev/null +++ b/patches.suse/arm64-Discard-.note.GNU-stack-section.patch @@ -0,0 +1,50 @@ +From fa71cc4400924859467812705749ee9b98b3eec6 Mon Sep 17 00:00:00 2001 +From: Oscar Salvador +Date: Wed, 5 Oct 2022 18:09:21 +0200 +Subject: [PATCH] arm64: Discard .note.GNU-stack section +Patch-mainline: Never, SUSE specific +References: bsc#1203693 + +Commit "Makefile: link with -z noexecstack --no-warn-rwx-segments: ddbd47d2219a" +creates a new section .note.GNU-stack, which is not discarded by arm64. +This changes the ELF layout and causes the build to fail on arm64. + +Quoting Michal Matz: + + "The .note.GNU-stack section in head.o is created by 'ld -r -z noexecstack', + when relinking head.o into head.o (for various reasons). That section is created + with SHT_PROGBITS, and as the kernel linker script doesn't discard those + it also makes the output ".notes" section (which + collects all .note* sections) SHT_PROGBITS, which in turn makes ld not generate + a PT_NOTE segment covering all these. + + Now, I initially thought the linker with 'ld -r', when generating a + .note.GNU-stack section because of a command line option should simply create it + with the type SHT_NOTE and all would be well. That somewhat works, but is actually + wrong: a SHT_NOTE section has a specific layout per the gABI (at least + it must contain a header), but .note.GNU-stack is empty. So it really can't + be SHT_NOTE but must remain either SHT_PROGBITS or SHT_NOBITS." + +Fix it for now by discarding that section. + +Signed-off-by: Oscar Salvador +Suggested-by: Michael Matz +Date: Sun, 12 Dec 2021 23:35:24 +0530 +Subject: drivers: acpi: acpi_apd: Remove unused device property "is-rv" +Patch-mainline: v5.17-rc1 +Git-commit: 3663f26b389b3951426971b44bb9312fdff0efec +References: jsc#PED-1408 + +Initially "is-rv" device property is added for 48MHz fixed clock +support on Raven or RV architecture. It's unused now as we moved +to pci device_id based selection to extend such support on other +architectures. This change removed unused code from acpi driver. + +Signed-off-by: Ajit Kumar Pandey +Reviewed-by: Mario Limonciello +Link: https://lore.kernel.org/r/20211212180527.1641362-3-AjitKumar.Pandey@amd.com +Signed-off-by: Stephen Boyd +Acked-by: Lee, Chun-Yi +--- + drivers/acpi/acpi_apd.c | 3 --- + include/linux/platform_data/clk-fch.h | 1 - + 2 files changed, 4 deletions(-) + +--- a/drivers/acpi/acpi_apd.c ++++ b/drivers/acpi/acpi_apd.c +@@ -87,9 +87,6 @@ static int fch_misc_setup(struct apd_pri + if (ret < 0) + return -ENOENT; + +- if (!acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, &obj)) +- clk_data->is_rv = obj->integer.value; +- + list_for_each_entry(rentry, &resource_list, node) { + clk_data->base = devm_ioremap(&adev->dev, rentry->res->start, + resource_size(rentry->res)); +--- a/include/linux/platform_data/clk-fch.h ++++ b/include/linux/platform_data/clk-fch.h +@@ -12,7 +12,6 @@ + + struct fch_clk_data { + void __iomem *base; +- u32 is_rv; + }; + + #endif /* __CLK_FCH_H */ diff --git a/patches.suse/drivers-nvdimm-Add-nvdimm-pmu-structure.patch b/patches.suse/drivers-nvdimm-Add-nvdimm-pmu-structure.patch new file mode 100644 index 0000000..51d819a --- /dev/null +++ b/patches.suse/drivers-nvdimm-Add-nvdimm-pmu-structure.patch @@ -0,0 +1,66 @@ +From 9a61d0838cd0a81529badfba7bfa39e81d5529d3 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Fri, 25 Feb 2022 20:00:21 +0530 +Subject: [PATCH] drivers/nvdimm: Add nvdimm pmu structure + +References: jsc#PED-1925 +Patch-mainline: v5.18-rc1 +Git-commit: 9a61d0838cd0a81529badfba7bfa39e81d5529d3 + +A structure is added called nvdimm_pmu, for performance +stats reporting support of nvdimm devices. It can be used to add +device pmu data such as pmu data structure for performance +stats, nvdimm device pointer along with cpumask attributes. + +Acked-by: Peter Zijlstra (Intel) +Tested-by: Nageswara R Sastry +Signed-off-by: Kajol Jain +Reviewed-by: Madhavan Srinivasan +Link: https://lore.kernel.org/r/20220225143024.47947-2-kjain@linux.ibm.com +Signed-off-by: Dan Williams +Acked-by: Michal Suchanek +--- + include/linux/nd.h | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/include/linux/nd.h b/include/linux/nd.h +index 8a8c63edb1b2..ad186e828263 100644 +--- a/include/linux/nd.h ++++ b/include/linux/nd.h +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + enum nvdimm_event { + NVDIMM_REVALIDATE_POISON, +@@ -23,6 +24,25 @@ enum nvdimm_claim_class { + NVDIMM_CCLASS_UNKNOWN, + }; + ++/** ++ * struct nvdimm_pmu - data structure for nvdimm perf driver ++ * @pmu: pmu data structure for nvdimm performance stats. ++ * @dev: nvdimm device pointer. ++ * @cpu: designated cpu for counter access. ++ * @node: node for cpu hotplug notifier link. ++ * @cpuhp_state: state for cpu hotplug notification. ++ * @arch_cpumask: cpumask to get designated cpu for counter access. ++ */ ++struct nvdimm_pmu { ++ struct pmu pmu; ++ struct device *dev; ++ int cpu; ++ struct hlist_node node; ++ enum cpuhp_state cpuhp_state; ++ /* cpumask provided by arch/platform specific code */ ++ struct cpumask arch_cpumask; ++}; ++ + struct nd_device_driver { + struct device_driver drv; + unsigned long type; +-- +2.35.3 + diff --git a/patches.suse/drivers-nvdimm-Add-perf-interface-to-expose-nvdimm-p.patch b/patches.suse/drivers-nvdimm-Add-perf-interface-to-expose-nvdimm-p.patch new file mode 100644 index 0000000..3248c62 --- /dev/null +++ b/patches.suse/drivers-nvdimm-Add-perf-interface-to-expose-nvdimm-p.patch @@ -0,0 +1,440 @@ +From 0fab1ba6ad6ba1f76380f92ead95c6e861ef8116 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Fri, 25 Feb 2022 20:00:22 +0530 +Subject: [PATCH] drivers/nvdimm: Add perf interface to expose nvdimm + performance stats + +References: jsc#PED-1925 +Patch-mainline: v5.18-rc1 +Git-commit: 0fab1ba6ad6ba1f76380f92ead95c6e861ef8116 + +A common interface is added to get performance stats reporting +support for nvdimm devices. Added interface defines supported +event list, config fields for the event attributes and their +corresponding bit values which are exported via sysfs. + +Interface also added support for pmu register/unregister functions, +cpu hotplug feature along with macros for handling events addition +via sysfs. It adds attribute groups for format, cpumask and events +to the pmu structure. + +User could use the standard perf tool to access perf events exposed +via nvdimm pmu. + +[Declare pmu functions in nd.h file to resolve implicit-function-declaration +warning and make hotplug function static as reported by kernel test robot] + +Acked-by: Peter Zijlstra (Intel) +Tested-by: Nageswara R Sastry +Signed-off-by: Kajol Jain +Link: https://lore.kernel.org/all/202202241242.zqzGkguy-lkp@intel.com/ +Reported-by: kernel test robot +Reviewed-by: Madhavan Srinivasan +Link: https://lore.kernel.org/r/20220225143024.47947-3-kjain@linux.ibm.com +Signed-off-by: Dan Williams +Acked-by: Michal Suchanek +--- + drivers/nvdimm/Makefile | 1 + + drivers/nvdimm/nd_perf.c | 328 +++++++++++++++++++++++++++++++++++++++ + include/linux/nd.h | 24 +++ + 3 files changed, 353 insertions(+) + create mode 100644 drivers/nvdimm/nd_perf.c + +diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile +index 29203f3d3069..25dba6095612 100644 +--- a/drivers/nvdimm/Makefile ++++ b/drivers/nvdimm/Makefile +@@ -18,6 +18,7 @@ nd_e820-y := e820.o + libnvdimm-y := core.o + libnvdimm-y += bus.o + libnvdimm-y += dimm_devs.o ++libnvdimm-y += nd_perf.o + libnvdimm-y += dimm.o + libnvdimm-y += region_devs.o + libnvdimm-y += region.o +diff --git a/drivers/nvdimm/nd_perf.c b/drivers/nvdimm/nd_perf.c +new file mode 100644 +index 000000000000..314415894acf +--- /dev/null ++++ b/drivers/nvdimm/nd_perf.c +@@ -0,0 +1,328 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * nd_perf.c: NVDIMM Device Performance Monitoring Unit support ++ * ++ * Perf interface to expose nvdimm performance stats. ++ * ++ * Copyright (C) 2021 IBM Corporation ++ */ ++ ++#define pr_fmt(fmt) "nvdimm_pmu: " fmt ++ ++#include ++ ++#define EVENT(_name, _code) enum{_name = _code} ++ ++/* ++ * NVDIMM Events codes. ++ */ ++ ++/* Controller Reset Count */ ++EVENT(CTL_RES_CNT, 0x1); ++/* Controller Reset Elapsed Time */ ++EVENT(CTL_RES_TM, 0x2); ++/* Power-on Seconds */ ++EVENT(POWERON_SECS, 0x3); ++/* Life Remaining */ ++EVENT(MEM_LIFE, 0x4); ++/* Critical Resource Utilization */ ++EVENT(CRI_RES_UTIL, 0x5); ++/* Host Load Count */ ++EVENT(HOST_L_CNT, 0x6); ++/* Host Store Count */ ++EVENT(HOST_S_CNT, 0x7); ++/* Host Store Duration */ ++EVENT(HOST_S_DUR, 0x8); ++/* Host Load Duration */ ++EVENT(HOST_L_DUR, 0x9); ++/* Media Read Count */ ++EVENT(MED_R_CNT, 0xa); ++/* Media Write Count */ ++EVENT(MED_W_CNT, 0xb); ++/* Media Read Duration */ ++EVENT(MED_R_DUR, 0xc); ++/* Media Write Duration */ ++EVENT(MED_W_DUR, 0xd); ++/* Cache Read Hit Count */ ++EVENT(CACHE_RH_CNT, 0xe); ++/* Cache Write Hit Count */ ++EVENT(CACHE_WH_CNT, 0xf); ++/* Fast Write Count */ ++EVENT(FAST_W_CNT, 0x10); ++ ++NVDIMM_EVENT_ATTR(ctl_res_cnt, CTL_RES_CNT); ++NVDIMM_EVENT_ATTR(ctl_res_tm, CTL_RES_TM); ++NVDIMM_EVENT_ATTR(poweron_secs, POWERON_SECS); ++NVDIMM_EVENT_ATTR(mem_life, MEM_LIFE); ++NVDIMM_EVENT_ATTR(cri_res_util, CRI_RES_UTIL); ++NVDIMM_EVENT_ATTR(host_l_cnt, HOST_L_CNT); ++NVDIMM_EVENT_ATTR(host_s_cnt, HOST_S_CNT); ++NVDIMM_EVENT_ATTR(host_s_dur, HOST_S_DUR); ++NVDIMM_EVENT_ATTR(host_l_dur, HOST_L_DUR); ++NVDIMM_EVENT_ATTR(med_r_cnt, MED_R_CNT); ++NVDIMM_EVENT_ATTR(med_w_cnt, MED_W_CNT); ++NVDIMM_EVENT_ATTR(med_r_dur, MED_R_DUR); ++NVDIMM_EVENT_ATTR(med_w_dur, MED_W_DUR); ++NVDIMM_EVENT_ATTR(cache_rh_cnt, CACHE_RH_CNT); ++NVDIMM_EVENT_ATTR(cache_wh_cnt, CACHE_WH_CNT); ++NVDIMM_EVENT_ATTR(fast_w_cnt, FAST_W_CNT); ++ ++static struct attribute *nvdimm_events_attr[] = { ++ NVDIMM_EVENT_PTR(CTL_RES_CNT), ++ NVDIMM_EVENT_PTR(CTL_RES_TM), ++ NVDIMM_EVENT_PTR(POWERON_SECS), ++ NVDIMM_EVENT_PTR(MEM_LIFE), ++ NVDIMM_EVENT_PTR(CRI_RES_UTIL), ++ NVDIMM_EVENT_PTR(HOST_L_CNT), ++ NVDIMM_EVENT_PTR(HOST_S_CNT), ++ NVDIMM_EVENT_PTR(HOST_S_DUR), ++ NVDIMM_EVENT_PTR(HOST_L_DUR), ++ NVDIMM_EVENT_PTR(MED_R_CNT), ++ NVDIMM_EVENT_PTR(MED_W_CNT), ++ NVDIMM_EVENT_PTR(MED_R_DUR), ++ NVDIMM_EVENT_PTR(MED_W_DUR), ++ NVDIMM_EVENT_PTR(CACHE_RH_CNT), ++ NVDIMM_EVENT_PTR(CACHE_WH_CNT), ++ NVDIMM_EVENT_PTR(FAST_W_CNT), ++ NULL ++}; ++ ++static struct attribute_group nvdimm_pmu_events_group = { ++ .name = "events", ++ .attrs = nvdimm_events_attr, ++}; ++ ++PMU_FORMAT_ATTR(event, "config:0-4"); ++ ++static struct attribute *nvdimm_pmu_format_attr[] = { ++ &format_attr_event.attr, ++ NULL, ++}; ++ ++static struct attribute_group nvdimm_pmu_format_group = { ++ .name = "format", ++ .attrs = nvdimm_pmu_format_attr, ++}; ++ ++ssize_t nvdimm_events_sysfs_show(struct device *dev, ++ struct device_attribute *attr, char *page) ++{ ++ struct perf_pmu_events_attr *pmu_attr; ++ ++ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); ++ ++ return sprintf(page, "event=0x%02llx\n", pmu_attr->id); ++} ++ ++static ssize_t nvdimm_pmu_cpumask_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct pmu *pmu = dev_get_drvdata(dev); ++ struct nvdimm_pmu *nd_pmu; ++ ++ nd_pmu = container_of(pmu, struct nvdimm_pmu, pmu); ++ ++ return cpumap_print_to_pagebuf(true, buf, cpumask_of(nd_pmu->cpu)); ++} ++ ++static int nvdimm_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node) ++{ ++ struct nvdimm_pmu *nd_pmu; ++ u32 target; ++ int nodeid; ++ const struct cpumask *cpumask; ++ ++ nd_pmu = hlist_entry_safe(node, struct nvdimm_pmu, node); ++ ++ /* Clear it, incase given cpu is set in nd_pmu->arch_cpumask */ ++ cpumask_test_and_clear_cpu(cpu, &nd_pmu->arch_cpumask); ++ ++ /* ++ * If given cpu is not same as current designated cpu for ++ * counter access, just return. ++ */ ++ if (cpu != nd_pmu->cpu) ++ return 0; ++ ++ /* Check for any active cpu in nd_pmu->arch_cpumask */ ++ target = cpumask_any(&nd_pmu->arch_cpumask); ++ ++ /* ++ * Incase we don't have any active cpu in nd_pmu->arch_cpumask, ++ * check in given cpu's numa node list. ++ */ ++ if (target >= nr_cpu_ids) { ++ nodeid = cpu_to_node(cpu); ++ cpumask = cpumask_of_node(nodeid); ++ target = cpumask_any_but(cpumask, cpu); ++ } ++ nd_pmu->cpu = target; ++ ++ /* Migrate nvdimm pmu events to the new target cpu if valid */ ++ if (target >= 0 && target < nr_cpu_ids) ++ perf_pmu_migrate_context(&nd_pmu->pmu, cpu, target); ++ ++ return 0; ++} ++ ++static int nvdimm_pmu_cpu_online(unsigned int cpu, struct hlist_node *node) ++{ ++ struct nvdimm_pmu *nd_pmu; ++ ++ nd_pmu = hlist_entry_safe(node, struct nvdimm_pmu, node); ++ ++ if (nd_pmu->cpu >= nr_cpu_ids) ++ nd_pmu->cpu = cpu; ++ ++ return 0; ++} ++ ++static int create_cpumask_attr_group(struct nvdimm_pmu *nd_pmu) ++{ ++ struct perf_pmu_events_attr *pmu_events_attr; ++ struct attribute **attrs_group; ++ struct attribute_group *nvdimm_pmu_cpumask_group; ++ ++ pmu_events_attr = kzalloc(sizeof(*pmu_events_attr), GFP_KERNEL); ++ if (!pmu_events_attr) ++ return -ENOMEM; ++ ++ attrs_group = kzalloc(2 * sizeof(struct attribute *), GFP_KERNEL); ++ if (!attrs_group) { ++ kfree(pmu_events_attr); ++ return -ENOMEM; ++ } ++ ++ /* Allocate memory for cpumask attribute group */ ++ nvdimm_pmu_cpumask_group = kzalloc(sizeof(*nvdimm_pmu_cpumask_group), GFP_KERNEL); ++ if (!nvdimm_pmu_cpumask_group) { ++ kfree(pmu_events_attr); ++ kfree(attrs_group); ++ return -ENOMEM; ++ } ++ ++ sysfs_attr_init(&pmu_events_attr->attr.attr); ++ pmu_events_attr->attr.attr.name = "cpumask"; ++ pmu_events_attr->attr.attr.mode = 0444; ++ pmu_events_attr->attr.show = nvdimm_pmu_cpumask_show; ++ attrs_group[0] = &pmu_events_attr->attr.attr; ++ attrs_group[1] = NULL; ++ ++ nvdimm_pmu_cpumask_group->attrs = attrs_group; ++ nd_pmu->pmu.attr_groups[NVDIMM_PMU_CPUMASK_ATTR] = nvdimm_pmu_cpumask_group; ++ return 0; ++} ++ ++static int nvdimm_pmu_cpu_hotplug_init(struct nvdimm_pmu *nd_pmu) ++{ ++ int nodeid, rc; ++ const struct cpumask *cpumask; ++ ++ /* ++ * Incase of cpu hotplug feature, arch specific code ++ * can provide required cpumask which can be used ++ * to get designatd cpu for counter access. ++ * Check for any active cpu in nd_pmu->arch_cpumask. ++ */ ++ if (!cpumask_empty(&nd_pmu->arch_cpumask)) { ++ nd_pmu->cpu = cpumask_any(&nd_pmu->arch_cpumask); ++ } else { ++ /* pick active cpu from the cpumask of device numa node. */ ++ nodeid = dev_to_node(nd_pmu->dev); ++ cpumask = cpumask_of_node(nodeid); ++ nd_pmu->cpu = cpumask_any(cpumask); ++ } ++ ++ rc = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/nvdimm:online", ++ nvdimm_pmu_cpu_online, nvdimm_pmu_cpu_offline); ++ ++ if (rc < 0) ++ return rc; ++ ++ nd_pmu->cpuhp_state = rc; ++ ++ /* Register the pmu instance for cpu hotplug */ ++ rc = cpuhp_state_add_instance_nocalls(nd_pmu->cpuhp_state, &nd_pmu->node); ++ if (rc) { ++ cpuhp_remove_multi_state(nd_pmu->cpuhp_state); ++ return rc; ++ } ++ ++ /* Create cpumask attribute group */ ++ rc = create_cpumask_attr_group(nd_pmu); ++ if (rc) { ++ cpuhp_state_remove_instance_nocalls(nd_pmu->cpuhp_state, &nd_pmu->node); ++ cpuhp_remove_multi_state(nd_pmu->cpuhp_state); ++ return rc; ++ } ++ ++ return 0; ++} ++ ++static void nvdimm_pmu_free_hotplug_memory(struct nvdimm_pmu *nd_pmu) ++{ ++ cpuhp_state_remove_instance_nocalls(nd_pmu->cpuhp_state, &nd_pmu->node); ++ cpuhp_remove_multi_state(nd_pmu->cpuhp_state); ++ ++ if (nd_pmu->pmu.attr_groups[NVDIMM_PMU_CPUMASK_ATTR]) ++ kfree(nd_pmu->pmu.attr_groups[NVDIMM_PMU_CPUMASK_ATTR]->attrs); ++ kfree(nd_pmu->pmu.attr_groups[NVDIMM_PMU_CPUMASK_ATTR]); ++} ++ ++int register_nvdimm_pmu(struct nvdimm_pmu *nd_pmu, struct platform_device *pdev) ++{ ++ int rc; ++ ++ if (!nd_pmu || !pdev) ++ return -EINVAL; ++ ++ /* event functions like add/del/read/event_init and pmu name should not be NULL */ ++ if (WARN_ON_ONCE(!(nd_pmu->pmu.event_init && nd_pmu->pmu.add && ++ nd_pmu->pmu.del && nd_pmu->pmu.read && nd_pmu->pmu.name))) ++ return -EINVAL; ++ ++ nd_pmu->pmu.attr_groups = kzalloc((NVDIMM_PMU_NULL_ATTR + 1) * ++ sizeof(struct attribute_group *), GFP_KERNEL); ++ if (!nd_pmu->pmu.attr_groups) ++ return -ENOMEM; ++ ++ /* ++ * Add platform_device->dev pointer to nvdimm_pmu to access ++ * device data in events functions. ++ */ ++ nd_pmu->dev = &pdev->dev; ++ ++ /* Fill attribute groups for the nvdimm pmu device */ ++ nd_pmu->pmu.attr_groups[NVDIMM_PMU_FORMAT_ATTR] = &nvdimm_pmu_format_group; ++ nd_pmu->pmu.attr_groups[NVDIMM_PMU_EVENT_ATTR] = &nvdimm_pmu_events_group; ++ nd_pmu->pmu.attr_groups[NVDIMM_PMU_NULL_ATTR] = NULL; ++ ++ /* Fill attribute group for cpumask */ ++ rc = nvdimm_pmu_cpu_hotplug_init(nd_pmu); ++ if (rc) { ++ pr_info("cpu hotplug feature failed for device: %s\n", nd_pmu->pmu.name); ++ kfree(nd_pmu->pmu.attr_groups); ++ return rc; ++ } ++ ++ rc = perf_pmu_register(&nd_pmu->pmu, nd_pmu->pmu.name, -1); ++ if (rc) { ++ kfree(nd_pmu->pmu.attr_groups); ++ nvdimm_pmu_free_hotplug_memory(nd_pmu); ++ return rc; ++ } ++ ++ pr_info("%s NVDIMM performance monitor support registered\n", ++ nd_pmu->pmu.name); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(register_nvdimm_pmu); ++ ++void unregister_nvdimm_pmu(struct nvdimm_pmu *nd_pmu) ++{ ++ perf_pmu_unregister(&nd_pmu->pmu); ++ nvdimm_pmu_free_hotplug_memory(nd_pmu); ++ kfree(nd_pmu); ++} ++EXPORT_SYMBOL_GPL(unregister_nvdimm_pmu); +diff --git a/include/linux/nd.h b/include/linux/nd.h +index ad186e828263..4813c7089e5c 100644 +--- a/include/linux/nd.h ++++ b/include/linux/nd.h +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + enum nvdimm_event { + NVDIMM_REVALIDATE_POISON, +@@ -24,6 +25,19 @@ enum nvdimm_claim_class { + NVDIMM_CCLASS_UNKNOWN, + }; + ++#define NVDIMM_EVENT_VAR(_id) event_attr_##_id ++#define NVDIMM_EVENT_PTR(_id) (&event_attr_##_id.attr.attr) ++ ++#define NVDIMM_EVENT_ATTR(_name, _id) \ ++ PMU_EVENT_ATTR(_name, NVDIMM_EVENT_VAR(_id), _id, \ ++ nvdimm_events_sysfs_show) ++ ++/* Event attribute array index */ ++#define NVDIMM_PMU_FORMAT_ATTR 0 ++#define NVDIMM_PMU_EVENT_ATTR 1 ++#define NVDIMM_PMU_CPUMASK_ATTR 2 ++#define NVDIMM_PMU_NULL_ATTR 3 ++ + /** + * struct nvdimm_pmu - data structure for nvdimm perf driver + * @pmu: pmu data structure for nvdimm performance stats. +@@ -43,6 +57,16 @@ struct nvdimm_pmu { + struct cpumask arch_cpumask; + }; + ++extern ssize_t nvdimm_events_sysfs_show(struct device *dev, ++ struct device_attribute *attr, ++ char *page); ++ ++int register_nvdimm_pmu(struct nvdimm_pmu *nvdimm, struct platform_device *pdev); ++void unregister_nvdimm_pmu(struct nvdimm_pmu *nd_pmu); ++void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu); ++int perf_pmu_register(struct pmu *pmu, const char *name, int type); ++void perf_pmu_unregister(struct pmu *pmu); ++ + struct nd_device_driver { + struct device_driver drv; + unsigned long type; +-- +2.35.3 + diff --git a/patches.suse/drivers-nvdimm-Fix-build-failure-when-CONFIG_PERF_EV.patch b/patches.suse/drivers-nvdimm-Fix-build-failure-when-CONFIG_PERF_EV.patch new file mode 100644 index 0000000..8de73f4 --- /dev/null +++ b/patches.suse/drivers-nvdimm-Fix-build-failure-when-CONFIG_PERF_EV.patch @@ -0,0 +1,118 @@ +From de7a9e949f4f094741f708cd05572f932d009d02 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Wed, 23 Mar 2022 22:15:49 +0530 +Subject: [PATCH] drivers/nvdimm: Fix build failure when CONFIG_PERF_EVENTS is + not set + +References: jsc#PED-1925 +Patch-mainline: v5.18-rc1 +Git-commit: de7a9e949f4f094741f708cd05572f932d009d02 + +The following build failure occurs when CONFIG_PERF_EVENTS is not set +as generic pmu functions are not visible in that scenario. + +|-- s390-randconfig-r044-20220313 +| |-- nd_perf.c:(.text):undefined-reference-to-perf_pmu_migrate_context +| |-- nd_perf.c:(.text):undefined-reference-to-perf_pmu_register +| `-- nd_perf.c:(.text):undefined-reference-to-perf_pmu_unregister + +Similar build failure in nds32 architecture: +nd_perf.c:(.text+0x21e): undefined reference to `perf_pmu_migrate_context' +nd_perf.c:(.text+0x434): undefined reference to `perf_pmu_register' +nd_perf.c:(.text+0x57c): undefined reference to `perf_pmu_unregister' + +Fix this issue by adding check for CONFIG_PERF_EVENTS config option +and disabling the nvdimm perf interface incase this config is not set. + +Also remove function declaration of perf_pmu_migrate_context, +perf_pmu_register, perf_pmu_unregister functions from nd.h as these are +common pmu functions which are part of perf_event.h and since we +are disabling nvdimm perf interface incase CONFIG_PERF_EVENTS option +is not set, we not need to declare them in nd.h + +Also move the platform_device header file addition part from nd.h to +nd_perf.c and add stub functions for register_nvdimm_pmu and +unregister_nvdimm_pmu functions to handle CONFIG_PERF_EVENTS=n +case. + +Fixes: 0fab1ba6ad6b ("drivers/nvdimm: Add perf interface to expose nvdimm performance stats") (Commit id based on libnvdimm-for-next tree) +Signed-off-by: Kajol Jain +Link: https://lore.kernel.org/all/62317124.YBQFU33+s%2FwdvWGj%25lkp@intel.com/ +Reported-by: kernel test robot +Link: https://lore.kernel.org/r/20220323164550.109768-1-kjain@linux.ibm.com +Signed-off-by: Dan Williams +Acked-by: Michal Suchanek +--- + drivers/nvdimm/Makefile | 2 +- + drivers/nvdimm/nd_perf.c | 1 + + include/linux/nd.h | 16 ++++++++++++---- + 3 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile +index 3fb806748716..ba0296dca9db 100644 +--- a/drivers/nvdimm/Makefile ++++ b/drivers/nvdimm/Makefile +@@ -15,7 +15,7 @@ nd_e820-y := e820.o + libnvdimm-y := core.o + libnvdimm-y += bus.o + libnvdimm-y += dimm_devs.o +-libnvdimm-y += nd_perf.o ++libnvdimm-$(CONFIG_PERF_EVENTS) += nd_perf.o + libnvdimm-y += dimm.o + libnvdimm-y += region_devs.o + libnvdimm-y += region.o +diff --git a/drivers/nvdimm/nd_perf.c b/drivers/nvdimm/nd_perf.c +index 314415894acf..433bbb68ae64 100644 +--- a/drivers/nvdimm/nd_perf.c ++++ b/drivers/nvdimm/nd_perf.c +@@ -10,6 +10,7 @@ + #define pr_fmt(fmt) "nvdimm_pmu: " fmt + + #include ++#include + + #define EVENT(_name, _code) enum{_name = _code} + +diff --git a/include/linux/nd.h b/include/linux/nd.h +index 7b2ccbdc1cbc..b9771ba1ef87 100644 +--- a/include/linux/nd.h ++++ b/include/linux/nd.h +@@ -9,7 +9,6 @@ + #include + #include + #include +-#include + + enum nvdimm_event { + NVDIMM_REVALIDATE_POISON, +@@ -57,15 +56,24 @@ struct nvdimm_pmu { + struct cpumask arch_cpumask; + }; + ++struct platform_device; ++ ++#ifdef CONFIG_PERF_EVENTS + extern ssize_t nvdimm_events_sysfs_show(struct device *dev, + struct device_attribute *attr, + char *page); + + int register_nvdimm_pmu(struct nvdimm_pmu *nvdimm, struct platform_device *pdev); + void unregister_nvdimm_pmu(struct nvdimm_pmu *nd_pmu); +-void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu); +-int perf_pmu_register(struct pmu *pmu, const char *name, int type); +-void perf_pmu_unregister(struct pmu *pmu); ++ ++#else ++static inline int register_nvdimm_pmu(struct nvdimm_pmu *nvdimm, struct platform_device *pdev) ++{ ++ return -ENXIO; ++} ++ ++static inline void unregister_nvdimm_pmu(struct nvdimm_pmu *nd_pmu) { } ++#endif + + struct nd_device_driver { + struct device_driver drv; +-- +2.35.3 + diff --git a/patches.suse/efi-Introduce-EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.patch b/patches.suse/efi-Introduce-EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.patch new file mode 100644 index 0000000..fe02d32 --- /dev/null +++ b/patches.suse/efi-Introduce-EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.patch @@ -0,0 +1,97 @@ +From: Chen Yu +Date: Wed, 22 Dec 2021 12:31:03 +0800 +Subject: efi: Introduce EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and + corresponding structures +Patch-mainline: v5.17-rc1 +Git-commit: 1882de7fc56c2b0ea91dd9fd9922d434fc3feb15 +References: jsc#PED-1408 + +Platform Firmware Runtime Update image starts with UEFI headers, and the +headers are defined in UEFI specification, but some of them have not been +defined in the kernel yet. + +For example, the header layout of a capsule file looks like this: + +EFI_CAPSULE_HEADER +EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER +EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER +EFI_FIRMWARE_IMAGE_AUTHENTICATION + +These structures would be used by the Platform Firmware Runtime Update +driver to parse the format of capsule file to verify if the corresponding +version number is valid. In this way, if the user provides an invalid +capsule image, the kernel could be used as a guard to reject it, without +switching to the Management Mode (which might be costly). + +EFI_CAPSULE_HEADER has been defined in the kernel, but the other +structures have not been defined yet, so do that. Besides, +EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and +EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are required to be packed +in the uefi specification. For this reason, use the __packed attribute +to indicate to the compiler that the entire structure can appear +misaligned in memory (as suggested by Ard) in case one of them follows +the other directly in a capsule header. + +Acked-by: Ard Biesheuvel +Signed-off-by: Chen Yu +Signed-off-by: Rafael J. Wysocki +Acked-by: Lee, Chun-Yi +--- + include/linux/efi.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -148,6 +148,52 @@ typedef struct { + u32 imagesize; + } efi_capsule_header_t; + ++/* EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER */ ++struct efi_manage_capsule_header { ++ u32 ver; ++ u16 emb_drv_cnt; ++ u16 payload_cnt; ++ /* ++ * Variable-size array of the size given by the sum of ++ * emb_drv_cnt and payload_cnt. ++ */ ++ u64 offset_list[]; ++} __packed; ++ ++/* EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER */ ++struct efi_manage_capsule_image_header { ++ u32 ver; ++ efi_guid_t image_type_id; ++ u8 image_index; ++ u8 reserved_bytes[3]; ++ u32 image_size; ++ u32 vendor_code_size; ++ /* hw_ins was introduced in version 2 */ ++ u64 hw_ins; ++ /* capsule_support was introduced in version 3 */ ++ u64 capsule_support; ++} __packed; ++ ++/* WIN_CERTIFICATE */ ++struct win_cert { ++ u32 len; ++ u16 rev; ++ u16 cert_type; ++}; ++ ++/* WIN_CERTIFICATE_UEFI_GUID */ ++struct win_cert_uefi_guid { ++ struct win_cert hdr; ++ efi_guid_t cert_type; ++ u8 cert_data[]; ++}; ++ ++/* EFI_FIRMWARE_IMAGE_AUTHENTICATION */ ++struct efi_image_auth { ++ u64 mon_count; ++ struct win_cert_uefi_guid auth_info; ++}; ++ + /* + * EFI capsule flags + */ diff --git a/patches.suse/media-i2c-ov2640-Depend-on-V4L2_ASYNC.patch b/patches.suse/media-i2c-ov2640-Depend-on-V4L2_ASYNC.patch new file mode 100644 index 0000000..b19df7c --- /dev/null +++ b/patches.suse/media-i2c-ov2640-Depend-on-V4L2_ASYNC.patch @@ -0,0 +1,30 @@ +From 8429b358975f11574f747ca8ef20d524d8247682 Mon Sep 17 00:00:00 2001 +From: Mike Pagano +Date: Wed, 27 Apr 2022 23:59:23 +0200 +Subject: [PATCH] media: i2c: ov2640: Depend on V4L2_ASYNC +Git-commit: 8429b358975f11574f747ca8ef20d524d8247682 +References: git-fixes +Patch-mainline: v5.19-rc1 + +Add V4L2_ASYNC as a dependency to match other drivers and prevent failures +when compile testing. + +Fixes: ff3cc65cadb5 ("media: v4l: async, fwnode: Improve module organisation") +Signed-off-by: Mike Pagano +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Oliver Neukum +--- + drivers/media/i2c/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -871,6 +871,7 @@ config VIDEO_OV02A10 + config VIDEO_OV2640 + tristate "OmniVision OV2640 sensor support" + depends on VIDEO_V4L2 && I2C ++ select V4L2_ASYNC + help + This is a Video4Linux2 sensor driver for the OmniVision + OV2640 camera. diff --git a/patches.suse/powerpc-papr_scm-Add-perf-interface-support.patch b/patches.suse/powerpc-papr_scm-Add-perf-interface-support.patch new file mode 100644 index 0000000..c597fca --- /dev/null +++ b/patches.suse/powerpc-papr_scm-Add-perf-interface-support.patch @@ -0,0 +1,352 @@ +From 4c08d4bbc089a95f3f38389c2b79dbc6ab24f10b Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Fri, 25 Feb 2022 20:00:23 +0530 +Subject: [PATCH] powerpc/papr_scm: Add perf interface support + +References: jsc#PED-1925 +Patch-mainline: v5.18-rc1 +Git-commit: 4c08d4bbc089a95f3f38389c2b79dbc6ab24f10b + +Performance monitoring support for papr-scm nvdimm devices +via perf interface is added which includes addition of pmu +functions like add/del/read/event_init for nvdimm_pmu struture. + +A new parameter 'priv' in added to the pdev_archdata structure to save +nvdimm_pmu device pointer, to handle the unregistering of pmu device. + +papr_scm_pmu_register function populates the nvdimm_pmu structure +with name, capabilities, cpumask along with event handling +functions. Finally the populated nvdimm_pmu structure is passed to +register the pmu device. Event handling functions internally uses +hcall to get events and counter data. + +Result in power9 machine with 2 nvdimm device: + +Ex: List all event by perf list + +command:# perf list nmem + + nmem0/cache_rh_cnt/ [Kernel PMU event] + nmem0/cache_wh_cnt/ [Kernel PMU event] + nmem0/cri_res_util/ [Kernel PMU event] + nmem0/ctl_res_cnt/ [Kernel PMU event] + nmem0/ctl_res_tm/ [Kernel PMU event] + nmem0/fast_w_cnt/ [Kernel PMU event] + nmem0/host_l_cnt/ [Kernel PMU event] + nmem0/host_l_dur/ [Kernel PMU event] + nmem0/host_s_cnt/ [Kernel PMU event] + nmem0/host_s_dur/ [Kernel PMU event] + nmem0/med_r_cnt/ [Kernel PMU event] + nmem0/med_r_dur/ [Kernel PMU event] + nmem0/med_w_cnt/ [Kernel PMU event] + nmem0/med_w_dur/ [Kernel PMU event] + nmem0/mem_life/ [Kernel PMU event] + nmem0/poweron_secs/ [Kernel PMU event] + ... + nmem1/mem_life/ [Kernel PMU event] + nmem1/poweron_secs/ [Kernel PMU event] + +Acked-by: Peter Zijlstra (Intel) +Tested-by: Nageswara R Sastry +Signed-off-by: Kajol Jain +[Add numa_map_to_online_node function call to get online node id] +Reported-by: Nageswara R Sastry +Reviewed-by: Madhavan Srinivasan +Link: https://lore.kernel.org/r/20220225143024.47947-4-kjain@linux.ibm.com +Signed-off-by: Dan Williams +Acked-by: Michal Suchanek +--- + arch/powerpc/include/asm/device.h | 5 + + arch/powerpc/platforms/pseries/papr_scm.c | 225 ++++++++++++++++++++++ + 2 files changed, 230 insertions(+) + +diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h +index 219559d65864..47ed639f3b8f 100644 +--- a/arch/powerpc/include/asm/device.h ++++ b/arch/powerpc/include/asm/device.h +@@ -48,6 +48,11 @@ struct dev_archdata { + + struct pdev_archdata { + u64 dma_mask; ++ /* ++ * Pointer to nvdimm_pmu structure, to handle the unregistering ++ * of pmu device ++ */ ++ void *priv; + }; + + #endif /* _ASM_POWERPC_DEVICE_H */ +diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c +index f48e87ac89c9..4dd513d7c029 100644 +--- a/arch/powerpc/platforms/pseries/papr_scm.c ++++ b/arch/powerpc/platforms/pseries/papr_scm.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #define BIND_ANY_ADDR (~0ul) + +@@ -68,6 +69,8 @@ + #define PAPR_SCM_PERF_STATS_EYECATCHER __stringify(SCMSTATS) + #define PAPR_SCM_PERF_STATS_VERSION 0x1 + ++#define to_nvdimm_pmu(_pmu) container_of(_pmu, struct nvdimm_pmu, pmu) ++ + /* Struct holding a single performance metric */ + struct papr_scm_perf_stat { + u8 stat_id[8]; +@@ -120,6 +123,9 @@ struct papr_scm_priv { + + /* length of the stat buffer as expected by phyp */ + size_t stat_buffer_len; ++ ++ /* array to have event_code and stat_id mappings */ ++ char **nvdimm_events_map; + }; + + static int papr_scm_pmem_flush(struct nd_region *nd_region, +@@ -340,6 +346,218 @@ static ssize_t drc_pmem_query_stats(struct papr_scm_priv *p, + return 0; + } + ++static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, u64 *count) ++{ ++ struct papr_scm_perf_stat *stat; ++ struct papr_scm_perf_stats *stats; ++ struct papr_scm_priv *p = (struct papr_scm_priv *)dev->driver_data; ++ int rc, size; ++ ++ /* Allocate request buffer enough to hold single performance stat */ ++ size = sizeof(struct papr_scm_perf_stats) + ++ sizeof(struct papr_scm_perf_stat); ++ ++ if (!p || !p->nvdimm_events_map) ++ return -EINVAL; ++ ++ stats = kzalloc(size, GFP_KERNEL); ++ if (!stats) ++ return -ENOMEM; ++ ++ stat = &stats->scm_statistic[0]; ++ memcpy(&stat->stat_id, ++ p->nvdimm_events_map[event->attr.config], ++ sizeof(stat->stat_id)); ++ stat->stat_val = 0; ++ ++ rc = drc_pmem_query_stats(p, stats, 1); ++ if (rc < 0) { ++ kfree(stats); ++ return rc; ++ } ++ ++ *count = be64_to_cpu(stat->stat_val); ++ kfree(stats); ++ return 0; ++} ++ ++static int papr_scm_pmu_event_init(struct perf_event *event) ++{ ++ struct nvdimm_pmu *nd_pmu = to_nvdimm_pmu(event->pmu); ++ struct papr_scm_priv *p; ++ ++ if (!nd_pmu) ++ return -EINVAL; ++ ++ /* test the event attr type for PMU enumeration */ ++ if (event->attr.type != event->pmu->type) ++ return -ENOENT; ++ ++ /* it does not support event sampling mode */ ++ if (is_sampling_event(event)) ++ return -EOPNOTSUPP; ++ ++ /* no branch sampling */ ++ if (has_branch_stack(event)) ++ return -EOPNOTSUPP; ++ ++ p = (struct papr_scm_priv *)nd_pmu->dev->driver_data; ++ if (!p) ++ return -EINVAL; ++ ++ /* Invalid eventcode */ ++ if (event->attr.config == 0 || event->attr.config > 16) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int papr_scm_pmu_add(struct perf_event *event, int flags) ++{ ++ u64 count; ++ int rc; ++ struct nvdimm_pmu *nd_pmu = to_nvdimm_pmu(event->pmu); ++ ++ if (!nd_pmu) ++ return -EINVAL; ++ ++ if (flags & PERF_EF_START) { ++ rc = papr_scm_pmu_get_value(event, nd_pmu->dev, &count); ++ if (rc) ++ return rc; ++ ++ local64_set(&event->hw.prev_count, count); ++ } ++ ++ return 0; ++} ++ ++static void papr_scm_pmu_read(struct perf_event *event) ++{ ++ u64 prev, now; ++ int rc; ++ struct nvdimm_pmu *nd_pmu = to_nvdimm_pmu(event->pmu); ++ ++ if (!nd_pmu) ++ return; ++ ++ rc = papr_scm_pmu_get_value(event, nd_pmu->dev, &now); ++ if (rc) ++ return; ++ ++ prev = local64_xchg(&event->hw.prev_count, now); ++ local64_add(now - prev, &event->count); ++} ++ ++static void papr_scm_pmu_del(struct perf_event *event, int flags) ++{ ++ papr_scm_pmu_read(event); ++} ++ ++static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu *nd_pmu) ++{ ++ struct papr_scm_perf_stat *stat; ++ struct papr_scm_perf_stats *stats; ++ char *statid; ++ int index, rc, count; ++ u32 available_events; ++ ++ if (!p->stat_buffer_len) ++ return -ENOENT; ++ ++ available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats)) ++ / sizeof(struct papr_scm_perf_stat); ++ ++ /* Allocate the buffer for phyp where stats are written */ ++ stats = kzalloc(p->stat_buffer_len, GFP_KERNEL); ++ if (!stats) { ++ rc = -ENOMEM; ++ return rc; ++ } ++ ++ /* Allocate memory to nvdimm_event_map */ ++ p->nvdimm_events_map = kcalloc(available_events, sizeof(char *), GFP_KERNEL); ++ if (!p->nvdimm_events_map) { ++ rc = -ENOMEM; ++ goto out_stats; ++ } ++ ++ /* Called to get list of events supported */ ++ rc = drc_pmem_query_stats(p, stats, 0); ++ if (rc) ++ goto out_nvdimm_events_map; ++ ++ for (index = 0, stat = stats->scm_statistic, count = 0; ++ index < available_events; index++, ++stat) { ++ statid = kzalloc(strlen(stat->stat_id) + 1, GFP_KERNEL); ++ if (!statid) { ++ rc = -ENOMEM; ++ goto out_nvdimm_events_map; ++ } ++ ++ strcpy(statid, stat->stat_id); ++ p->nvdimm_events_map[count] = statid; ++ count++; ++ } ++ p->nvdimm_events_map[count] = NULL; ++ kfree(stats); ++ return 0; ++ ++out_nvdimm_events_map: ++ kfree(p->nvdimm_events_map); ++out_stats: ++ kfree(stats); ++ return rc; ++} ++ ++static void papr_scm_pmu_register(struct papr_scm_priv *p) ++{ ++ struct nvdimm_pmu *nd_pmu; ++ int rc, nodeid; ++ ++ nd_pmu = kzalloc(sizeof(*nd_pmu), GFP_KERNEL); ++ if (!nd_pmu) { ++ rc = -ENOMEM; ++ goto pmu_err_print; ++ } ++ ++ rc = papr_scm_pmu_check_events(p, nd_pmu); ++ if (rc) ++ goto pmu_check_events_err; ++ ++ nd_pmu->pmu.task_ctx_nr = perf_invalid_context; ++ nd_pmu->pmu.name = nvdimm_name(p->nvdimm); ++ nd_pmu->pmu.event_init = papr_scm_pmu_event_init; ++ nd_pmu->pmu.read = papr_scm_pmu_read; ++ nd_pmu->pmu.add = papr_scm_pmu_add; ++ nd_pmu->pmu.del = papr_scm_pmu_del; ++ ++ nd_pmu->pmu.capabilities = PERF_PMU_CAP_NO_INTERRUPT | ++ PERF_PMU_CAP_NO_EXCLUDE; ++ ++ /*updating the cpumask variable */ ++ nodeid = numa_map_to_online_node(dev_to_node(&p->pdev->dev)); ++ nd_pmu->arch_cpumask = *cpumask_of_node(nodeid); ++ ++ rc = register_nvdimm_pmu(nd_pmu, p->pdev); ++ if (rc) ++ goto pmu_register_err; ++ ++ /* ++ * Set archdata.priv value to nvdimm_pmu structure, to handle the ++ * unregistering of pmu device. ++ */ ++ p->pdev->archdata.priv = nd_pmu; ++ return; ++ ++pmu_register_err: ++ kfree(p->nvdimm_events_map); ++pmu_check_events_err: ++ kfree(nd_pmu); ++pmu_err_print: ++ dev_info(&p->pdev->dev, "nvdimm pmu didn't register rc=%d\n", rc); ++} ++ + /* + * Issue hcall to retrieve dimm health info and populate papr_scm_priv with the + * health information. +@@ -1236,6 +1454,7 @@ static int papr_scm_probe(struct platform_device *pdev) + goto err2; + + platform_set_drvdata(pdev, p); ++ papr_scm_pmu_register(p); + + return 0; + +@@ -1254,6 +1473,12 @@ static int papr_scm_remove(struct platform_device *pdev) + + nvdimm_bus_unregister(p->bus); + drc_pmem_unbind(p); ++ ++ if (pdev->archdata.priv) ++ unregister_nvdimm_pmu(pdev->archdata.priv); ++ ++ pdev->archdata.priv = NULL; ++ kfree(p->nvdimm_events_map); + kfree(p->bus_desc.provider_name); + kfree(p); + +-- +2.35.3 + diff --git a/patches.suse/powerpc-papr_scm-Ensure-rc-is-always-initialized-in-.patch b/patches.suse/powerpc-papr_scm-Ensure-rc-is-always-initialized-in-.patch new file mode 100644 index 0000000..26288ca --- /dev/null +++ b/patches.suse/powerpc-papr_scm-Ensure-rc-is-always-initialized-in-.patch @@ -0,0 +1,67 @@ +From 6cf07810e9ef8535d60160d13bf0fd05f2af38e7 Mon Sep 17 00:00:00 2001 +From: Nathan Chancellor +Date: Tue, 30 Aug 2022 08:12:56 -0700 +Subject: [PATCH] powerpc/papr_scm: Ensure rc is always initialized in + papr_scm_pmu_register() + +References: jsc#PED-1925 +Patch-mainline: v6.0-rc4 +Git-commit: 6cf07810e9ef8535d60160d13bf0fd05f2af38e7 + +Clang warns: + + arch/powerpc/platforms/pseries/papr_scm.c:492:6: warning: variable 'rc' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized] + if (!p->stat_buffer_len) + ^~~~~~~~~~~~~~~~~~~ + arch/powerpc/platforms/pseries/papr_scm.c:523:64: note: uninitialized use occurs here + dev_info(&p->pdev->dev, "nvdimm pmu didn't register rc=%d\n", rc); + ^~ + include/linux/dev_printk.h:150:67: note: expanded from macro 'dev_info' + dev_printk_index_wrap(_dev_info, KERN_INFO, dev, dev_fmt(fmt), ##__VA_ARGS__) + ^~~~~~~~~~~ + include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap' + _p_func(dev, fmt, ##__VA_ARGS__); \ + ^~~~~~~~~~~ + arch/powerpc/platforms/pseries/papr_scm.c:492:2: note: remove the 'if' if its condition is always false + if (!p->stat_buffer_len) + ^~~~~~~~~~~~~~~~~~~~~~~~ + arch/powerpc/platforms/pseries/papr_scm.c:484:8: note: initialize the variable 'rc' to silence this warning + int rc, nodeid; + ^ + = 0 + 1 warning generated. + +The call to papr_scm_pmu_check_events() was eliminated but a return code +was not added to the if statement. Add the same return code from +papr_scm_pmu_check_events() for this condition so there is no more +warning. + +Fixes: 9b1ac04698a4 ("powerpc/papr_scm: Fix nvdimm event mappings") +Signed-off-by: Nathan Chancellor +Signed-off-by: Michael Ellerman +Link: https://github.com/ClangBuiltLinux/linux/issues/1701 +Link: https://lore.kernel.org/r/20220830151256.1473169-1-nathan@kernel.org +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/papr_scm.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c +index 54740af21557..2f8385523a13 100644 +--- a/arch/powerpc/platforms/pseries/papr_scm.c ++++ b/arch/powerpc/platforms/pseries/papr_scm.c +@@ -489,8 +489,10 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p) + goto pmu_err_print; + } + +- if (!p->stat_buffer_len) ++ if (!p->stat_buffer_len) { ++ rc = -ENOENT; + goto pmu_check_events_err; ++ } + + nd_pmu->pmu.task_ctx_nr = perf_invalid_context; + nd_pmu->pmu.name = nvdimm_name(p->nvdimm); +-- +2.35.3 + diff --git a/patches.suse/powerpc-papr_scm-Fix-buffer-overflow-issue-with-CONF.patch b/patches.suse/powerpc-papr_scm-Fix-buffer-overflow-issue-with-CONF.patch new file mode 100644 index 0000000..f7280d1 --- /dev/null +++ b/patches.suse/powerpc-papr_scm-Fix-buffer-overflow-issue-with-CONF.patch @@ -0,0 +1,80 @@ +From 348c71344111d7a48892e3e52264ff11956fc196 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Thu, 5 May 2022 21:04:51 +0530 +Subject: [PATCH] powerpc/papr_scm: Fix buffer overflow issue with + CONFIG_FORTIFY_SOURCE + +References: jsc#PED-1925 +Patch-mainline: v5.18-rc6 +Git-commit: 348c71344111d7a48892e3e52264ff11956fc196 + +With CONFIG_FORTIFY_SOURCE enabled, string functions will also perform +dynamic checks for string size which can panic the kernel, like incase +of overflow detection. + +In papr_scm, papr_scm_pmu_check_events function uses stat->stat_id with +string operations, to populate the nvdimm_events_map array. Since +stat_id variable is not NULL terminated, the kernel panics with +CONFIG_FORTIFY_SOURCE enabled at boot time. + +Below are the logs of kernel panic: + + detected buffer overflow in __fortify_strlen + ------------[ cut here ]------------ + kernel BUG at lib/string_helpers.c:980! + Oops: Exception in kernel mode, sig: 5 [#1] + NIP [c00000000077dad0] fortify_panic+0x28/0x38 + LR [c00000000077dacc] fortify_panic+0x24/0x38 + Call Trace: + [c0000022d77836e0] [c00000000077dacc] fortify_panic+0x24/0x38 (unreliable) + [c00800000deb2660] papr_scm_pmu_check_events.constprop.0+0x118/0x220 [papr_scm] + [c00800000deb2cb0] papr_scm_probe+0x288/0x62c [papr_scm] + [c0000000009b46a8] platform_probe+0x98/0x150 + +Fix this issue by using kmemdup_nul() to copy the content of +stat->stat_id directly to the nvdimm_events_map array. + +mpe: stat->stat_id comes from the hypervisor, not userspace, so there is +no security exposure. + +Fixes: 4c08d4bbc089 ("powerpc/papr_scm: Add perf interface support") +Signed-off-by: Kajol Jain +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220505153451.35503-1-kjain@linux.ibm.com +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/papr_scm.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c +index f58728d5f10d..39962c905542 100644 +--- a/arch/powerpc/platforms/pseries/papr_scm.c ++++ b/arch/powerpc/platforms/pseries/papr_scm.c +@@ -462,7 +462,6 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu + { + struct papr_scm_perf_stat *stat; + struct papr_scm_perf_stats *stats; +- char *statid; + int index, rc, count; + u32 available_events; + +@@ -493,14 +492,12 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu + + for (index = 0, stat = stats->scm_statistic, count = 0; + index < available_events; index++, ++stat) { +- statid = kzalloc(strlen(stat->stat_id) + 1, GFP_KERNEL); +- if (!statid) { ++ p->nvdimm_events_map[count] = kmemdup_nul(stat->stat_id, 8, GFP_KERNEL); ++ if (!p->nvdimm_events_map[count]) { + rc = -ENOMEM; + goto out_nvdimm_events_map; + } + +- strcpy(statid, stat->stat_id); +- p->nvdimm_events_map[count] = statid; + count++; + } + p->nvdimm_events_map[count] = NULL; +-- +2.35.3 + diff --git a/patches.suse/powerpc-papr_scm-Fix-build-failure-when.patch b/patches.suse/powerpc-papr_scm-Fix-build-failure-when.patch new file mode 100644 index 0000000..00f46a1 --- /dev/null +++ b/patches.suse/powerpc-papr_scm-Fix-build-failure-when.patch @@ -0,0 +1,90 @@ +From d0007eb15c2a8113e847143c783ea83d93963741 Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Wed, 23 Mar 2022 22:15:50 +0530 +Subject: [PATCH] powerpc/papr_scm: Fix build failure when +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +References: jsc#PED-1925 +Patch-mainline: v5.18-rc1 +Git-commit: d0007eb15c2a8113e847143c783ea83d93963741 + +The following build failure occurs when CONFIG_PERF_EVENTS is not set +as generic pmu functions are not visible in that scenario. + +arch/powerpc/platforms/pseries/papr_scm.c:372:35: error: ‘struct perf_event’ has no member named ‘attr’ + p->nvdimm_events_map[event->attr.config], + ^~ +In file included from ./include/linux/list.h:5, + from ./include/linux/kobject.h:19, + from ./include/linux/of.h:17, + from arch/powerpc/platforms/pseries/papr_scm.c:5: +arch/powerpc/platforms/pseries/papr_scm.c: In function ‘papr_scm_pmu_event_init’: +arch/powerpc/platforms/pseries/papr_scm.c:389:49: error: ‘struct perf_event’ has no member named ‘pmu’ + struct nvdimm_pmu *nd_pmu = to_nvdimm_pmu(event->pmu); + ^~ +./include/linux/container_of.h:18:26: note: in definition of macro ‘container_of’ + void *__mptr = (void *)(ptr); \ + ^~~ +arch/powerpc/platforms/pseries/papr_scm.c:389:30: note: in expansion of macro ‘to_nvdimm_pmu’ + struct nvdimm_pmu *nd_pmu = to_nvdimm_pmu(event->pmu); + ^~~~~~~~~~~~~ +In file included from ./include/linux/bits.h:22, + from ./include/linux/bitops.h:6, + from ./include/linux/of.h:15, + from arch/powerpc/platforms/pseries/papr_scm.c:5: + +Fix the build issue by adding check for CONFIG_PERF_EVENTS config option +and also add stub function for papr_scm_pmu_register to handle +the CONFIG_PERF_EVENTS=n case. Also move the position of macro +"to_nvdimm_pmu" inorder to merge it in CONFIG_PERF_EVENTS=y block. + +based on libnvdimm-for-next tree) + +Fixes: 4c08d4bbc089 ("powerpc/papr_scm: Add perf interface support") (Commit id +Signed-off-by: Kajol Jain +Link: https://lore.kernel.org/r/20220323164550.109768-2-kjain@linux.ibm.com +Signed-off-by: Dan Williams +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/papr_scm.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c +index 4dd513d7c029..9dba9e71fde9 100644 +--- a/arch/powerpc/platforms/pseries/papr_scm.c ++++ b/arch/powerpc/platforms/pseries/papr_scm.c +@@ -69,8 +69,6 @@ + #define PAPR_SCM_PERF_STATS_EYECATCHER __stringify(SCMSTATS) + #define PAPR_SCM_PERF_STATS_VERSION 0x1 + +-#define to_nvdimm_pmu(_pmu) container_of(_pmu, struct nvdimm_pmu, pmu) +- + /* Struct holding a single performance metric */ + struct papr_scm_perf_stat { + u8 stat_id[8]; +@@ -346,6 +344,9 @@ static ssize_t drc_pmem_query_stats(struct papr_scm_priv *p, + return 0; + } + ++#ifdef CONFIG_PERF_EVENTS ++#define to_nvdimm_pmu(_pmu) container_of(_pmu, struct nvdimm_pmu, pmu) ++ + static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, u64 *count) + { + struct papr_scm_perf_stat *stat; +@@ -558,6 +559,10 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p) + dev_info(&p->pdev->dev, "nvdimm pmu didn't register rc=%d\n", rc); + } + ++#else ++static void papr_scm_pmu_register(struct papr_scm_priv *p) { } ++#endif ++ + /* + * Issue hcall to retrieve dimm health info and populate papr_scm_priv with the + * health information. +-- +2.35.3 + diff --git a/patches.suse/powerpc-papr_scm-Fix-leaking-nvdimm_events_map-eleme.patch b/patches.suse/powerpc-papr_scm-Fix-leaking-nvdimm_events_map-eleme.patch new file mode 100644 index 0000000..90887f6 --- /dev/null +++ b/patches.suse/powerpc-papr_scm-Fix-leaking-nvdimm_events_map-eleme.patch @@ -0,0 +1,133 @@ +From 0e0946e22f3665d27325d389ff45ade6e93f3678 Mon Sep 17 00:00:00 2001 +From: Vaibhav Jain +Date: Wed, 11 May 2022 13:56:36 +0530 +Subject: [PATCH] powerpc/papr_scm: Fix leaking nvdimm_events_map elements + +References: jsc#PED-557 +Patch-mainline: v5.19-rc1 +Git-commit: 0e0946e22f3665d27325d389ff45ade6e93f3678 + +Right now 'char *' elements allocated for individual 'stat_id' in +'papr_scm_priv.nvdimm_events_map[]' during papr_scm_pmu_check_events(), get +leaked in papr_scm_remove() and papr_scm_pmu_register(), +papr_scm_pmu_check_events() error paths. + +Also individual 'stat_id' arent NULL terminated 'char *' instead they are fixed +8-byte sized identifiers. However papr_scm_pmu_register() assumes it to be a +NULL terminated 'char *' and at other places it assumes it to be a +'papr_scm_perf_stat.stat_id' sized string which is 8-byes in size. + +Fix this by allocating the memory for papr_scm_priv.nvdimm_events_map to also +include space for 'stat_id' entries. This is possible since number of available +events/stat_ids are known upfront. This saves some memory and one extra level of +indirection from 'nvdimm_events_map' to 'stat_id'. Also rest of the code +can continue to call 'kfree(papr_scm_priv.nvdimm_events_map)' without needing to +iterate over the array and free up individual elements. + +Fixes: 4c08d4bbc089 ("powerpc/papr_scm: Add perf interface support") +Signed-off-by: Vaibhav Jain +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220511082637.646714-1-vaibhav@linux.ibm.com +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/papr_scm.c | 54 ++++++++++------------- + 1 file changed, 24 insertions(+), 30 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c +--- a/arch/powerpc/platforms/pseries/papr_scm.c ++++ b/arch/powerpc/platforms/pseries/papr_scm.c +@@ -125,8 +125,8 @@ struct papr_scm_priv { + /* length of the stat buffer as expected by phyp */ + size_t stat_buffer_len; + +- /* array to have event_code and stat_id mappings */ +- char **nvdimm_events_map; ++ /* array to have event_code and stat_id mappings */ ++ u8 *nvdimm_events_map; + }; + + static int papr_scm_pmem_flush(struct nd_region *nd_region, +@@ -370,7 +370,7 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, + + stat = &stats->scm_statistic[0]; + memcpy(&stat->stat_id, +- p->nvdimm_events_map[event->attr.config], ++ &p->nvdimm_events_map[event->attr.config * sizeof(stat->stat_id)], + sizeof(stat->stat_id)); + stat->stat_val = 0; + +@@ -462,14 +462,13 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu + { + struct papr_scm_perf_stat *stat; + struct papr_scm_perf_stats *stats; +- int index, rc, count; + u32 available_events; +- +- if (!p->stat_buffer_len) +- return -ENOENT; ++ int index, rc = 0; + + available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats)) + / sizeof(struct papr_scm_perf_stat); ++ if (available_events == 0) ++ return -EOPNOTSUPP; + + /* Allocate the buffer for phyp where stats are written */ + stats = kzalloc(p->stat_buffer_len, GFP_KERNEL); +@@ -478,35 +477,30 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu + return rc; + } + +- /* Allocate memory to nvdimm_event_map */ +- p->nvdimm_events_map = kcalloc(available_events, sizeof(char *), GFP_KERNEL); +- if (!p->nvdimm_events_map) { +- rc = -ENOMEM; +- goto out_stats; +- } +- + /* Called to get list of events supported */ + rc = drc_pmem_query_stats(p, stats, 0); + if (rc) +- goto out_nvdimm_events_map; +- +- for (index = 0, stat = stats->scm_statistic, count = 0; +- index < available_events; index++, ++stat) { +- p->nvdimm_events_map[count] = kmemdup_nul(stat->stat_id, 8, GFP_KERNEL); +- if (!p->nvdimm_events_map[count]) { +- rc = -ENOMEM; +- goto out_nvdimm_events_map; +- } ++ goto out; + +- count++; ++ /* ++ * Allocate memory and populate nvdimm_event_map. ++ * Allocate an extra element for NULL entry ++ */ ++ p->nvdimm_events_map = kcalloc(available_events + 1, ++ sizeof(stat->stat_id), ++ GFP_KERNEL); ++ if (!p->nvdimm_events_map) { ++ rc = -ENOMEM; ++ goto out; + } +- p->nvdimm_events_map[count] = NULL; +- kfree(stats); +- return 0; + +-out_nvdimm_events_map: +- kfree(p->nvdimm_events_map); +-out_stats: ++ /* Copy all stat_ids to event map */ ++ for (index = 0, stat = stats->scm_statistic; ++ index < available_events; index++, ++stat) { ++ memcpy(&p->nvdimm_events_map[index * sizeof(stat->stat_id)], ++ &stat->stat_id, sizeof(stat->stat_id)); ++ } ++out: + kfree(stats); + return rc; + } +-- +2.35.3 + diff --git a/patches.suse/powerpc-papr_scm-Fix-nvdimm-event-mappings.patch b/patches.suse/powerpc-papr_scm-Fix-nvdimm-event-mappings.patch new file mode 100644 index 0000000..39ff3e4 --- /dev/null +++ b/patches.suse/powerpc-papr_scm-Fix-nvdimm-event-mappings.patch @@ -0,0 +1,199 @@ +From 9b1ac04698a4bfec146322502cdcd9904c1777fa Mon Sep 17 00:00:00 2001 +From: Kajol Jain +Date: Thu, 4 Aug 2022 13:18:52 +0530 +Subject: [PATCH] powerpc/papr_scm: Fix nvdimm event mappings + +References: jsc#PED-557 +Patch-mainline: v6.0-rc4 +Git-commit: 9b1ac04698a4bfec146322502cdcd9904c1777fa + +Commit 4c08d4bbc089 ("powerpc/papr_scm: Add perf interface support") +added performance monitoring support for papr-scm nvdimm devices via +perf interface. Commit also added an array in papr_scm_priv +structure called "nvdimm_events_map", which got filled based on the +result of H_SCM_PERFORMANCE_STATS hcall. + +Currently there is an assumption that the order of events in the +stats buffer, returned by the hypervisor is same. And order also +happens to matches with the events specified in nvdimm driver code. +But this assumption is not documented in Power Architecture +Platform Requirements (PAPR) document. Although the order +of events happens to be same on current generation od system, but +it might not be true in future generation systems. Fix the issue, by +adding a static mapping for nvdimm events to corresponding stat-id, +and removing the dynamic map from papr_scm_priv structure. Also +remove the function papr_scm_pmu_check_events from papr_scm.c file, +as we no longer need to copy stat-ids dynamically. + +Fixes: 4c08d4bbc089 ("powerpc/papr_scm: Add perf interface support") +Reported-by: Aneesh Kumar K.V +Signed-off-by: Kajol Jain +Reviewed-by: Vaibhav Jain +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220804074852.55157-1-kjain@linux.ibm.com +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/papr_scm.c | 88 +++++++---------------- + 1 file changed, 27 insertions(+), 61 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c +--- a/arch/powerpc/platforms/pseries/papr_scm.c ++++ b/arch/powerpc/platforms/pseries/papr_scm.c +@@ -124,9 +124,6 @@ struct papr_scm_priv { + + /* length of the stat buffer as expected by phyp */ + size_t stat_buffer_len; +- +- /* array to have event_code and stat_id mappings */ +- u8 *nvdimm_events_map; + }; + + static int papr_scm_pmem_flush(struct nd_region *nd_region, +@@ -350,6 +347,25 @@ static ssize_t drc_pmem_query_stats(struct papr_scm_priv *p, + #ifdef CONFIG_PERF_EVENTS + #define to_nvdimm_pmu(_pmu) container_of(_pmu, struct nvdimm_pmu, pmu) + ++static const char * const nvdimm_events_map[] = { ++ [1] = "CtlResCt", ++ [2] = "CtlResTm", ++ [3] = "PonSecs ", ++ [4] = "MemLife ", ++ [5] = "CritRscU", ++ [6] = "HostLCnt", ++ [7] = "HostSCnt", ++ [8] = "HostSDur", ++ [9] = "HostLDur", ++ [10] = "MedRCnt ", ++ [11] = "MedWCnt ", ++ [12] = "MedRDur ", ++ [13] = "MedWDur ", ++ [14] = "CchRHCnt", ++ [15] = "CchWHCnt", ++ [16] = "FastWCnt", ++}; ++ + static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, u64 *count) + { + struct papr_scm_perf_stat *stat; +@@ -357,11 +373,15 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, + struct papr_scm_priv *p = (struct papr_scm_priv *)dev->driver_data; + int rc, size; + ++ /* Invalid eventcode */ ++ if (event->attr.config == 0 || event->attr.config >= ARRAY_SIZE(nvdimm_events_map)) ++ return -EINVAL; ++ + /* Allocate request buffer enough to hold single performance stat */ + size = sizeof(struct papr_scm_perf_stats) + + sizeof(struct papr_scm_perf_stat); + +- if (!p || !p->nvdimm_events_map) ++ if (!p) + return -EINVAL; + + stats = kzalloc(size, GFP_KERNEL); +@@ -370,7 +390,7 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, + + stat = &stats->scm_statistic[0]; + memcpy(&stat->stat_id, +- &p->nvdimm_events_map[event->attr.config * sizeof(stat->stat_id)], ++ nvdimm_events_map[event->attr.config], + sizeof(stat->stat_id)); + stat->stat_val = 0; + +@@ -458,56 +478,6 @@ static void papr_scm_pmu_del(struct perf_event *event, int flags) + papr_scm_pmu_read(event); + } + +-static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu *nd_pmu) +-{ +- struct papr_scm_perf_stat *stat; +- struct papr_scm_perf_stats *stats; +- u32 available_events; +- int index, rc = 0; +- +- if (!p->stat_buffer_len) +- return -ENOENT; +- +- available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats)) +- / sizeof(struct papr_scm_perf_stat); +- if (available_events == 0) +- return -EOPNOTSUPP; +- +- /* Allocate the buffer for phyp where stats are written */ +- stats = kzalloc(p->stat_buffer_len, GFP_KERNEL); +- if (!stats) { +- rc = -ENOMEM; +- return rc; +- } +- +- /* Called to get list of events supported */ +- rc = drc_pmem_query_stats(p, stats, 0); +- if (rc) +- goto out; +- +- /* +- * Allocate memory and populate nvdimm_event_map. +- * Allocate an extra element for NULL entry +- */ +- p->nvdimm_events_map = kcalloc(available_events + 1, +- sizeof(stat->stat_id), +- GFP_KERNEL); +- if (!p->nvdimm_events_map) { +- rc = -ENOMEM; +- goto out; +- } +- +- /* Copy all stat_ids to event map */ +- for (index = 0, stat = stats->scm_statistic; +- index < available_events; index++, ++stat) { +- memcpy(&p->nvdimm_events_map[index * sizeof(stat->stat_id)], +- &stat->stat_id, sizeof(stat->stat_id)); +- } +-out: +- kfree(stats); +- return rc; +-} +- + static void papr_scm_pmu_register(struct papr_scm_priv *p) + { + struct nvdimm_pmu *nd_pmu; +@@ -519,8 +489,7 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p) + goto pmu_err_print; + } + +- rc = papr_scm_pmu_check_events(p, nd_pmu); +- if (rc) ++ if (!p->stat_buffer_len) + goto pmu_check_events_err; + + nd_pmu->pmu.task_ctx_nr = perf_invalid_context; +@@ -539,7 +508,7 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p) + + rc = register_nvdimm_pmu(nd_pmu, p->pdev); + if (rc) +- goto pmu_register_err; ++ goto pmu_check_events_err; + + /* + * Set archdata.priv value to nvdimm_pmu structure, to handle the +@@ -548,8 +517,6 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p) + p->pdev->archdata.priv = nd_pmu; + return; + +-pmu_register_err: +- kfree(p->nvdimm_events_map); + pmu_check_events_err: + kfree(nd_pmu); + pmu_err_print: +@@ -1560,7 +1527,6 @@ static int papr_scm_remove(struct platform_device *pdev) + unregister_nvdimm_pmu(pdev->archdata.priv); + + pdev->archdata.priv = NULL; +- kfree(p->nvdimm_events_map); + kfree(p->bus_desc.provider_name); + kfree(p); + +-- +2.35.3 + diff --git a/patches.suse/powerpc-papr_scm-don-t-requests-stats-with-0-sized-s.patch b/patches.suse/powerpc-papr_scm-don-t-requests-stats-with-0-sized-s.patch new file mode 100644 index 0000000..b2903be --- /dev/null +++ b/patches.suse/powerpc-papr_scm-don-t-requests-stats-with-0-sized-s.patch @@ -0,0 +1,73 @@ +From 07bf9431b1590d1cd7a8d62075d0b50b073f0495 Mon Sep 17 00:00:00 2001 +From: Vaibhav Jain +Date: Tue, 24 May 2022 16:53:53 +0530 +Subject: [PATCH] powerpc/papr_scm: don't requests stats with '0' sized stats + buffer + +References: jsc#PED-1925 +Patch-mainline: v5.19-rc2 +Git-commit: 07bf9431b1590d1cd7a8d62075d0b50b073f0495 + +Sachin reported [1] that on a POWER-10 lpar he is seeing a kernel panic being +reported with vPMEM when papr_scm probe is being called. The panic is of the +form below and is observed only with following option disabled(profile) for the +said LPAR 'Enable Performance Information Collection' in the HMC: + + Kernel attempted to write user page (1c) - exploit attempt? (uid: 0) + BUG: Kernel NULL pointer dereference on write at 0x0000001c + Faulting instruction address: 0xc008000001b90844 + Oops: Kernel access of bad area, sig: 11 [#1] + + NIP [c008000001b90844] drc_pmem_query_stats+0x5c/0x270 [papr_scm] + LR [c008000001b92794] papr_scm_probe+0x2ac/0x6ec [papr_scm] + Call Trace: + 0xc00000000941bca0 (unreliable) + papr_scm_probe+0x2ac/0x6ec [papr_scm] + platform_probe+0x98/0x150 + really_probe+0xfc/0x510 + __driver_probe_device+0x17c/0x230 + + ---[ end trace 0000000000000000 ]--- + Kernel panic - not syncing: Fatal exception + +On investigation looks like this panic was caused due to a 'stat_buffer' of +size==0 being provided to drc_pmem_query_stats() to fetch all performance +stats-ids of an NVDIMM. However drc_pmem_query_stats() shouldn't have been called +since the vPMEM NVDIMM doesn't support and performance stat-id's. This was caused +due to missing check for 'p->stat_buffer_len' at the beginning of +papr_scm_pmu_check_events() which indicates that the NVDIMM doesn't support +performance-stats. + +Fix this by introducing the check for 'p->stat_buffer_len' at the beginning of +papr_scm_pmu_check_events(). + +[1] https://lore.kernel.org/all/6B3A522A-6A5F-4CC9-B268-0C63AA6E07D3@linux.ibm.com + +Fixes: 0e0946e22f3665d2732 ("powerpc/papr_scm: Fix leaking nvdimm_events_map elements") +Reported-by: Sachin Sant +Signed-off-by: Vaibhav Jain +Tested-by: Sachin Sant +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220524112353.1718454-1-vaibhav@linux.ibm.com +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/papr_scm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c +index 181b855b3050..82cae08976bc 100644 +--- a/arch/powerpc/platforms/pseries/papr_scm.c ++++ b/arch/powerpc/platforms/pseries/papr_scm.c +@@ -465,6 +465,9 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu + u32 available_events; + int index, rc = 0; + ++ if (!p->stat_buffer_len) ++ return -ENOENT; ++ + available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats)) + / sizeof(struct papr_scm_perf_stat); + if (available_events == 0) +-- +2.35.3 + diff --git a/patches.suse/tools-testing-nvdimm-Fix-security_init-symbol-collis.patch b/patches.suse/tools-testing-nvdimm-Fix-security_init-symbol-collis.patch new file mode 100644 index 0000000..9292dbe --- /dev/null +++ b/patches.suse/tools-testing-nvdimm-Fix-security_init-symbol-collis.patch @@ -0,0 +1,60 @@ +From e8cf229ebe5eb31eecee86268223530a872872c2 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Sun, 3 Apr 2022 20:19:46 -0700 +Subject: [PATCH] tools/testing/nvdimm: Fix security_init() symbol collision +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +References: jsc#PED-1925 +Patch-mainline: v5.18-rc2 +Git-commit: e8cf229ebe5eb31eecee86268223530a872872c2 + +Starting with the new perf-event support in the nvdimm core, the +nfit_test mock module stops compiling. Rename its security_init() to +nfit_security_init(). + +tools/testing/nvdimm/test/nfit.c:1845:13: error: conflicting types for ‘security_init’; have ‘void(struct nfit_test *)’ + 1845 | static void security_init(struct nfit_test *t) + | ^~~~~~~~~~~~~ +In file included from ./include/linux/perf_event.h:61, + from ./include/linux/nd.h:11, + from ./drivers/nvdimm/nd-core.h:11, + from tools/testing/nvdimm/test/nfit.c:19: + +Fixes: 9a61d0838cd0 ("drivers/nvdimm: Add nvdimm pmu structure") +Cc: Kajol Jain +Reviewed-by: Kajol Jain +Reviewed-by: Vishal Verma +Link: https://lore.kernel.org/r/164904238610.1330275.1889212115373993727.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Acked-by: Michal Suchanek +--- + tools/testing/nvdimm/test/nfit.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c +index 65dbdda3a054..1da76ccde448 100644 +--- a/tools/testing/nvdimm/test/nfit.c ++++ b/tools/testing/nvdimm/test/nfit.c +@@ -1842,7 +1842,7 @@ static int nfit_test_dimm_init(struct nfit_test *t) + return 0; + } + +-static void security_init(struct nfit_test *t) ++static void nfit_security_init(struct nfit_test *t) + { + int i; + +@@ -1938,7 +1938,7 @@ static int nfit_test0_alloc(struct nfit_test *t) + if (nfit_test_dimm_init(t)) + return -ENOMEM; + smart_init(t); +- security_init(t); ++ nfit_security_init(t); + return ars_state_init(&t->pdev.dev, &t->ars_state); + } + +-- +2.35.3 + diff --git a/patches.suse/usb-Avoid-extra-usb-SET_SEL-requests-when-enabling-l.patch b/patches.suse/usb-Avoid-extra-usb-SET_SEL-requests-when-enabling-l.patch new file mode 100644 index 0000000..5d1875d --- /dev/null +++ b/patches.suse/usb-Avoid-extra-usb-SET_SEL-requests-when-enabling-l.patch @@ -0,0 +1,194 @@ +From e146caf303493c4f2458173d7f1598b76a9b1396 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Fri, 6 May 2022 19:18:07 +0300 +Subject: [PATCH] usb: Avoid extra usb SET_SEL requests when enabling link + power management +Git-commit: e146caf303493c4f2458173d7f1598b76a9b1396 +References: jsc#PED-531 +Patch-mainline: v6.0-rc1 + +The host needs to tell the device the exit latencies using the SET_SEL +request before device initiated link powermanagement can be enabled. + +The exit latency values do not change after enumeration, it's enough +to set them once. So do like Windows 10 and issue the SET_SEL request +once just before setting the configuration. + +This is also the sequence described in USB 3.2 specs "9.1.2 Bus +enumeration". SET_SEL is issued once before the Set Configuration +request, and won't be cleared by the Set Configuration, +Set Interface or ClearFeature (STALL) requests. + +Only warm reset, hot reset, set Address 0 clears the exit latencies. +See USB 3.2 section 9.4.14 Table 9-10 Device parameters and events + +Add udev->lpm_devinit_allow, and set it if SET_SEL was successful. +If not set, then don't try to enable device initiated LPM + +We used to issue a SET_SEL request every time lpm is enabled for either +U1 or U2 link states, meaning a SET_SEL was issued twice after every +Set Configuration and Set Interface requests, easily accumulating to +over 15 SET_SEL requets during a USB3 webcam enumeration. + +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220506161807.3369439-1-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/hub.c | 60 +++++++++++++++--------------------------- + include/linux/usb.h | 2 ++ + 2 files changed, 23 insertions(+), 39 deletions(-) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index ba406b8d688d..b7f66dcd1fe0 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -3947,7 +3947,7 @@ static const char * const usb3_lpm_names[] = { + * This function will fail if the SEL or PEL values for udev are greater than + * the maximum allowed values for the link state to be enabled. + */ +-static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) ++static int usb_req_set_sel(struct usb_device *udev) + { + struct usb_set_sel_req *sel_values; + unsigned long long u1_sel; +@@ -3956,7 +3956,7 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) + unsigned long long u2_pel; + int ret; + +- if (udev->state != USB_STATE_CONFIGURED) ++ if (!udev->parent || udev->speed < USB_SPEED_SUPER || !udev->lpm_capable) + return 0; + + /* Convert SEL and PEL stored in ns to us */ +@@ -3973,34 +3973,14 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) + * latency for the link state, and could start a device-initiated + * U1/U2 when the exit latencies are too high. + */ +- if ((state == USB3_LPM_U1 && +- (u1_sel > USB3_LPM_MAX_U1_SEL_PEL || +- u1_pel > USB3_LPM_MAX_U1_SEL_PEL)) || +- (state == USB3_LPM_U2 && +- (u2_sel > USB3_LPM_MAX_U2_SEL_PEL || +- u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) { +- dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n", +- usb3_lpm_names[state], u1_sel, u1_pel); ++ if (u1_sel > USB3_LPM_MAX_U1_SEL_PEL || ++ u1_pel > USB3_LPM_MAX_U1_SEL_PEL || ++ u2_sel > USB3_LPM_MAX_U2_SEL_PEL || ++ u2_pel > USB3_LPM_MAX_U2_SEL_PEL) { ++ dev_dbg(&udev->dev, "Device-initiated U1/U2 disabled due to long SEL or PEL\n"); + return -EINVAL; + } + +- /* +- * If we're enabling device-initiated LPM for one link state, +- * but the other link state has a too high SEL or PEL value, +- * just set those values to the max in the Set SEL request. +- */ +- if (u1_sel > USB3_LPM_MAX_U1_SEL_PEL) +- u1_sel = USB3_LPM_MAX_U1_SEL_PEL; +- +- if (u1_pel > USB3_LPM_MAX_U1_SEL_PEL) +- u1_pel = USB3_LPM_MAX_U1_SEL_PEL; +- +- if (u2_sel > USB3_LPM_MAX_U2_SEL_PEL) +- u2_sel = USB3_LPM_MAX_U2_SEL_PEL; +- +- if (u2_pel > USB3_LPM_MAX_U2_SEL_PEL) +- u2_pel = USB3_LPM_MAX_U2_SEL_PEL; +- + /* + * usb_enable_lpm() can be called as part of a failed device reset, + * which may be initiated by an error path of a mass storage driver. +@@ -4022,6 +4002,10 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) + sel_values, sizeof *(sel_values), + USB_CTRL_SET_TIMEOUT); + kfree(sel_values); ++ ++ if (ret > 0) ++ udev->lpm_devinit_allow = 1; ++ + return ret; + } + +@@ -4137,6 +4121,9 @@ static bool usb_device_may_initiate_lpm(struct usb_device *udev, + unsigned int sel; /* us */ + int i, j; + ++ if (!udev->lpm_devinit_allow) ++ return false; ++ + if (state == USB3_LPM_U1) + sel = DIV_ROUND_UP(udev->u1_params.sel, 1000); + else if (state == USB3_LPM_U2) +@@ -4185,7 +4172,7 @@ static bool usb_device_may_initiate_lpm(struct usb_device *udev, + static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, + enum usb3_link_state state) + { +- int timeout, ret; ++ int timeout; + __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; + __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; + +@@ -4197,17 +4184,6 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, + (state == USB3_LPM_U2 && u2_mel == 0)) + return; + +- /* +- * First, let the device know about the exit latencies +- * associated with the link state we're about to enable. +- */ +- ret = usb_req_set_sel(udev, state); +- if (ret < 0) { +- dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n", +- usb3_lpm_names[state]); +- return; +- } +- + /* We allow the host controller to set the U1/U2 timeout internally + * first, so that it can change its schedule to account for the + * additional latency to send data to a device in a lower power +@@ -4487,6 +4463,11 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, + return 0; + } + ++static int usb_req_set_sel(struct usb_device *udev) ++{ ++ return 0; ++} ++ + #endif /* CONFIG_PM */ + + /* +@@ -5012,6 +4993,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + udev->lpm_capable = usb_device_supports_lpm(udev); + udev->lpm_disable_count = 1; + usb_set_lpm_parameters(udev); ++ usb_req_set_sel(udev); + } + } + +diff --git a/include/linux/usb.h b/include/linux/usb.h +index 60bee864d897..f7a9914fc97f 100644 +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -584,6 +584,7 @@ struct usb3_lpm_parameters { + * @authenticated: Crypto authentication passed + * @wusb: device is Wireless USB + * @lpm_capable: device supports LPM ++ * @lpm_devinit_allow: Allow USB3 device initiated LPM, exit latency is in range + * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM + * @usb2_hw_lpm_besl_capable: device can perform USB2 hardware BESL LPM + * @usb2_hw_lpm_enabled: USB2 hardware LPM is enabled +@@ -666,6 +667,7 @@ struct usb_device { + unsigned authenticated:1; + unsigned wusb:1; + unsigned lpm_capable:1; ++ unsigned lpm_devinit_allow:1; + unsigned usb2_hw_lpm_capable:1; + unsigned usb2_hw_lpm_besl_capable:1; + unsigned usb2_hw_lpm_enabled:1; +-- +2.35.3 + diff --git a/patches.suse/usb-core-devices-remove-dead-code-under-ifdef-PROC_E.patch b/patches.suse/usb-core-devices-remove-dead-code-under-ifdef-PROC_E.patch new file mode 100644 index 0000000..4c4483e --- /dev/null +++ b/patches.suse/usb-core-devices-remove-dead-code-under-ifdef-PROC_E.patch @@ -0,0 +1,70 @@ +From 4f8cfe675f4666117c93420783049eff04c3ceba Mon Sep 17 00:00:00 2001 +From: Sergey Shtylyov +Date: Mon, 18 Apr 2022 23:33:55 +0300 +Subject: [PATCH] usb: core: devices: remove dead code under #ifdef PROC_EXTRA +Git-commit: 4f8cfe675f4666117c93420783049eff04c3ceba +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +usb_dump_hub_descriptor() and usb_dump_string() are defined under #ifdef +PROC_EXTRA (while PROC_EXTRA doesn't seem to have ever been #define'd) +since the dawn of the git era -- remove this dead code at last... + +Signed-off-by: Sergey Shtylyov + +Link: https://lore.kernel.org/r/ec08915b-faf2-2f0b-dfb1-048dfa2c67f3@omp.ru +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/devices.c | 35 ----------------------------------- + 1 file changed, 35 deletions(-) + +diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c +index d8b0041de612..cc12cdd5559f 100644 +--- a/drivers/usb/core/devices.c ++++ b/drivers/usb/core/devices.c +@@ -390,41 +390,6 @@ static char *usb_dump_desc(char *start, char *end, struct usb_device *dev) + return start; + } + +- +-#ifdef PROC_EXTRA /* TBD: may want to add this code later */ +- +-static char *usb_dump_hub_descriptor(char *start, char *end, +- const struct usb_hub_descriptor *desc) +-{ +- int leng = USB_DT_HUB_NONVAR_SIZE; +- unsigned char *ptr = (unsigned char *)desc; +- +- if (start > end) +- return start; +- start += sprintf(start, "Interface:"); +- while (leng && start <= end) { +- start += sprintf(start, " %02x", *ptr); +- ptr++; leng--; +- } +- *start++ = '\n'; +- return start; +-} +- +-static char *usb_dump_string(char *start, char *end, +- const struct usb_device *dev, char *id, int index) +-{ +- if (start > end) +- return start; +- start += sprintf(start, "Interface:"); +- if (index <= dev->maxstring && dev->stringindex && +- dev->stringindex[index]) +- start += sprintf(start, "%s: %.100s ", id, +- dev->stringindex[index]); +- return start; +-} +- +-#endif /* PROC_EXTRA */ +- + /*****************************************************************/ + + /* This is a recursive function. Parameters: +-- +2.35.3 + diff --git a/patches.suse/usb-core-fix-repeated-words-in-comments.patch b/patches.suse/usb-core-fix-repeated-words-in-comments.patch new file mode 100644 index 0000000..87c75d2 --- /dev/null +++ b/patches.suse/usb-core-fix-repeated-words-in-comments.patch @@ -0,0 +1,48 @@ +From a7a9f4c0060e8f29a5fc2fe610575c3eabfc2253 Mon Sep 17 00:00:00 2001 +From: Jilin Yuan +Date: Sat, 16 Jul 2022 21:24:03 +0800 +Subject: [PATCH] usb/core: fix repeated words in comments +Git-commit: a7a9f4c0060e8f29a5fc2fe610575c3eabfc2253 +References: git-fixes +Patch-mainline: v6.0-rc1 + + Delete the redundant word 'the'. + +Signed-off-by: Jilin Yuan +Link: https://lore.kernel.org/r/20220716132403.35270-1-yuanjilin@cdjrlc.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/driver.c | 2 +- + drivers/usb/core/usb.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c +index b87452e22835..7e7e119c253f 100644 +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -1482,7 +1482,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) + * @msg: Power Management message describing this state transition + * + * This is the central routine for resuming USB devices. It calls the +- * the resume method for @udev and then calls the resume methods for all ++ * resume method for @udev and then calls the resume methods for all + * the interface drivers in @udev. + * + * Autoresume requests originating from a child device or an interface +diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c +index 2f71636af6e1..11b15d7b357a 100644 +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -801,7 +801,7 @@ EXPORT_SYMBOL_GPL(usb_intf_get_dma_device); + * is simple: + * + * When locking both a device and its parent, always lock the +- * the parent first. ++ * parent first. + */ + + /** +-- +2.35.3 + diff --git a/patches.suse/usb-core-sysfs-convert-sysfs-snprintf-to-sysfs_emit.patch b/patches.suse/usb-core-sysfs-convert-sysfs-snprintf-to-sysfs_emit.patch new file mode 100644 index 0000000..3873b76 --- /dev/null +++ b/patches.suse/usb-core-sysfs-convert-sysfs-snprintf-to-sysfs_emit.patch @@ -0,0 +1,369 @@ +From 6569689e78299ff91002960a163012b576f2b21a Mon Sep 17 00:00:00 2001 +From: Xuezhi Zhang +Date: Fri, 24 Jun 2022 20:12:38 +0800 +Subject: [PATCH] usb: core: sysfs: convert sysfs snprintf to sysfs_emit +Git-commit: 6569689e78299ff91002960a163012b576f2b21a +References: git-fixes +Patch-mainline: v6.0-rc1 + +Fix up all sysfs show entries to use sysfs_emit + +Signed-off-by: Xuezhi Zhang +Link: https://lore.kernel.org/r/20220624121238.134256-1-zhangxuezhi1@coolpad.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/sysfs.c | 79 ++++++++++++++++++++-------------------- + 1 file changed, 40 insertions(+), 39 deletions(-) + +diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c +index fa2e49d432ff..631574718d8a 100644 +--- a/drivers/usb/core/sysfs.c ++++ b/drivers/usb/core/sysfs.c +@@ -35,7 +35,7 @@ static ssize_t field##_show(struct device *dev, \ + return -EINTR; \ + actconfig = udev->actconfig; \ + if (actconfig) \ +- rc = sprintf(buf, format_string, \ ++ rc = sysfs_emit(buf, format_string, \ + actconfig->desc.field); \ + usb_unlock_device(udev); \ + return rc; \ +@@ -61,7 +61,7 @@ static ssize_t bMaxPower_show(struct device *dev, + return -EINTR; + actconfig = udev->actconfig; + if (actconfig) +- rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig)); ++ rc = sysfs_emit(buf, "%dmA\n", usb_get_max_power(udev, actconfig)); + usb_unlock_device(udev); + return rc; + } +@@ -80,7 +80,7 @@ static ssize_t configuration_show(struct device *dev, + return -EINTR; + actconfig = udev->actconfig; + if (actconfig && actconfig->string) +- rc = sprintf(buf, "%s\n", actconfig->string); ++ rc = sysfs_emit(buf, "%s\n", actconfig->string); + usb_unlock_device(udev); + return rc; + } +@@ -114,7 +114,7 @@ static ssize_t devspec_show(struct device *dev, struct device_attribute *attr, + { + struct device_node *of_node = dev->of_node; + +- return sprintf(buf, "%pOF\n", of_node); ++ return sysfs_emit(buf, "%pOF\n", of_node); + } + static DEVICE_ATTR_RO(devspec); + #endif +@@ -131,7 +131,7 @@ static ssize_t name##_show(struct device *dev, \ + retval = usb_lock_device_interruptible(udev); \ + if (retval < 0) \ + return -EINTR; \ +- retval = sprintf(buf, "%s\n", udev->name); \ ++ retval = sysfs_emit(buf, "%s\n", udev->name); \ + usb_unlock_device(udev); \ + return retval; \ + } \ +@@ -175,7 +175,7 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr, + default: + speed = "unknown"; + } +- return sprintf(buf, "%s\n", speed); ++ return sysfs_emit(buf, "%s\n", speed); + } + static DEVICE_ATTR_RO(speed); + +@@ -185,7 +185,7 @@ static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", udev->rx_lanes); ++ return sysfs_emit(buf, "%d\n", udev->rx_lanes); + } + static DEVICE_ATTR_RO(rx_lanes); + +@@ -195,7 +195,7 @@ static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", udev->tx_lanes); ++ return sysfs_emit(buf, "%d\n", udev->tx_lanes); + } + static DEVICE_ATTR_RO(tx_lanes); + +@@ -205,7 +205,7 @@ static ssize_t busnum_show(struct device *dev, struct device_attribute *attr, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", udev->bus->busnum); ++ return sysfs_emit(buf, "%d\n", udev->bus->busnum); + } + static DEVICE_ATTR_RO(busnum); + +@@ -215,7 +215,7 @@ static ssize_t devnum_show(struct device *dev, struct device_attribute *attr, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", udev->devnum); ++ return sysfs_emit(buf, "%d\n", udev->devnum); + } + static DEVICE_ATTR_RO(devnum); + +@@ -225,7 +225,7 @@ static ssize_t devpath_show(struct device *dev, struct device_attribute *attr, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "%s\n", udev->devpath); ++ return sysfs_emit(buf, "%s\n", udev->devpath); + } + static DEVICE_ATTR_RO(devpath); + +@@ -237,7 +237,7 @@ static ssize_t version_show(struct device *dev, struct device_attribute *attr, + + udev = to_usb_device(dev); + bcdUSB = le16_to_cpu(udev->descriptor.bcdUSB); +- return sprintf(buf, "%2x.%02x\n", bcdUSB >> 8, bcdUSB & 0xff); ++ return sysfs_emit(buf, "%2x.%02x\n", bcdUSB >> 8, bcdUSB & 0xff); + } + static DEVICE_ATTR_RO(version); + +@@ -247,7 +247,7 @@ static ssize_t maxchild_show(struct device *dev, struct device_attribute *attr, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", udev->maxchild); ++ return sysfs_emit(buf, "%d\n", udev->maxchild); + } + static DEVICE_ATTR_RO(maxchild); + +@@ -257,7 +257,7 @@ static ssize_t quirks_show(struct device *dev, struct device_attribute *attr, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "0x%x\n", udev->quirks); ++ return sysfs_emit(buf, "0x%x\n", udev->quirks); + } + static DEVICE_ATTR_RO(quirks); + +@@ -267,7 +267,7 @@ static ssize_t avoid_reset_quirk_show(struct device *dev, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET)); ++ return sysfs_emit(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET)); + } + + static ssize_t avoid_reset_quirk_store(struct device *dev, +@@ -297,7 +297,7 @@ static ssize_t urbnum_show(struct device *dev, struct device_attribute *attr, + struct usb_device *udev; + + udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", atomic_read(&udev->urbnum)); ++ return sysfs_emit(buf, "%d\n", atomic_read(&udev->urbnum)); + } + static DEVICE_ATTR_RO(urbnum); + +@@ -305,8 +305,8 @@ static ssize_t ltm_capable_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + if (usb_device_supports_ltm(to_usb_device(dev))) +- return sprintf(buf, "%s\n", "yes"); +- return sprintf(buf, "%s\n", "no"); ++ return sysfs_emit(buf, "%s\n", "yes"); ++ return sysfs_emit(buf, "%s\n", "no"); + } + static DEVICE_ATTR_RO(ltm_capable); + +@@ -317,7 +317,7 @@ static ssize_t persist_show(struct device *dev, struct device_attribute *attr, + { + struct usb_device *udev = to_usb_device(dev); + +- return sprintf(buf, "%d\n", udev->persist_enabled); ++ return sysfs_emit(buf, "%d\n", udev->persist_enabled); + } + + static ssize_t persist_store(struct device *dev, struct device_attribute *attr, +@@ -372,7 +372,7 @@ static ssize_t connected_duration_show(struct device *dev, + { + struct usb_device *udev = to_usb_device(dev); + +- return sprintf(buf, "%u\n", ++ return sysfs_emit(buf, "%u\n", + jiffies_to_msecs(jiffies - udev->connect_time)); + } + static DEVICE_ATTR_RO(connected_duration); +@@ -394,14 +394,14 @@ static ssize_t active_duration_show(struct device *dev, + duration = jiffies_to_msecs(jiffies + udev->active_duration); + else + duration = jiffies_to_msecs(udev->active_duration); +- return sprintf(buf, "%u\n", duration); ++ return sysfs_emit(buf, "%u\n", duration); + } + static DEVICE_ATTR_RO(active_duration); + + static ssize_t autosuspend_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +- return sprintf(buf, "%d\n", dev->power.autosuspend_delay / 1000); ++ return sysfs_emit(buf, "%d\n", dev->power.autosuspend_delay / 1000); + } + + static ssize_t autosuspend_store(struct device *dev, +@@ -442,7 +442,7 @@ static ssize_t level_show(struct device *dev, struct device_attribute *attr, + warn_level(); + if (udev->state != USB_STATE_SUSPENDED && !udev->dev.power.runtime_auto) + p = on_string; +- return sprintf(buf, "%s\n", p); ++ return sysfs_emit(buf, "%s\n", p); + } + + static ssize_t level_store(struct device *dev, struct device_attribute *attr, +@@ -490,7 +490,7 @@ static ssize_t usb2_hardware_lpm_show(struct device *dev, + else + p = "disabled"; + +- return sprintf(buf, "%s\n", p); ++ return sysfs_emit(buf, "%s\n", p); + } + + static ssize_t usb2_hardware_lpm_store(struct device *dev, +@@ -529,7 +529,7 @@ static ssize_t usb2_lpm_l1_timeout_show(struct device *dev, + char *buf) + { + struct usb_device *udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", udev->l1_params.timeout); ++ return sysfs_emit(buf, "%d\n", udev->l1_params.timeout); + } + + static ssize_t usb2_lpm_l1_timeout_store(struct device *dev, +@@ -552,7 +552,7 @@ static ssize_t usb2_lpm_besl_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct usb_device *udev = to_usb_device(dev); +- return sprintf(buf, "%d\n", udev->l1_params.besl); ++ return sysfs_emit(buf, "%d\n", udev->l1_params.besl); + } + + static ssize_t usb2_lpm_besl_store(struct device *dev, +@@ -589,7 +589,7 @@ static ssize_t usb3_hardware_lpm_u1_show(struct device *dev, + + usb_unlock_device(udev); + +- return sprintf(buf, "%s\n", p); ++ return sysfs_emit(buf, "%s\n", p); + } + static DEVICE_ATTR_RO(usb3_hardware_lpm_u1); + +@@ -611,7 +611,7 @@ static ssize_t usb3_hardware_lpm_u2_show(struct device *dev, + + usb_unlock_device(udev); + +- return sprintf(buf, "%s\n", p); ++ return sysfs_emit(buf, "%s\n", p); + } + static DEVICE_ATTR_RO(usb3_hardware_lpm_u2); + +@@ -694,7 +694,7 @@ field##_show(struct device *dev, struct device_attribute *attr, \ + struct usb_device *udev; \ + \ + udev = to_usb_device(dev); \ +- return sprintf(buf, format_string, \ ++ return sysfs_emit(buf, format_string, \ + le16_to_cpu(udev->descriptor.field)); \ + } \ + static DEVICE_ATTR_RO(field) +@@ -711,7 +711,7 @@ field##_show(struct device *dev, struct device_attribute *attr, \ + struct usb_device *udev; \ + \ + udev = to_usb_device(dev); \ +- return sprintf(buf, format_string, udev->descriptor.field); \ ++ return sysfs_emit(buf, format_string, udev->descriptor.field); \ + } \ + static DEVICE_ATTR_RO(field) + +@@ -727,7 +727,7 @@ static ssize_t authorized_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct usb_device *usb_dev = to_usb_device(dev); +- return snprintf(buf, PAGE_SIZE, "%u\n", usb_dev->authorized); ++ return sysfs_emit(buf, "%u\n", usb_dev->authorized); + } + + /* +@@ -918,7 +918,7 @@ static ssize_t authorized_default_show(struct device *dev, + struct usb_hcd *hcd; + + hcd = bus_to_hcd(usb_bus); +- return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy); ++ return sysfs_emit(buf, "%u\n", hcd->dev_policy); + } + + static ssize_t authorized_default_store(struct device *dev, +@@ -957,7 +957,7 @@ static ssize_t interface_authorized_default_show(struct device *dev, + struct usb_device *usb_dev = to_usb_device(dev); + struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus); + +- return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd)); ++ return sysfs_emit(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd)); + } + + /* +@@ -1066,7 +1066,7 @@ iad_##field##_show(struct device *dev, struct device_attribute *attr, \ + { \ + struct usb_interface *intf = to_usb_interface(dev); \ + \ +- return sprintf(buf, format_string, \ ++ return sysfs_emit(buf, format_string, \ + intf->intf_assoc->field); \ + } \ + static DEVICE_ATTR_RO(iad_##field) +@@ -1085,7 +1085,7 @@ field##_show(struct device *dev, struct device_attribute *attr, \ + { \ + struct usb_interface *intf = to_usb_interface(dev); \ + \ +- return sprintf(buf, format_string, \ ++ return sysfs_emit(buf, format_string, \ + intf->cur_altsetting->desc.field); \ + } \ + static DEVICE_ATTR_RO(field) +@@ -1107,7 +1107,7 @@ static ssize_t interface_show(struct device *dev, struct device_attribute *attr, + string = READ_ONCE(intf->cur_altsetting->string); + if (!string) + return 0; +- return sprintf(buf, "%s\n", string); ++ return sysfs_emit(buf, "%s\n", string); + } + static DEVICE_ATTR_RO(interface); + +@@ -1122,7 +1122,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + udev = interface_to_usbdev(intf); + alt = READ_ONCE(intf->cur_altsetting); + +- return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X" ++ return sysfs_emit(buf, ++ "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X" + "ic%02Xisc%02Xip%02Xin%02X\n", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), +@@ -1150,7 +1151,7 @@ static ssize_t supports_autosuspend_show(struct device *dev, + s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend); + device_unlock(dev); + +- return sprintf(buf, "%u\n", s); ++ return sysfs_emit(buf, "%u\n", s); + } + static DEVICE_ATTR_RO(supports_autosuspend); + +@@ -1163,7 +1164,7 @@ static ssize_t interface_authorized_show(struct device *dev, + { + struct usb_interface *intf = to_usb_interface(dev); + +- return sprintf(buf, "%u\n", intf->authorized); ++ return sysfs_emit(buf, "%u\n", intf->authorized); + } + + /* +-- +2.35.3 + diff --git a/patches.suse/usb-dwc3-pci-Add-support-for-Intel-Raptor-Lake.patch b/patches.suse/usb-dwc3-pci-Add-support-for-Intel-Raptor-Lake.patch index a727548..ac0a3aa 100644 --- a/patches.suse/usb-dwc3-pci-Add-support-for-Intel-Raptor-Lake.patch +++ b/patches.suse/usb-dwc3-pci-Add-support-for-Intel-Raptor-Lake.patch @@ -4,7 +4,7 @@ Date: Mon, 15 Aug 2022 15:33:34 +0300 Subject: [PATCH] usb: dwc3: pci: Add support for Intel Raptor Lake Git-commit: bad0d1d726ace2db9e0f39c62b173bc7cc43dd6a Patch-mainline: v6.0-rc4 -References: git-fixes +References: jsc#PED-1715 This adds the necessary PCI device ID for the controller inside the Intel Raptor Lake CPU block. The controllers that diff --git a/patches.suse/usb-host-xhci-drop-redundant-checks.patch b/patches.suse/usb-host-xhci-drop-redundant-checks.patch new file mode 100644 index 0000000..25abcb6 --- /dev/null +++ b/patches.suse/usb-host-xhci-drop-redundant-checks.patch @@ -0,0 +1,48 @@ +From 133da4b470ecb1d696f07d18753cc482fa0b7580 Mon Sep 17 00:00:00 2001 +From: Sergey Shtylyov +Date: Wed, 16 Feb 2022 11:51:52 +0200 +Subject: [PATCH] usb: host: xhci: drop redundant checks +Git-commit: 133da4b470ecb1d696f07d18753cc482fa0b7580 +References: jsc#PED-531 +Patch-mainline: v5.18-rc1 + +In xhci_endpoint_{disable|reset}() the expression '&vdev->eps[ep_index]' +just cannot be NULL, so the checks have no sense at all... + +Found by Linux Verification Center (linuxtesting.org) with the SVACE static +analysis tool. + +Signed-off-by: Sergey Shtylyov +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220216095153.1303105-9-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 2a58677d9b7a..33bae434aa94 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -3150,8 +3150,6 @@ static void xhci_endpoint_disable(struct usb_hcd *hcd, + + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = &vdev->eps[ep_index]; +- if (!ep) +- goto done; + + /* wait for hub_tt_work to finish clearing hub TT */ + if (ep->ep_state & EP_CLEARING_TT) { +@@ -3209,8 +3207,6 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, + return; + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = &vdev->eps[ep_index]; +- if (!ep) +- return; + + /* Bail out if toggle is already being cleared by a endpoint reset */ + spin_lock_irqsave(&xhci->lock, flags); +-- +2.35.3 + diff --git a/patches.suse/usb-host-xhci-plat-create-shared-hcd-after-having-ad.patch b/patches.suse/usb-host-xhci-plat-create-shared-hcd-after-having-ad.patch new file mode 100644 index 0000000..439140e --- /dev/null +++ b/patches.suse/usb-host-xhci-plat-create-shared-hcd-after-having-ad.patch @@ -0,0 +1,106 @@ +From 0cf1ea040a7e2cae4776216d16d33d3898ea58de Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Thu, 12 May 2022 01:04:44 +0300 +Subject: [PATCH] usb: host: xhci-plat: create shared hcd after having added + main hcd +Git-commit: 0cf1ea040a7e2cae4776216d16d33d3898ea58de +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +This patch is in preparation of an extension where in case of a +root hub with no ports no shared hcd will be created. +Whether one of the root hubs has no ports we figure our in +usb_add_hcd() for the primary hcd. Therefore create the shared hcd +only after this call. + +Signed-off-by: Heiner Kallweit +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220511220450.85367-4-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-plat.c | 29 ++++++++++++++++------------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 649ffd861b44..5d752b384de2 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -283,12 +283,6 @@ static int xhci_plat_probe(struct platform_device *pdev) + device_set_wakeup_capable(&pdev->dev, true); + + xhci->main_hcd = hcd; +- xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, +- dev_name(&pdev->dev), hcd); +- if (!xhci->shared_hcd) { +- ret = -ENOMEM; +- goto disable_clk; +- } + + /* imod_interval is the interrupt moderation value in nanoseconds. */ + xhci->imod_interval = 40000; +@@ -313,16 +307,16 @@ static int xhci_plat_probe(struct platform_device *pdev) + if (IS_ERR(hcd->usb_phy)) { + ret = PTR_ERR(hcd->usb_phy); + if (ret == -EPROBE_DEFER) +- goto put_usb3_hcd; ++ goto disable_clk; + hcd->usb_phy = NULL; + } else { + ret = usb_phy_init(hcd->usb_phy); + if (ret) +- goto put_usb3_hcd; ++ goto disable_clk; + } + + hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); +- xhci->shared_hcd->tpl_support = hcd->tpl_support; ++ + if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) + hcd->skip_phy_initialization = 1; + +@@ -333,12 +327,21 @@ static int xhci_plat_probe(struct platform_device *pdev) + if (ret) + goto disable_usb_phy; + ++ xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, ++ dev_name(&pdev->dev), hcd); ++ if (!xhci->shared_hcd) { ++ ret = -ENOMEM; ++ goto dealloc_usb2_hcd; ++ } ++ ++ xhci->shared_hcd->tpl_support = hcd->tpl_support; ++ + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) + xhci->shared_hcd->can_do_streams = 1; + + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); + if (ret) +- goto dealloc_usb2_hcd; ++ goto put_usb3_hcd; + + device_enable_async_suspend(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); +@@ -352,15 +355,15 @@ static int xhci_plat_probe(struct platform_device *pdev) + return 0; + + ++put_usb3_hcd: ++ usb_put_hcd(xhci->shared_hcd); ++ + dealloc_usb2_hcd: + usb_remove_hcd(hcd); + + disable_usb_phy: + usb_phy_shutdown(hcd->usb_phy); + +-put_usb3_hcd: +- usb_put_hcd(xhci->shared_hcd); +- + disable_clk: + clk_disable_unprepare(xhci->clk); + +-- +2.35.3 + diff --git a/patches.suse/usb-host-xhci-plat-omit-shared-hcd-if-either-root-hu.patch b/patches.suse/usb-host-xhci-plat-omit-shared-hcd-if-either-root-hu.patch new file mode 100644 index 0000000..106cce3 --- /dev/null +++ b/patches.suse/usb-host-xhci-plat-omit-shared-hcd-if-either-root-hu.patch @@ -0,0 +1,37 @@ +From 4736ebd7fcaff1eb8481c140ba494962847d6e0a Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Thu, 12 May 2022 01:04:46 +0300 +Subject: [PATCH] usb: host: xhci-plat: omit shared hcd if either root hub has + no ports +Git-commit: 4736ebd7fcaff1eb8481c140ba494962847d6e0a +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +Activate the just added extension for xhci-plat and omit the shared +hcd if either of the root hubs has no ports. + +Signed-off-by: Heiner Kallweit +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220511220450.85367-6-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-plat.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index c512ec2148ae..044855818cb1 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -245,6 +245,8 @@ static int xhci_plat_probe(struct platform_device *pdev) + + xhci = hcd_to_xhci(hcd); + ++ xhci->allow_single_roothub = 1; ++ + /* + * Not all platforms have clks so it is not an error if the + * clock do not exist. +-- +2.35.3 + diff --git a/patches.suse/usb-host-xhci-plat-prepare-operation-w-o-shared-hcd.patch b/patches.suse/usb-host-xhci-plat-prepare-operation-w-o-shared-hcd.patch new file mode 100644 index 0000000..e9d2ccf --- /dev/null +++ b/patches.suse/usb-host-xhci-plat-prepare-operation-w-o-shared-hcd.patch @@ -0,0 +1,76 @@ +From e0fe986972f5b6b12086c73569206dd29c520be9 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Thu, 12 May 2022 01:04:45 +0300 +Subject: [PATCH] usb: host: xhci-plat: prepare operation w/o shared hcd +Git-commit: e0fe986972f5b6b12086c73569206dd29c520be9 +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +This patch prepares xhci-plat for the following scenario +- If either of the root hubs has no ports, then omit shared hcd +- Main hcd can be USB3 if there are no USB2 ports + +Signed-off-by: Heiner Kallweit +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220511220450.85367-5-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-plat.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 5d752b384de2..c512ec2148ae 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -180,7 +180,7 @@ static int xhci_plat_probe(struct platform_device *pdev) + struct device *sysdev, *tmpdev; + struct xhci_hcd *xhci; + struct resource *res; +- struct usb_hcd *hcd; ++ struct usb_hcd *hcd, *usb3_hcd; + int ret; + int irq; + struct xhci_plat_priv *priv = NULL; +@@ -327,21 +327,26 @@ static int xhci_plat_probe(struct platform_device *pdev) + if (ret) + goto disable_usb_phy; + +- xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, +- dev_name(&pdev->dev), hcd); +- if (!xhci->shared_hcd) { +- ret = -ENOMEM; +- goto dealloc_usb2_hcd; +- } ++ if (!xhci_has_one_roothub(xhci)) { ++ xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, ++ dev_name(&pdev->dev), hcd); ++ if (!xhci->shared_hcd) { ++ ret = -ENOMEM; ++ goto dealloc_usb2_hcd; ++ } + +- xhci->shared_hcd->tpl_support = hcd->tpl_support; ++ xhci->shared_hcd->tpl_support = hcd->tpl_support; ++ } + +- if (HCC_MAX_PSA(xhci->hcc_params) >= 4) +- xhci->shared_hcd->can_do_streams = 1; ++ usb3_hcd = xhci_get_usb3_hcd(xhci); ++ if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4) ++ usb3_hcd->can_do_streams = 1; + +- ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); +- if (ret) +- goto put_usb3_hcd; ++ if (xhci->shared_hcd) { ++ ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); ++ if (ret) ++ goto put_usb3_hcd; ++ } + + device_enable_async_suspend(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); +-- +2.35.3 + diff --git a/patches.suse/usb-hub-port-add-sysfs-entry-to-switch-port-power.patch b/patches.suse/usb-hub-port-add-sysfs-entry-to-switch-port-power.patch new file mode 100644 index 0000000..30c0038 --- /dev/null +++ b/patches.suse/usb-hub-port-add-sysfs-entry-to-switch-port-power.patch @@ -0,0 +1,345 @@ +From f061f43d7418cb62b8d073e221ec75d3f5b89e17 Mon Sep 17 00:00:00 2001 +From: Michael Grzeschik +Date: Tue, 7 Jun 2022 13:45:22 +0200 +Subject: [PATCH] usb: hub: port: add sysfs entry to switch port power +Git-commit: f061f43d7418cb62b8d073e221ec75d3f5b89e17 +References: jsc#PED-531 +Patch-mainline: v6.0-rc1 + +In some cases the port of an hub needs to be disabled or switched off +and on again. E.g. when the connected device needs to be re-enumerated. +Or it needs to be explicitly disabled while the rest of the usb tree +stays working. + +For this purpose this patch adds an sysfs switch to enable/disable the +port on any hub. In the case the hub is supporting power switching, the +power line will be disabled to the connected device. + +When the port gets disabled, the associated device gets disconnected and +removed from the logical usb tree. No further device will be enumerated +on that port until the port gets enabled again. + +Reviewed-by: Alan Stern +Signed-off-by: Michael Grzeschik +Link: https://lore.kernel.org/r/20220607114522.3359148-1-m.grzeschik@pengutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + Documentation/ABI/testing/sysfs-bus-usb | 11 ++++ + drivers/usb/core/hub.c | 39 ++++++------ + drivers/usb/core/hub.h | 3 + + drivers/usb/core/port.c | 83 +++++++++++++++++++++++++ + 4 files changed, 117 insertions(+), 19 deletions(-) + +diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb +index 7efe31ed3a25..568103d3376e 100644 +--- a/Documentation/ABI/testing/sysfs-bus-usb ++++ b/Documentation/ABI/testing/sysfs-bus-usb +@@ -253,6 +253,17 @@ Description: + only if the system firmware is capable of describing the + connection between a port and its connector. + ++What: /sys/bus/usb/devices/...//port/disable ++Date: June 2022 ++Contact: Michael Grzeschik ++Description: ++ This file controls the state of a USB port, including ++ Vbus power output (but only on hubs that support ++ power switching -- most hubs don't support it). If ++ a port is disabled, the port is unusable: Devices ++ attached to the port will not be detected, initialized, ++ or enumerated. ++ + What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout + Date: May 2013 + Contact: Mathias Nyman +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 68e9121c1878..ba406b8d688d 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -613,7 +613,7 @@ static int hub_ext_port_status(struct usb_hub *hub, int port1, int type, + return ret; + } + +-static int hub_port_status(struct usb_hub *hub, int port1, ++int usb_hub_port_status(struct usb_hub *hub, int port1, + u16 *status, u16 *change) + { + return hub_ext_port_status(hub, port1, HUB_PORT_STATUS, +@@ -1126,7 +1126,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + u16 portstatus, portchange; + + portstatus = portchange = 0; +- status = hub_port_status(hub, port1, &portstatus, &portchange); ++ status = usb_hub_port_status(hub, port1, &portstatus, &portchange); + if (status) + goto abort; + +@@ -2855,7 +2855,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, + &portstatus, &portchange, + &ext_portstatus); + else +- ret = hub_port_status(hub, port1, &portstatus, ++ ret = usb_hub_port_status(hub, port1, &portstatus, + &portchange); + if (ret < 0) + return ret; +@@ -2956,7 +2956,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1, + * If the caller hasn't explicitly requested a warm reset, + * double check and see if one is needed. + */ +- if (hub_port_status(hub, port1, &portstatus, &portchange) == 0) ++ if (usb_hub_port_status(hub, port1, &portstatus, ++ &portchange) == 0) + if (hub_port_warm_reset_required(hub, port1, + portstatus)) + warm = true; +@@ -3008,7 +3009,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, + * If a USB 3.0 device migrates from reset to an error + * state, re-issue the warm reset. + */ +- if (hub_port_status(hub, port1, ++ if (usb_hub_port_status(hub, port1, + &portstatus, &portchange) < 0) + goto done; + +@@ -3074,7 +3075,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, + } + + /* Check if a port is power on */ +-static int port_is_power_on(struct usb_hub *hub, unsigned portstatus) ++int usb_port_is_power_on(struct usb_hub *hub, unsigned int portstatus) + { + int ret = 0; + +@@ -3140,13 +3141,13 @@ static int check_port_resume_type(struct usb_device *udev, + } + /* Is the device still present? */ + else if (status || port_is_suspended(hub, portstatus) || +- !port_is_power_on(hub, portstatus)) { ++ !usb_port_is_power_on(hub, portstatus)) { + if (status >= 0) + status = -ENODEV; + } else if (!(portstatus & USB_PORT_STAT_CONNECTION)) { + if (retries--) { + usleep_range(200, 300); +- status = hub_port_status(hub, port1, &portstatus, ++ status = usb_hub_port_status(hub, port1, &portstatus, + &portchange); + goto retry; + } +@@ -3409,7 +3410,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) + u16 portstatus, portchange; + + portstatus = portchange = 0; +- ret = hub_port_status(hub, port1, &portstatus, ++ ret = usb_hub_port_status(hub, port1, &portstatus, + &portchange); + + dev_dbg(&port_dev->dev, +@@ -3587,13 +3588,13 @@ static int wait_for_connected(struct usb_device *udev, + while (delay_ms < 2000) { + if (status || *portstatus & USB_PORT_STAT_CONNECTION) + break; +- if (!port_is_power_on(hub, *portstatus)) { ++ if (!usb_port_is_power_on(hub, *portstatus)) { + status = -ENODEV; + break; + } + msleep(20); + delay_ms += 20; +- status = hub_port_status(hub, port1, portstatus, portchange); ++ status = usb_hub_port_status(hub, port1, portstatus, portchange); + } + dev_dbg(&udev->dev, "Waited %dms for CONNECT\n", delay_ms); + return status; +@@ -3653,7 +3654,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) + usb_lock_port(port_dev); + + /* Skip the initial Clear-Suspend step for a remote wakeup */ +- status = hub_port_status(hub, port1, &portstatus, &portchange); ++ status = usb_hub_port_status(hub, port1, &portstatus, &portchange); + if (status == 0 && !port_is_suspended(hub, portstatus)) { + if (portchange & USB_PORT_STAT_C_SUSPEND) + pm_wakeup_event(&udev->dev, 0); +@@ -3678,7 +3679,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) + * stop resume signaling. Then finish the resume + * sequence. + */ +- status = hub_port_status(hub, port1, &portstatus, &portchange); ++ status = usb_hub_port_status(hub, port1, &portstatus, &portchange); + } + + SuspendCleared: +@@ -3791,7 +3792,7 @@ static int check_ports_changed(struct usb_hub *hub) + u16 portstatus, portchange; + int status; + +- status = hub_port_status(hub, port1, &portstatus, &portchange); ++ status = usb_hub_port_status(hub, port1, &portstatus, &portchange); + if (!status && portchange) + return 1; + } +@@ -4554,7 +4555,7 @@ int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected) + struct usb_port *port_dev = hub->ports[port1 - 1]; + + for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { +- ret = hub_port_status(hub, port1, &portstatus, &portchange); ++ ret = usb_hub_port_status(hub, port1, &portstatus, &portchange); + if (ret < 0) + return ret; + +@@ -5240,7 +5241,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, + * but only if the port isn't owned by someone else. + */ + if (hub_is_port_power_switchable(hub) +- && !port_is_power_on(hub, portstatus) ++ && !usb_port_is_power_on(hub, portstatus) + && !port_dev->port_owner) + set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + +@@ -5557,7 +5558,7 @@ static void port_event(struct usb_hub *hub, int port1) + clear_bit(port1, hub->event_bits); + clear_bit(port1, hub->wakeup_bits); + +- if (hub_port_status(hub, port1, &portstatus, &portchange) < 0) ++ if (usb_hub_port_status(hub, port1, &portstatus, &portchange) < 0) + return; + + if (portchange & USB_PORT_STAT_C_CONNECTION) { +@@ -5594,7 +5595,7 @@ static void port_event(struct usb_hub *hub, int port1) + USB_PORT_FEAT_C_OVER_CURRENT); + msleep(100); /* Cool down */ + hub_power_on(hub, true); +- hub_port_status(hub, port1, &status, &unused); ++ usb_hub_port_status(hub, port1, &status, &unused); + if (status & USB_PORT_STAT_OVERCURRENT) + dev_err(&port_dev->dev, "over-current condition\n"); + } +@@ -5638,7 +5639,7 @@ static void port_event(struct usb_hub *hub, int port1) + u16 unused; + + msleep(20); +- hub_port_status(hub, port1, &portstatus, &unused); ++ usb_hub_port_status(hub, port1, &portstatus, &unused); + dev_dbg(&port_dev->dev, "Wait for inactive link disconnect detect\n"); + continue; + } else if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION) +diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h +index 22ea1f4f2d66..3fcb38099ce3 100644 +--- a/drivers/usb/core/hub.h ++++ b/drivers/usb/core/hub.h +@@ -121,6 +121,9 @@ extern int hub_port_debounce(struct usb_hub *hub, int port1, + bool must_be_connected); + extern int usb_clear_port_feature(struct usb_device *hdev, + int port1, int feature); ++extern int usb_hub_port_status(struct usb_hub *hub, int port1, ++ u16 *status, u16 *change); ++extern int usb_port_is_power_on(struct usb_hub *hub, unsigned int portstatus); + + static inline bool hub_is_port_power_switchable(struct usb_hub *hub) + { +diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c +index d5bc36ca5b1f..38c1a4f4fdea 100644 +--- a/drivers/usb/core/port.c ++++ b/drivers/usb/core/port.c +@@ -17,6 +17,88 @@ static int usb_port_block_power_off; + + static const struct attribute_group *port_dev_group[]; + ++static ssize_t disable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct usb_port *port_dev = to_usb_port(dev); ++ struct usb_device *hdev = to_usb_device(dev->parent->parent); ++ struct usb_hub *hub = usb_hub_to_struct_hub(hdev); ++ struct usb_interface *intf = to_usb_interface(hub->intfdev); ++ int port1 = port_dev->portnum; ++ u16 portstatus, unused; ++ bool disabled; ++ int rc; ++ ++ rc = usb_autopm_get_interface(intf); ++ if (rc < 0) ++ return rc; ++ ++ usb_lock_device(hdev); ++ if (hub->disconnected) { ++ rc = -ENODEV; ++ goto out_hdev_lock; ++ } ++ ++ usb_hub_port_status(hub, port1, &portstatus, &unused); ++ disabled = !usb_port_is_power_on(hub, portstatus); ++ ++out_hdev_lock: ++ usb_unlock_device(hdev); ++ usb_autopm_put_interface(intf); ++ ++ if (rc) ++ return rc; ++ ++ return sysfs_emit(buf, "%s\n", disabled ? "1" : "0"); ++} ++ ++static ssize_t disable_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct usb_port *port_dev = to_usb_port(dev); ++ struct usb_device *hdev = to_usb_device(dev->parent->parent); ++ struct usb_hub *hub = usb_hub_to_struct_hub(hdev); ++ struct usb_interface *intf = to_usb_interface(hub->intfdev); ++ int port1 = port_dev->portnum; ++ bool disabled; ++ int rc; ++ ++ rc = strtobool(buf, &disabled); ++ if (rc) ++ return rc; ++ ++ rc = usb_autopm_get_interface(intf); ++ if (rc < 0) ++ return rc; ++ ++ usb_lock_device(hdev); ++ if (hub->disconnected) { ++ rc = -ENODEV; ++ goto out_hdev_lock; ++ } ++ ++ if (disabled && port_dev->child) ++ usb_disconnect(&port_dev->child); ++ ++ rc = usb_hub_set_port_power(hdev, hub, port1, !disabled); ++ ++ if (disabled) { ++ usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); ++ if (!port_dev->is_superspeed) ++ usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); ++ } ++ ++ if (!rc) ++ rc = count; ++ ++out_hdev_lock: ++ usb_unlock_device(hdev); ++ usb_autopm_put_interface(intf); ++ ++ return rc; ++} ++static DEVICE_ATTR_RW(disable); ++ + static ssize_t location_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -153,6 +235,7 @@ static struct attribute *port_dev_attrs[] = { + &dev_attr_location.attr, + &dev_attr_quirks.attr, + &dev_attr_over_current_count.attr, ++ &dev_attr_disable.attr, + NULL, + }; + +-- +2.35.3 + diff --git a/patches.suse/usb-typec-intel_pmc_mux-Add-new-ACPI-ID-for-Meteor-L.patch b/patches.suse/usb-typec-intel_pmc_mux-Add-new-ACPI-ID-for-Meteor-L.patch index e98c8f7..7a2e1f4 100644 --- a/patches.suse/usb-typec-intel_pmc_mux-Add-new-ACPI-ID-for-Meteor-L.patch +++ b/patches.suse/usb-typec-intel_pmc_mux-Add-new-ACPI-ID-for-Meteor-L.patch @@ -4,7 +4,7 @@ Date: Tue, 16 Aug 2022 13:16:24 +0300 Subject: [PATCH] usb: typec: intel_pmc_mux: Add new ACPI ID for Meteor Lake IOM device Git-commit: 1b1b672cc1d4fb3065dac79efb8901bd6244ef69 Patch-mainline: v6.0-rc4 -References: git-fixes +References: jsc#PED-1211 This adds the necessary ACPI ID for Intel Meteor Lake IOM devices. diff --git a/patches.suse/usb-xhci-fix-minmax.cocci-warnings.patch b/patches.suse/usb-xhci-fix-minmax.cocci-warnings.patch new file mode 100644 index 0000000..5139cd2 --- /dev/null +++ b/patches.suse/usb-xhci-fix-minmax.cocci-warnings.patch @@ -0,0 +1,40 @@ +From 0b86f02d91c82c8348a8f3be960486e14a3dd479 Mon Sep 17 00:00:00 2001 +From: kernel test robot +Date: Wed, 16 Feb 2022 11:51:53 +0200 +Subject: [PATCH] usb: xhci: fix minmax.cocci warnings +Git-commit: 0b86f02d91c82c8348a8f3be960486e14a3dd479 +References: jsc#PED-531 +Patch-mainline: v5.18-rc1 + +Simplify the code using max(). + +Generated by: scripts/coccinelle/misc/minmax.cocci + +Reported-by: kernel test robot +Signed-off-by: kernel test robot +Signed-off-by: Julia Lawall +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220216095153.1303105-10-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-mem.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 7a2dce730e9a..f8c2b6c79543 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -433,8 +433,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, + (TRBS_PER_SEGMENT - 1); + + /* Allocate number of segments we needed, or double the ring size */ +- num_segs = ring->num_segs > num_segs_needed ? +- ring->num_segs : num_segs_needed; ++ num_segs = max(ring->num_segs, num_segs_needed); + + ret = xhci_alloc_segments_for_ring(xhci, &first, &last, + num_segs, ring->cycle_state, ring->type, +-- +2.35.3 + diff --git a/patches.suse/usb-xhci-mtk-add-support-optional-controller-reset.patch b/patches.suse/usb-xhci-mtk-add-support-optional-controller-reset.patch new file mode 100644 index 0000000..a8348eb --- /dev/null +++ b/patches.suse/usb-xhci-mtk-add-support-optional-controller-reset.patch @@ -0,0 +1,49 @@ +From 32b615ed4b7da586eb447212e3d2665b8aa6fdb2 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun +Date: Mon, 23 May 2022 17:04:48 +0800 +Subject: [PATCH] usb: xhci-mtk: add support optional controller reset +Git-commit: 32b615ed4b7da586eb447212e3d2665b8aa6fdb2 +References: jsc#PED-531 +Patch-mainline: v6.0-rc1 + +Add support controller reset via a reset-controller usually in infracfg, +it's different with the software reset by IPPC which only used to reset MAC, +and it will also reset IPPC meanwhile. + +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Chunfeng Yun +Link: https://lore.kernel.org/r/20220523090449.14430-3-chunfeng.yun@mediatek.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-mtk.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index b1045f534a4b..01705e559c42 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "xhci.h" + #include "xhci-mtk.h" +@@ -550,6 +551,12 @@ static int xhci_mtk_probe(struct platform_device *pdev) + if (ret) + goto disable_ldos; + ++ ret = device_reset_optional(dev); ++ if (ret) { ++ dev_err_probe(dev, ret, "failed to reset controller\n"); ++ goto disable_clk; ++ } ++ + hcd = usb_create_hcd(driver, dev, dev_name(dev)); + if (!hcd) { + ret = -ENOMEM; +-- +2.35.3 + diff --git a/patches.suse/x86-PCI-Remove-initialization-of-static-variables-to.patch b/patches.suse/x86-PCI-Remove-initialization-of-static-variables-to.patch new file mode 100644 index 0000000..165ce46 --- /dev/null +++ b/patches.suse/x86-PCI-Remove-initialization-of-static-variables-to.patch @@ -0,0 +1,28 @@ +From: Longji Guo +Date: Fri, 3 Dec 2021 16:07:58 +0800 +Subject: x86/PCI: Remove initialization of static variables to false +Patch-mainline: v5.17-rc1 +Git-commit: 346865f0745357f9f4704614ce1d9a8e6f27dbc4 +References: jsc#PED-1408 + +Remove the initialization of pci_ignore_seg to false which is pointless. + +Link: https://lore.kernel.org/r/20211203080758.962-1-guolongji@uniontech.com +Signed-off-by: Longji Guo +Signed-off-by: Bjorn Helgaas +Acked-by: Lee, Chun-Yi +--- + arch/x86/pci/acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/pci/acpi.c ++++ b/arch/x86/pci/acpi.c +@@ -20,7 +20,7 @@ struct pci_root_info { + }; + + static bool pci_use_crs = true; +-static bool pci_ignore_seg = false; ++static bool pci_ignore_seg; + + static int __init set_use_crs(const struct dmi_system_id *id) + { diff --git a/patches.suse/x86-clk-clk-fch-Add-support-for-newer-family-of-AMD-.patch b/patches.suse/x86-clk-clk-fch-Add-support-for-newer-family-of-AMD-.patch new file mode 100644 index 0000000..9b66a89 --- /dev/null +++ b/patches.suse/x86-clk-clk-fch-Add-support-for-newer-family-of-AMD-.patch @@ -0,0 +1,135 @@ +From: Ajit Kumar Pandey +Date: Sun, 12 Dec 2021 23:35:23 +0530 +Subject: x86: clk: clk-fch: Add support for newer family of AMD's SOC +Patch-mainline: v5.17-rc1 +Git-commit: 65ab884ac9cd8454435b5159ade540004f1a24fe +References: jsc#PED-1408 + +FCH controller clock configuration slightly differs across AMD's +SOC architectures. Newer family of SOC only support a 48MHz fix +clock while stoney SOC family has a clk_mux to choose 48MHz and +25 MHz clk. At present fixed clk support is only enabled for RV +architecture using "is-rv" device property initialized from boot +loader. This limit 48MHz fixed clock gate support to RV platform +unless we add similar device property in boot loader for other +architectures. + +Add pci_device_id table with Stoney platform id and replace "is-rv" +device property check with pci id match to add clk mux support with +25MHz and 48MHz clk support based on clk mux selection. This enable +48Mhz fixed fch clock support by default on all newer SOC's except +stoney. Also replace RV with FIXED as a generic naming conventions +across all platforms and changed module description. + +Signed-off-by: Ajit Kumar Pandey +Reviewed-by: Mario Limonciello +Link: https://lore.kernel.org/r/20211212180527.1641362-2-AjitKumar.Pandey@amd.com +Signed-off-by: Stephen Boyd +Acked-by: Lee, Chun-Yi +--- + drivers/clk/x86/clk-fch.c | 42 +++++++++++++++++++++++++++++++----------- + 1 file changed, 31 insertions(+), 11 deletions(-) + +--- a/drivers/clk/x86/clk-fch.c ++++ b/drivers/clk/x86/clk-fch.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: MIT + /* +- * clock framework for AMD Stoney based clocks ++ * clock framework for AMD FCH controller block + * + * Copyright 2018 Advanced Micro Devices, Inc. + */ +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -26,22 +27,37 @@ + #define ST_CLK_GATE 3 + #define ST_MAX_CLKS 4 + +-#define RV_CLK_48M 0 +-#define RV_CLK_GATE 1 +-#define RV_MAX_CLKS 2 ++#define CLK_48M_FIXED 0 ++#define CLK_GATE_FIXED 1 ++#define CLK_MAX_FIXED 2 ++ ++/* List of supported CPU ids for clk mux with 25Mhz clk support */ ++#define AMD_CPU_ID_ST 0x1576 + + static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" }; + static struct clk_hw *hws[ST_MAX_CLKS]; + ++static const struct pci_device_id fch_pci_ids[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_ST) }, ++ { } ++}; ++ + static int fch_clk_probe(struct platform_device *pdev) + { + struct fch_clk_data *fch_data; ++ struct pci_dev *rdev; + + fch_data = dev_get_platdata(&pdev->dev); + if (!fch_data || !fch_data->base) + return -EINVAL; + +- if (!fch_data->is_rv) { ++ rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); ++ if (!rdev) { ++ dev_err(&pdev->dev, "FCH device not found\n"); ++ return -ENODEV; ++ } ++ ++ if (pci_match_id(fch_pci_ids, rdev)) { + hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", + NULL, 0, 48000000); + hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", +@@ -61,32 +77,36 @@ static int fch_clk_probe(struct platform + devm_clk_hw_register_clkdev(&pdev->dev, hws[ST_CLK_GATE], + "oscout1", NULL); + } else { +- hws[RV_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", ++ hws[CLK_48M_FIXED] = clk_hw_register_fixed_rate(NULL, "clk48MHz", + NULL, 0, 48000000); + +- hws[RV_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", ++ hws[CLK_GATE_FIXED] = clk_hw_register_gate(NULL, "oscout1", + "clk48MHz", 0, fch_data->base + MISCCLKCNTL1, + OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL); + +- devm_clk_hw_register_clkdev(&pdev->dev, hws[RV_CLK_GATE], ++ devm_clk_hw_register_clkdev(&pdev->dev, hws[CLK_GATE_FIXED], + "oscout1", NULL); + } + ++ pci_dev_put(rdev); + return 0; + } + + static int fch_clk_remove(struct platform_device *pdev) + { + int i, clks; +- struct fch_clk_data *fch_data; ++ struct pci_dev *rdev; + +- fch_data = dev_get_platdata(&pdev->dev); ++ rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); ++ if (!rdev) ++ return -ENODEV; + +- clks = fch_data->is_rv ? RV_MAX_CLKS : ST_MAX_CLKS; ++ clks = pci_match_id(fch_pci_ids, rdev) ? CLK_MAX_FIXED : ST_MAX_CLKS; + + for (i = 0; i < clks; i++) + clk_hw_unregister(hws[i]); + ++ pci_dev_put(rdev); + return 0; + } + diff --git a/patches.suse/xhci-Allocate-separate-command-structures-for-each-L.patch b/patches.suse/xhci-Allocate-separate-command-structures-for-each-L.patch new file mode 100644 index 0000000..a8f3df3 --- /dev/null +++ b/patches.suse/xhci-Allocate-separate-command-structures-for-each-L.patch @@ -0,0 +1,136 @@ +From 5c2a380a5aa8c15985359904b6d47466528d2993 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Wed, 16 Feb 2022 11:51:50 +0200 +Subject: [PATCH] xhci: Allocate separate command structures for each LPM + command +Git-commit: 5c2a380a5aa8c15985359904b6d47466528d2993 +References: git-fixes +Patch-mainline: v5.18-rc1 + +Every lpm commmand, both for USB 2 and USB 3 devies used the same +xhci->lpm_command structure to change max exit latency. + +xhci->lpm_command is only protected by a hcd->bandwidth mutex, which is +not enoungh as USB 2 and USB 3 devices are behind separate HCDs. + +Simplify code and avoid unnecessary locking risks by allocating +separate command structures for each lpm command, just like with +all other commands. + +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220216095153.1303105-7-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-mem.c | 7 ------- + drivers/usb/host/xhci.c | 21 ++++++++------------- + drivers/usb/host/xhci.h | 2 -- + 3 files changed, 8 insertions(+), 22 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 0e312066c5c6..7a2dce730e9a 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1846,9 +1846,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) + xhci->event_ring = NULL; + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed event ring"); + +- if (xhci->lpm_command) +- xhci_free_command(xhci, xhci->lpm_command); +- xhci->lpm_command = NULL; + if (xhci->cmd_ring) + xhci_ring_free(xhci, xhci->cmd_ring); + xhci->cmd_ring = NULL; +@@ -2488,10 +2485,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + "// Setting command ring address to 0x%016llx", val_64); + xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); + +- xhci->lpm_command = xhci_alloc_command_with_ctx(xhci, true, flags); +- if (!xhci->lpm_command) +- goto fail; +- + /* Reserve one command ring TRB for disabling LPM. + * Since the USB core grabs the shared usb_bus bandwidth mutex before + * disabling LPM, we only need to reserve one TRB for all devices. +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 17a561abfab7..2a58677d9b7a 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -4344,6 +4344,10 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, + unsigned long flags; + int ret; + ++ command = xhci_alloc_command_with_ctx(xhci, true, GFP_KERNEL); ++ if (!command) ++ return -ENOMEM; ++ + spin_lock_irqsave(&xhci->lock, flags); + + virt_dev = xhci->devs[udev->slot_id]; +@@ -4360,10 +4364,10 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, + } + + /* Attempt to issue an Evaluate Context command to change the MEL. */ +- command = xhci->lpm_command; + ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx); + if (!ctrl_ctx) { + spin_unlock_irqrestore(&xhci->lock, flags); ++ xhci_free_command(xhci, command); + xhci_warn(xhci, "%s: Could not get input context, bad type.\n", + __func__); + return -ENOMEM; +@@ -4390,6 +4394,9 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, + virt_dev->current_mel = max_exit_latency; + spin_unlock_irqrestore(&xhci->lock, flags); + } ++ ++ xhci_free_command(xhci, command); ++ + return ret; + } + +@@ -4510,18 +4517,8 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, + exit_latency = xhci_besl_encoding[hird]; + spin_unlock_irqrestore(&xhci->lock, flags); + +- /* USB 3.0 code dedicate one xhci->lpm_command->in_ctx +- * input context for link powermanagement evaluate +- * context commands. It is protected by hcd->bandwidth +- * mutex and is shared by all devices. We need to set +- * the max ext latency in USB 2 BESL LPM as well, so +- * use the same mutex and xhci_change_max_exit_latency() +- */ +- mutex_lock(hcd->bandwidth_mutex); + ret = xhci_change_max_exit_latency(xhci, udev, + exit_latency); +- mutex_unlock(hcd->bandwidth_mutex); +- + if (ret < 0) + return ret; + spin_lock_irqsave(&xhci->lock, flags); +@@ -4549,9 +4546,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, + readl(pm_addr); + if (udev->usb2_hw_lpm_besl_capable) { + spin_unlock_irqrestore(&xhci->lock, flags); +- mutex_lock(hcd->bandwidth_mutex); + xhci_change_max_exit_latency(xhci, udev, 0); +- mutex_unlock(hcd->bandwidth_mutex); + readl_poll_timeout(ports[port_num]->addr, pm_val, + (pm_val & PORT_PLS_MASK) == XDEV_U0, + 100, 10000); +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 5a75fe563123..8a0026ee9524 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1812,8 +1812,6 @@ struct xhci_hcd { + /* slot enabling and address device helpers */ + /* these are not thread safe so use mutex */ + struct mutex mutex; +- /* For USB 3.0 LPM enable/disable. */ +- struct xhci_command *lpm_command; + /* Internal mirror of the HW's dcbaa */ + struct xhci_virt_device *devs[MAX_HC_SLOTS]; + /* For keeping track of bandwidth domains per roothub. */ +-- +2.35.3 + diff --git a/patches.suse/xhci-Don-t-defer-primary-roothub-registration-if-the.patch b/patches.suse/xhci-Don-t-defer-primary-roothub-registration-if-the.patch new file mode 100644 index 0000000..7c0363b --- /dev/null +++ b/patches.suse/xhci-Don-t-defer-primary-roothub-registration-if-the.patch @@ -0,0 +1,57 @@ +From 1bd8bb7d2dfc44509acf729e636523c3c2b729df Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Mon, 16 May 2022 12:48:50 +0300 +Subject: [PATCH] xhci: Don't defer primary roothub registration if there is + only one roothub +Git-commit: 1bd8bb7d2dfc44509acf729e636523c3c2b729df +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +The support for xHCI controllers with only one roothub, and the code +to defer primary roothub registation until second roothub got merged +to usb-next for 5.19 at the same time. + +commit 873f323618c2 ("xhci: prepare for operation w/o shared hcd") +commit b7a4f9b5d0e4 ("xhci: Set HCD flag to defer primary roothub +registration") + +These got merged in such a way that the flag to defer primary roothub +registration is set even for xHC controllers with just one roothub. + +Fix this by setting the defer flag in a codepath taken only if we have +two roothubs + +Fixes: 873f323618c2 ("xhci: prepare for operation w/o shared hcd") +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220516094850.19788-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index d957eac59ab3..f0ab63138016 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -696,8 +696,6 @@ int xhci_run(struct usb_hcd *hcd) + xhci_dbg_trace(xhci, trace_xhci_dbg_init, + "Finished %s for main hcd", __func__); + +- set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags); +- + xhci_create_dbc_dev(xhci); + + xhci_debugfs_init(xhci); +@@ -705,6 +703,8 @@ int xhci_run(struct usb_hcd *hcd) + if (xhci_has_one_roothub(xhci)) + return xhci_run_finished(xhci); + ++ set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags); ++ + return 0; + } + EXPORT_SYMBOL_GPL(xhci_run); +-- +2.35.3 + diff --git a/patches.suse/xhci-factor-out-parts-of-xhci_gen_setup.patch b/patches.suse/xhci-factor-out-parts-of-xhci_gen_setup.patch new file mode 100644 index 0000000..6c9fad4 --- /dev/null +++ b/patches.suse/xhci-factor-out-parts-of-xhci_gen_setup.patch @@ -0,0 +1,160 @@ +From 57f23cd0bf2f56d339f810a913a9c0c5abfcfc7e Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Thu, 12 May 2022 01:04:42 +0300 +Subject: [PATCH] xhci: factor out parts of xhci_gen_setup() +Git-commit: 57f23cd0bf2f56d339f810a913a9c0c5abfcfc7e +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +Factoring out parts of xhci_gen_setup() has two motivations: +- When adding functionaliy to omit shared hcd if not needed in a + subsequent patch, we'll have to call xhci_hcd_init_usb3_data() + from two places. +- It reduces size of xhci_gen_setup() and makes it better readable. + +Signed-off-by: Heiner Kallweit +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220511220450.85367-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci.c | 104 +++++++++++++++++++++------------------- + 1 file changed, 54 insertions(+), 50 deletions(-) + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 2be38d9de8df..9f801de6d9e0 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -5209,6 +5209,57 @@ static int xhci_get_frame(struct usb_hcd *hcd) + return readl(&xhci->run_regs->microframe_index) >> 3; + } + ++static void xhci_hcd_init_usb2_data(struct xhci_hcd *xhci, struct usb_hcd *hcd) ++{ ++ xhci->usb2_rhub.hcd = hcd; ++ hcd->speed = HCD_USB2; ++ hcd->self.root_hub->speed = USB_SPEED_HIGH; ++ /* ++ * USB 2.0 roothub under xHCI has an integrated TT, ++ * (rate matching hub) as opposed to having an OHCI/UHCI ++ * companion controller. ++ */ ++ hcd->has_tt = 1; ++} ++ ++static void xhci_hcd_init_usb3_data(struct xhci_hcd *xhci, struct usb_hcd *hcd) ++{ ++ unsigned int minor_rev; ++ ++ /* ++ * Early xHCI 1.1 spec did not mention USB 3.1 capable hosts ++ * should return 0x31 for sbrn, or that the minor revision ++ * is a two digit BCD containig minor and sub-minor numbers. ++ * This was later clarified in xHCI 1.2. ++ * ++ * Some USB 3.1 capable hosts therefore have sbrn 0x30, and ++ * minor revision set to 0x1 instead of 0x10. ++ */ ++ if (xhci->usb3_rhub.min_rev == 0x1) ++ minor_rev = 1; ++ else ++ minor_rev = xhci->usb3_rhub.min_rev / 0x10; ++ ++ switch (minor_rev) { ++ case 2: ++ hcd->speed = HCD_USB32; ++ hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; ++ hcd->self.root_hub->rx_lanes = 2; ++ hcd->self.root_hub->tx_lanes = 2; ++ hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x2; ++ break; ++ case 1: ++ hcd->speed = HCD_USB31; ++ hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; ++ hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x1; ++ break; ++ } ++ xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", ++ minor_rev, minor_rev ? "Enhanced " : ""); ++ ++ xhci->usb3_rhub.hcd = hcd; ++} ++ + int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) + { + struct xhci_hcd *xhci; +@@ -5217,7 +5268,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) + * quirks + */ + struct device *dev = hcd->self.sysdev; +- unsigned int minor_rev; + int retval; + + /* Accept arbitrarily long scatter-gather lists */ +@@ -5232,60 +5282,14 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) + xhci = hcd_to_xhci(hcd); + + if (usb_hcd_is_primary_hcd(hcd)) { +- xhci->main_hcd = hcd; +- xhci->usb2_rhub.hcd = hcd; +- /* Mark the first roothub as being USB 2.0. +- * The xHCI driver will register the USB 3.0 roothub. +- */ +- hcd->speed = HCD_USB2; +- hcd->self.root_hub->speed = USB_SPEED_HIGH; +- /* +- * USB 2.0 roothub under xHCI has an integrated TT, +- * (rate matching hub) as opposed to having an OHCI/UHCI +- * companion controller. +- */ +- hcd->has_tt = 1; ++ xhci_hcd_init_usb2_data(xhci, hcd); + } else { +- /* +- * Early xHCI 1.1 spec did not mention USB 3.1 capable hosts +- * should return 0x31 for sbrn, or that the minor revision +- * is a two digit BCD containig minor and sub-minor numbers. +- * This was later clarified in xHCI 1.2. +- * +- * Some USB 3.1 capable hosts therefore have sbrn 0x30, and +- * minor revision set to 0x1 instead of 0x10. +- */ +- if (xhci->usb3_rhub.min_rev == 0x1) +- minor_rev = 1; +- else +- minor_rev = xhci->usb3_rhub.min_rev / 0x10; +- +- switch (minor_rev) { +- case 2: +- hcd->speed = HCD_USB32; +- hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; +- hcd->self.root_hub->rx_lanes = 2; +- hcd->self.root_hub->tx_lanes = 2; +- hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x2; +- break; +- case 1: +- hcd->speed = HCD_USB31; +- hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; +- hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x1; +- break; +- } +- xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", +- minor_rev, +- minor_rev ? "Enhanced " : ""); +- +- xhci->usb3_rhub.hcd = hcd; +- /* xHCI private pointer was set in xhci_pci_probe for the second +- * registered roothub. +- */ ++ xhci_hcd_init_usb3_data(xhci, hcd); + return 0; + } + + mutex_init(&xhci->mutex); ++ xhci->main_hcd = hcd; + xhci->cap_regs = hcd->regs; + xhci->op_regs = hcd->regs + + HC_LENGTH(readl(&xhci->cap_regs->hc_capbase)); +-- +2.35.3 + diff --git a/patches.suse/xhci-omit-mem-read-just-after-allocation-of-trb.patch b/patches.suse/xhci-omit-mem-read-just-after-allocation-of-trb.patch new file mode 100644 index 0000000..bc20116 --- /dev/null +++ b/patches.suse/xhci-omit-mem-read-just-after-allocation-of-trb.patch @@ -0,0 +1,36 @@ +From f9aeda81c0e8cfd6c5b21401f6206b2c7584f876 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 17 Feb 2022 14:35:49 +0100 +Subject: [PATCH] xhci: omit mem read just after allocation of trb +Git-commit: f9aeda81c0e8cfd6c5b21401f6206b2c7584f876 +References: jsc#PED-531 +Patch-mainline: v5.18-rc1 + +This has been allocated just a few lines earlier with a +zalloc(). The value is known and "|=" is a waste of memory +cycles. + +Acked-by: Mathias Nyman +Signed-off-by: Oliver Neukum +Link: https://lore.kernel.org/r/20220217133549.27961-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-mem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index f8c2b6c79543..cb70d0b31e08 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -57,7 +57,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, + /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */ + if (cycle_state == 0) { + for (i = 0; i < TRBS_PER_SEGMENT; i++) +- seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE); ++ seg->trbs[i].link.control = cpu_to_le32(TRB_CYCLE); + } + seg->dma = dma; + seg->next = NULL; +-- +2.35.3 + diff --git a/patches.suse/xhci-prepare-for-operation-w-o-shared-hcd.patch b/patches.suse/xhci-prepare-for-operation-w-o-shared-hcd.patch new file mode 100644 index 0000000..b0b177c --- /dev/null +++ b/patches.suse/xhci-prepare-for-operation-w-o-shared-hcd.patch @@ -0,0 +1,291 @@ +From 873f323618c202cd0675324a1027dcecc7745d0b Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Thu, 12 May 2022 01:04:43 +0300 +Subject: [PATCH] xhci: prepare for operation w/o shared hcd +Git-commit: 873f323618c202cd0675324a1027dcecc7745d0b +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +This patch prepares xhci for the following scenario: +- If either of the root hubs has no ports, then omit shared hcd +- Main hcd can be USB3 if there are no USB2 ports + +Signed-off-by: Heiner Kallweit +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220511220450.85367-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-hub.c | 3 ++- + drivers/usb/host/xhci-mem.c | 11 ++++---- + drivers/usb/host/xhci.c | 53 ++++++++++++++++++++++++------------- + drivers/usb/host/xhci.h | 26 ++++++++++++++++++ + 4 files changed, 68 insertions(+), 25 deletions(-) + +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index f65f1ba2b592..c54f2bc23d3f 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -707,6 +707,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, + u16 test_mode, u16 wIndex, unsigned long *flags) + __must_hold(&xhci->lock) + { ++ struct usb_hcd *usb3_hcd = xhci_get_usb3_hcd(xhci); + int i, retval; + + /* Disable all Device Slots */ +@@ -727,7 +728,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, + xhci_dbg(xhci, "Disable all port (PP = 0)\n"); + /* Power off USB3 ports*/ + for (i = 0; i < xhci->usb3_rhub.num_ports; i++) +- xhci_set_port_power(xhci, xhci->shared_hcd, i, false, flags); ++ xhci_set_port_power(xhci, usb3_hcd, i, false, flags); + /* Power off USB2 ports*/ + for (i = 0; i < xhci->usb2_rhub.num_ports; i++) + xhci_set_port_power(xhci, xhci->main_hcd, i, false, flags); +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index bbb27ee2c6a3..50bf64dcb186 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1072,7 +1072,7 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, + struct usb_hcd *hcd; + + if (udev->speed >= USB_SPEED_SUPER) +- hcd = xhci->shared_hcd; ++ hcd = xhci_get_usb3_hcd(xhci); + else + hcd = xhci->main_hcd; + +@@ -2362,10 +2362,11 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) + xhci->usb2_rhub.num_ports = USB_MAXCHILDREN; + } + +- /* +- * Note we could have all USB 3.0 ports, or all USB 2.0 ports. +- * Not sure how the USB core will handle a hub with no ports... +- */ ++ if (!xhci->usb2_rhub.num_ports) ++ xhci_info(xhci, "USB2 root hub has no ports\n"); ++ ++ if (!xhci->usb3_rhub.num_ports) ++ xhci_info(xhci, "USB3 root hub has no ports\n"); + + xhci_create_rhub_port_array(xhci, &xhci->usb2_rhub, flags); + xhci_create_rhub_port_array(xhci, &xhci->usb3_rhub, flags); +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 9f801de6d9e0..80db65f19e47 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -486,6 +486,10 @@ static void compliance_mode_recovery(struct timer_list *t) + + xhci = from_timer(xhci, t, comp_mode_recovery_timer); + rhub = &xhci->usb3_rhub; ++ hcd = rhub->hcd; ++ ++ if (!hcd) ++ return; + + for (i = 0; i < rhub->num_ports; i++) { + temp = readl(rhub->ports[i]->addr); +@@ -499,7 +503,6 @@ static void compliance_mode_recovery(struct timer_list *t) + i + 1); + xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, + "Attempting compliance mode recovery"); +- hcd = xhci->shared_hcd; + + if (hcd->state == HC_STATE_SUSPENDED) + usb_hcd_resume_root_hub(hcd); +@@ -612,14 +615,11 @@ static int xhci_run_finished(struct xhci_hcd *xhci) + xhci_halt(xhci); + return -ENODEV; + } +- xhci->shared_hcd->state = HC_STATE_RUNNING; + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; + + if (xhci->quirks & XHCI_NEC_HOST) + xhci_ring_cmd_db(xhci); + +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "Finished xhci_run for USB3 roothub"); + return 0; + } + +@@ -694,7 +694,7 @@ int xhci_run(struct usb_hcd *hcd) + xhci_free_command(xhci, command); + } + xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "Finished xhci_run for USB2 roothub"); ++ "Finished %s for main hcd", __func__); + + set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags); + +@@ -702,6 +702,9 @@ int xhci_run(struct usb_hcd *hcd) + + xhci_debugfs_init(xhci); + ++ if (xhci_has_one_roothub(xhci)) ++ return xhci_run_finished(xhci); ++ + return 0; + } + EXPORT_SYMBOL_GPL(xhci_run); +@@ -994,7 +997,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) + return 0; + + if (hcd->state != HC_STATE_SUSPENDED || +- xhci->shared_hcd->state != HC_STATE_SUSPENDED) ++ (xhci->shared_hcd && xhci->shared_hcd->state != HC_STATE_SUSPENDED)) + return -EINVAL; + + /* Clear root port wake on bits if wakeup not allowed. */ +@@ -1011,15 +1014,18 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) + __func__, hcd->self.busnum); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); +- clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); +- del_timer_sync(&xhci->shared_hcd->rh_timer); ++ if (xhci->shared_hcd) { ++ clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); ++ del_timer_sync(&xhci->shared_hcd->rh_timer); ++ } + + if (xhci->quirks & XHCI_SUSPEND_DELAY) + usleep_range(1000, 1500); + + spin_lock_irq(&xhci->lock); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); +- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); ++ if (xhci->shared_hcd) ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + /* step 1: stop endpoint */ + /* skipped assuming that port suspend has done */ + +@@ -1119,7 +1125,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + msleep(100); + + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); +- set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); ++ if (xhci->shared_hcd) ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + + spin_lock_irq(&xhci->lock); + +@@ -1179,7 +1186,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + + /* Let the USB core know _both_ roothubs lost power. */ + usb_root_hub_lost_power(xhci->main_hcd->self.root_hub); +- usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); ++ if (xhci->shared_hcd) ++ usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); + + xhci_dbg(xhci, "Stop HCD\n"); + xhci_halt(xhci); +@@ -1219,12 +1227,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + + xhci_dbg(xhci, "Start the primary HCD\n"); + retval = xhci_run(hcd->primary_hcd); +- if (!retval) { ++ if (!retval && secondary_hcd) { + xhci_dbg(xhci, "Start the secondary HCD\n"); + retval = xhci_run(secondary_hcd); + } + hcd->state = HC_STATE_SUSPENDED; +- xhci->shared_hcd->state = HC_STATE_SUSPENDED; ++ if (xhci->shared_hcd) ++ xhci->shared_hcd->state = HC_STATE_SUSPENDED; + goto done; + } + +@@ -1262,7 +1271,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + } + + if (pending_portevent) { +- usb_hcd_resume_root_hub(xhci->shared_hcd); ++ if (xhci->shared_hcd) ++ usb_hcd_resume_root_hub(xhci->shared_hcd); + usb_hcd_resume_root_hub(hcd); + } + } +@@ -1281,8 +1291,10 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + /* Re-enable port polling. */ + xhci_dbg(xhci, "%s: starting usb%d port polling.\n", + __func__, hcd->self.busnum); +- set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); +- usb_hcd_poll_rh_status(xhci->shared_hcd); ++ if (xhci->shared_hcd) { ++ set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); ++ usb_hcd_poll_rh_status(xhci->shared_hcd); ++ } + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + usb_hcd_poll_rh_status(hcd); + +@@ -5281,9 +5293,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) + + xhci = hcd_to_xhci(hcd); + +- if (usb_hcd_is_primary_hcd(hcd)) { +- xhci_hcd_init_usb2_data(xhci, hcd); +- } else { ++ if (!usb_hcd_is_primary_hcd(hcd)) { + xhci_hcd_init_usb3_data(xhci, hcd); + return 0; + } +@@ -5364,6 +5374,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) + return retval; + xhci_dbg(xhci, "Called HCD init\n"); + ++ if (xhci_hcd_is_usb3(hcd)) ++ xhci_hcd_init_usb3_data(xhci, hcd); ++ else ++ xhci_hcd_init_usb2_data(xhci, hcd); ++ + xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%016llx\n", + xhci->hcc_params, xhci->hci_version, xhci->quirks); + +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 473a33ce299e..c792a3148e49 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1911,6 +1911,8 @@ struct xhci_hcd { + unsigned hw_lpm_support:1; + /* Broken Suspend flag for SNPS Suspend resume issue */ + unsigned broken_suspend:1; ++ /* Indicates that omitting hcd is supported if root hub has no ports */ ++ unsigned allow_single_roothub:1; + /* cached usb2 extened protocol capabilites */ + u32 *ext_caps; + unsigned int num_ext_caps; +@@ -1966,6 +1968,30 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) + return xhci->main_hcd; + } + ++static inline struct usb_hcd *xhci_get_usb3_hcd(struct xhci_hcd *xhci) ++{ ++ if (xhci->shared_hcd) ++ return xhci->shared_hcd; ++ ++ if (!xhci->usb2_rhub.num_ports) ++ return xhci->main_hcd; ++ ++ return NULL; ++} ++ ++static inline bool xhci_hcd_is_usb3(struct usb_hcd *hcd) ++{ ++ struct xhci_hcd *xhci = hcd_to_xhci(hcd); ++ ++ return hcd == xhci_get_usb3_hcd(xhci); ++} ++ ++static inline bool xhci_has_one_roothub(struct xhci_hcd *xhci) ++{ ++ return xhci->allow_single_roothub && ++ (!xhci->usb2_rhub.num_ports || !xhci->usb3_rhub.num_ports); ++} ++ + #define xhci_dbg(xhci, fmt, args...) \ + dev_dbg(xhci_to_hcd(xhci)->self.controller , fmt , ## args) + #define xhci_err(xhci, fmt, args...) \ +-- +2.35.3 + diff --git a/patches.suse/xhci-prevent-U2-link-power-state-if-Intel-tier-polic.patch b/patches.suse/xhci-prevent-U2-link-power-state-if-Intel-tier-polic.patch new file mode 100644 index 0000000..b64390a --- /dev/null +++ b/patches.suse/xhci-prevent-U2-link-power-state-if-Intel-tier-polic.patch @@ -0,0 +1,73 @@ +From 424140d31ba1c613e7a087caf87723d0273f4dae Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Thu, 12 May 2022 01:04:48 +0300 +Subject: [PATCH] xhci: prevent U2 link power state if Intel tier policy + prevented U1 +Git-commit: 424140d31ba1c613e7a087caf87723d0273f4dae +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +Don't enable U1 or U2 Link powermanagenet (LPM) states for USB3 +devices connected to tier 2 or further hubs. + +For unknown reasons we previously only prevented U1. +Be consistent, and prevent both U1/U2 states if tier policy doesn't +allow LPM. + +Also check the tier policy a bit earlier, and return if U1/U2 is +not allowed. This avoids unnecessary xhci MEL commands. + +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220511220450.85367-8-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index e66a031de5a3..d957eac59ab3 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -4888,9 +4888,6 @@ static int xhci_check_intel_tier_policy(struct usb_device *udev, + struct usb_device *parent; + unsigned int num_hubs; + +- if (state == USB3_LPM_U2) +- return 0; +- + /* Don't enable U1 if the device is on a 2nd tier hub or lower. */ + for (parent = udev->parent, num_hubs = 0; parent->parent; + parent = parent->parent) +@@ -4899,7 +4896,7 @@ static int xhci_check_intel_tier_policy(struct usb_device *udev, + if (num_hubs < 2) + return 0; + +- dev_dbg(&udev->dev, "Disabling U1 link state for device" ++ dev_dbg(&udev->dev, "Disabling U1/U2 link state for device" + " below second-tier hub.\n"); + dev_dbg(&udev->dev, "Plug device into first-tier hub " + "to decrease power consumption.\n"); +@@ -4940,9 +4937,6 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd, + return timeout; + } + +- if (xhci_check_tier_policy(xhci, udev, state) < 0) +- return timeout; +- + /* Gather some information about the currently installed configuration + * and alternate interface settings. + */ +@@ -5049,6 +5043,9 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, + !xhci->devs[udev->slot_id]) + return USB3_LPM_DISABLED; + ++ if (xhci_check_tier_policy(xhci, udev, state) < 0) ++ return USB3_LPM_DISABLED; ++ + hub_encoded_timeout = xhci_calculate_lpm_timeout(hcd, udev, state); + mel = calculate_max_exit_latency(udev, state, hub_encoded_timeout); + if (mel < 0) { +-- +2.35.3 + diff --git a/patches.suse/xhci-use-generic-command-timer-for-stop-endpoint-com.patch b/patches.suse/xhci-use-generic-command-timer-for-stop-endpoint-com.patch new file mode 100644 index 0000000..a8e7f79 --- /dev/null +++ b/patches.suse/xhci-use-generic-command-timer-for-stop-endpoint-com.patch @@ -0,0 +1,271 @@ +From 25355e046d295bc15bb0d235eff019da67e245d3 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Thu, 12 May 2022 01:04:47 +0300 +Subject: [PATCH] xhci: use generic command timer for stop endpoint commands. +Git-commit: 25355e046d295bc15bb0d235eff019da67e245d3 +References: jsc#PED-531 +Patch-mainline: v5.19-rc1 + +The 'stop endpoint' command timer was started when a 'stop endpoint' +command was added to the command queue. +This can trigger unwanted timeouts if there are several pending commands +in the queue that xHC needs to handle first. + +The generic command timer, which was added later than the 'stop endpoint' +timeout timer, times each command currently being handled by xHC hardware. + +A timed out stop endpoint command was treated as a more severe issue than +other failed commands, so the separate stop endpoint timer was left +unchanged. + +Use the generic command timer for stop endpoint commands. Identify if +the timed out command was a stop endpoint command in the generic handler, +and treat it with the same severity as earlier. + +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220511220450.85367-7-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-mem.c | 12 +--- + drivers/usb/host/xhci-ring.c | 107 +++++++++++------------------------ + drivers/usb/host/xhci.c | 7 +-- + drivers/usb/host/xhci.h | 2 - + 4 files changed, 37 insertions(+), 91 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 50bf64dcb186..8c19e151a945 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -782,14 +782,6 @@ void xhci_free_stream_info(struct xhci_hcd *xhci, + + /***************** Device context manipulation *************************/ + +-static void xhci_init_endpoint_timer(struct xhci_hcd *xhci, +- struct xhci_virt_ep *ep) +-{ +- timer_setup(&ep->stop_cmd_timer, xhci_stop_endpoint_command_watchdog, +- 0); +- ep->xhci = xhci; +-} +- + static void xhci_free_tt_info(struct xhci_hcd *xhci, + struct xhci_virt_device *virt_dev, + int slot_id) +@@ -994,11 +986,11 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, + xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id, + (unsigned long long)dev->in_ctx->dma); + +- /* Initialize the cancellation list and watchdog timers for each ep */ ++ /* Initialize the cancellation and bandwidth list for each ep */ + for (i = 0; i < 31; i++) { + dev->eps[i].ep_index = i; + dev->eps[i].vdev = dev; +- xhci_init_endpoint_timer(xhci, &dev->eps[i]); ++ dev->eps[i].xhci = xhci; + INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list); + INIT_LIST_HEAD(&dev->eps[i].bw_endpoint_list); + } +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index f9707997969d..373e0e152854 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -740,14 +740,6 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, + } + } + +-static void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci, +- struct xhci_virt_ep *ep) +-{ +- ep->ep_state &= ~EP_STOP_CMD_PENDING; +- /* Can't del_timer_sync in interrupt */ +- del_timer(&ep->stop_cmd_timer); +-} +- + /* + * Must be called with xhci->lock held in interrupt context, + * releases and re-acquires xhci->lock +@@ -1122,18 +1114,17 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, + reset_type); + if (err) + break; +- xhci_stop_watchdog_timer_in_irq(xhci, ep); ++ ep->ep_state &= ~EP_STOP_CMD_PENDING; + return; + case EP_STATE_RUNNING: + /* Race, HW handled stop ep cmd before ep was running */ + xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n"); + + command = xhci_alloc_command(xhci, false, GFP_ATOMIC); +- if (!command) +- xhci_stop_watchdog_timer_in_irq(xhci, ep); +- +- mod_timer(&ep->stop_cmd_timer, +- jiffies + XHCI_STOP_EP_CMD_TIMEOUT * HZ); ++ if (!command) { ++ ep->ep_state &= ~EP_STOP_CMD_PENDING; ++ return; ++ } + xhci_queue_stop_endpoint(xhci, command, slot_id, ep_index, 0); + xhci_ring_cmd_db(xhci); + +@@ -1142,9 +1133,10 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, + break; + } + } ++ + /* will queue a set TR deq if stopped on a cancelled, uncleared TD */ + xhci_invalidate_cancelled_tds(ep); +- xhci_stop_watchdog_timer_in_irq(xhci, ep); ++ ep->ep_state &= ~EP_STOP_CMD_PENDING; + + /* Otherwise ring the doorbell(s) to restart queued transfers */ + xhci_giveback_invalidated_tds(ep); +@@ -1248,61 +1240,6 @@ void xhci_hc_died(struct xhci_hcd *xhci) + usb_hc_died(xhci_to_hcd(xhci)); + } + +-/* Watchdog timer function for when a stop endpoint command fails to complete. +- * In this case, we assume the host controller is broken or dying or dead. The +- * host may still be completing some other events, so we have to be careful to +- * let the event ring handler and the URB dequeueing/enqueueing functions know +- * through xhci->state. +- * +- * The timer may also fire if the host takes a very long time to respond to the +- * command, and the stop endpoint command completion handler cannot delete the +- * timer before the timer function is called. Another endpoint cancellation may +- * sneak in before the timer function can grab the lock, and that may queue +- * another stop endpoint command and add the timer back. So we cannot use a +- * simple flag to say whether there is a pending stop endpoint command for a +- * particular endpoint. +- * +- * Instead we use a combination of that flag and checking if a new timer is +- * pending. +- */ +-void xhci_stop_endpoint_command_watchdog(struct timer_list *t) +-{ +- struct xhci_virt_ep *ep = from_timer(ep, t, stop_cmd_timer); +- struct xhci_hcd *xhci = ep->xhci; +- unsigned long flags; +- u32 usbsts; +- char str[XHCI_MSG_MAX]; +- +- spin_lock_irqsave(&xhci->lock, flags); +- +- /* bail out if cmd completed but raced with stop ep watchdog timer.*/ +- if (!(ep->ep_state & EP_STOP_CMD_PENDING) || +- timer_pending(&ep->stop_cmd_timer)) { +- spin_unlock_irqrestore(&xhci->lock, flags); +- xhci_dbg(xhci, "Stop EP timer raced with cmd completion, exit"); +- return; +- } +- usbsts = readl(&xhci->op_regs->status); +- +- xhci_warn(xhci, "xHCI host not responding to stop endpoint command.\n"); +- xhci_warn(xhci, "USBSTS:%s\n", xhci_decode_usbsts(str, usbsts)); +- +- ep->ep_state &= ~EP_STOP_CMD_PENDING; +- +- xhci_halt(xhci); +- +- /* +- * handle a stop endpoint cmd timeout as if host died (-ENODEV). +- * In the future we could distinguish between -ENODEV and -ETIMEDOUT +- * and try to recover a -ETIMEDOUT with a host controller reset +- */ +- xhci_hc_died(xhci); +- +- spin_unlock_irqrestore(&xhci->lock, flags); +- xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, +- "xHCI host controller is dead."); +-} +- + static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, + struct xhci_virt_device *dev, + struct xhci_ring *ep_ring, +@@ -1650,9 +1587,12 @@ void xhci_cleanup_command_queue(struct xhci_hcd *xhci) + + void xhci_handle_command_timeout(struct work_struct *work) + { +- struct xhci_hcd *xhci; +- unsigned long flags; +- u64 hw_ring_state; ++ struct xhci_hcd *xhci; ++ unsigned long flags; ++ char str[XHCI_MSG_MAX]; ++ u64 hw_ring_state; ++ u32 cmd_field3; ++ u32 usbsts; + + xhci = container_of(to_delayed_work(work), struct xhci_hcd, cmd_timer); + +@@ -1666,6 +1606,27 @@ void xhci_handle_command_timeout(struct work_struct *work) + spin_unlock_irqrestore(&xhci->lock, flags); + return; + } ++ ++ cmd_field3 = le32_to_cpu(xhci->current_cmd->command_trb->generic.field[3]); ++ usbsts = readl(&xhci->op_regs->status); ++ xhci_dbg(xhci, "Command timeout, USBSTS:%s\n", xhci_decode_usbsts(str, usbsts)); ++ ++ /* Bail out and tear down xhci if a stop endpoint command failed */ ++ if (TRB_FIELD_TO_TYPE(cmd_field3) == TRB_STOP_RING) { ++ struct xhci_virt_ep *ep; ++ ++ xhci_warn(xhci, "xHCI host not responding to stop endpoint command\n"); ++ ++ ep = xhci_get_virt_ep(xhci, TRB_TO_SLOT_ID(cmd_field3), ++ TRB_TO_EP_INDEX(cmd_field3)); ++ if (ep) ++ ep->ep_state &= ~EP_STOP_CMD_PENDING; ++ ++ xhci_halt(xhci); ++ xhci_hc_died(xhci); ++ goto time_out_completed; ++ } ++ + /* mark this command to be cancelled */ + xhci->current_cmd->status = COMP_COMMAND_ABORTED; + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 80db65f19e47..e66a031de5a3 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -1874,9 +1874,6 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + goto done; + } + ep->ep_state |= EP_STOP_CMD_PENDING; +- ep->stop_cmd_timer.expires = jiffies + +- XHCI_STOP_EP_CMD_TIMEOUT * HZ; +- add_timer(&ep->stop_cmd_timer); + xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id, + ep_index, 0); + xhci_ring_cmd_db(xhci); +@@ -3986,10 +3983,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) + trace_xhci_free_dev(slot_ctx); + + /* Stop any wayward timer functions (which may grab the lock) */ +- for (i = 0; i < 31; i++) { ++ for (i = 0; i < 31; i++) + virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING; +- del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); +- } + virt_dev->udev = NULL; + xhci_disable_slot(xhci, udev->slot_id); + xhci_free_virt_device(xhci, udev->slot_id); +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index c792a3148e49..1e3ef8d01567 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -948,8 +948,6 @@ struct xhci_virt_ep { + #define EP_CLEARING_TT (1 << 8) + /* ---- Related to URB cancellation ---- */ + struct list_head cancelled_td_list; +- /* Watchdog timer for stop endpoint command to cancel URBs */ +- struct timer_list stop_cmd_timer; + struct xhci_hcd *xhci; + /* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue + * command. We'll need to update the ring's dequeue segment and dequeue +-- +2.35.3 + diff --git a/series.conf b/series.conf index aac4c9f..5a9465f 100644 --- a/series.conf +++ b/series.conf @@ -8631,6 +8631,7 @@ patches.suse/media-coda-imx-vdoa-Handle-dma_set_coherent_mask-err.patch patches.suse/media-c8sectpfe-fix-double-free-in-configure_channel.patch patches.suse/media-i2c-max9286-Use-dev_err_probe-helper.patch + patches.suse/ACPI-delay-enumeration-of-devices-with-a-_DEP-pointi.patch patches.suse/media-ov8865-Disable-only-enabled-regulators-on-erro.patch patches.suse/media-hantro-Fix-probe-func-error-path.patch patches.suse/net-stmmac-enhance-XDP-ZC-driver-level-switching-per.patch @@ -9187,22 +9188,70 @@ patches.suse/net-openvswitch-Fix-ct_state-nat-flags-for-conns-arr.patch patches.suse/net-mcs7830-handle-usb-read-errors-properly.patch patches.suse/ACPICA-actypes.h-Expand-the-ACPI_ACCESS_-definitions.patch + patches.suse/ACPICA-Use-original-data_table_region-pointer-for-ac.patch + patches.suse/ACPICA-Use-original-pointer-for-virtual-origin-table.patch + patches.suse/ACPICA-Macros-Remove-ACPI_PHYSADDR_TO_PTR.patch + patches.suse/ACPICA-Avoid-subobject-buffer-overflow-when-validati.patch + patches.suse/ACPICA-iASL-Disassembler-Additional-support-for-NHLT.patch + patches.suse/ACPICA-Fix-AEST-Processor-generic-resource-substruct.patch patches.suse/ACPICA-Utilities-Avoid-deleting-the-same-object-twic.patch patches.suse/ACPICA-Executer-Fix-the-REFCLASS_REFOF-case-in-acpi_.patch patches.suse/ACPICA-Fix-wrong-interpretation-of-PCC-address.patch + patches.suse/ACPICA-Add-support-for-PCC-Opregion-special-context-.patch patches.suse/ACPICA-Hardware-Do-not-flush-CPU-cache-when-entering.patch + patches.suse/ACPICA-Change-a-return_ACPI_STATUS-AE_BAD_PARAMETER.patch + patches.suse/ACPICA-Fixed-a-couple-of-warnings-under-MSVC.patch + patches.suse/ACPICA-iASL-Add-TDEL-table-to-both-compiler-disassem.patch + patches.suse/ACPICA-iASL-Add-suppport-for-AGDI-table.patch + patches.suse/ACPICA-iASL-NHLT-table-Specific-Data-field-support.patch + patches.suse/ACPICA-Update-version-to-20211217.patch + patches.suse/ACPI-scan-Do-not-add-device-IDs-from-_CID-if-_HID-is.patch patches.suse/ACPI-scan-Introduce-acpi_fetch_acpi_dev.patch + patches.suse/ACPI-Use-acpi_fetch_acpi_dev-instead-of-acpi_bus_get.patch patches.suse/ACPI-scan-Create-platform-device-for-BCM4752-and-LNV.patch + patches.suse/ACPI-x86-Add-acpi_quirk_skip_-i2c_client-serdev-_enu.patch + patches.suse/ACPI-PM-Avoid-CPU-cache-flush-when-entering-S4.patch + patches.suse/ACPI-PM-Remove-redundant-cache-flushing.patch + patches.suse/ACPI-PM-Emit-debug-messages-when-enabling-disabling-.patch patches.suse/PCI-ACPI-Fix-acpi_pci_osc_control_set-kernel-doc-com.patch + patches.suse/ACPI-EC-Rework-flushing-of-EC-work-while-suspended-t.patch + patches.suse/ACPI-EC-Call-advance_transaction-from-acpi_ec_dispat.patch + patches.suse/ACPI-EC-Pass-one-argument-to-acpi_ec_query.patch + patches.suse/ACPI-EC-Fold-acpi_ec_check_event-into-acpi_ec_event_.patch + patches.suse/ACPI-EC-Rearrange-the-loop-in-acpi_ec_event_handler.patch + patches.suse/ACPI-EC-Simplify-locking-in-acpi_ec_event_handler.patch + patches.suse/ACPI-EC-Rename-three-functions.patch + patches.suse/ACPI-EC-Avoid-queuing-unnecessary-work-in-acpi_ec_su.patch + patches.suse/ACPI-EC-Make-the-event-work-state-machine-visible.patch + patches.suse/ACPI-EC-Relocate-acpi_ec_create_query-and-drop-acpi_.patch + patches.suse/ACPI-EC-Mark-the-ec_sys-write_support-param-as-modul.patch + patches.suse/ACPI-processor-Replace-kernel.h-with-the-necessary-i.patch + patches.suse/ACPI-processor-idle-Use-swap-instead-of-open-coding-.patch + patches.suse/ACPI-processor-idle-Only-flush-cache-on-entering-C3.patch + patches.suse/ACPI-processor-thermal-avoid-cpufreq_get_policy.patch patches.suse/ACPI-x86-Drop-PWM2-device-on-Lenovo-Yoga-Book-from-a.patch patches.suse/ACPI-Change-acpi_device_always_present-into-acpi_dev.patch patches.suse/ACPI-x86-Allow-specifying-acpi_device_override_statu.patch patches.suse/ACPI-x86-Add-not-present-quirk-for-the-PCI0.SDHB.BRC.patch + patches.suse/ACPI-x86-Add-PWM2-on-the-Xiaomi-Mi-Pad-2-to-the-alwa.patch + patches.suse/ACPI-x86-Introduce-an-acpi_quirk_skip_acpi_ac_and_ba.patch + patches.suse/ACPI-x86-Skip-AC-and-battery-devices-on-x86-Android-.patch + patches.suse/ACPI-PMIC-constify-all-struct-intel_pmic_opregion_da.patch + patches.suse/ACPI-PMIC-allow-drivers-to-provide-a-custom-lpat_raw.patch + patches.suse/ACPI-PMIC-xpower-Fix-_TMP-ACPI-errors.patch + patches.suse/ACPI-DPTF-Update-device-ID-in-a-comment.patch + patches.suse/ACPI-tables-Add-AEST-to-the-list-of-known-table-sign.patch + patches.suse/ACPI-NUMA-Process-hotpluggable-memblocks-when-CONFIG.patch + patches.suse/ACPI-sysfs-use-default_groups-in-kobj_type.patch + patches.suse/ACPI-CPPC-Amend-documentation-in-the-comments.patch patches.suse/ACPI-thermal-drop-an-always-true-check.patch patches.suse/ACPI-battery-Add-the-ThinkPad-Not-Charging-quirk.patch patches.suse/cpufreq-intel_pstate-Update-EPP-for-AlderLake-mobile.patch + patches.suse/ACPI-CPPC-Implement-support-for-SystemIO-registers.patch patches.suse/ACPI-CPPC-Check-present-CPUs-for-determining-_CPC-is.patch + patches.suse/ACPI-CPPC-Add-CPPC-enable-register-function.patch patches.suse/PM-runtime-Add-safety-net-to-supplier-device-release.patch + patches.suse/PM-hibernate-Allow-ACPI-hardware-signature-to-be-hon.patch patches.suse/thermal-drivers-imx-Implement-runtime-PM-support.patch patches.suse/thermal-drivers-imx8mm-Enable-ADC-when-enabling-moni.patch patches.suse/thermal-drivers-int340x-Fix-RFIM-mailbox-write-comma.patch @@ -9476,6 +9525,10 @@ patches.suse/usb-gadget-u_audio-Subdevice-0-for-capture-ctls.patch patches.suse/filemap-Remove-PageHWPoison-check-from-next_uptodate_page.patch patches.suse/fuse-Pass-correct-lend-value-to-filemap_write_and_wait_range.patch + patches.suse/ACPI-NFIT-Import-GUID-before-use.patch + patches.suse/ACPI-Keep-sub-table-parsing-infrastructure-available.patch + patches.suse/ACPI-Teach-ACPI-table-parsing-about-the-CEDT-header-.patch + patches.suse/ACPI-Add-a-context-argument-for-table-parsing-handle.patch patches.suse/iommu-arm-smmu-qcom-fix-ttbr0-read patches.suse/iommu-io-pgtable-arm-v7s-add-error-handle-for-page-table-allocation-failure patches.suse/iommu-amd-restore-ga-log-tail-pointer-on-host-resume @@ -9509,6 +9562,9 @@ patches.suse/clk-imx-pllv1-fix-kernel-doc-notation-for-struct-clk.patch patches.suse/clk-Gemini-fix-struct-name-in-kernel-doc.patch patches.suse/clk-Emit-a-stern-warning-with-writable-debugfs-enabl.patch + patches.suse/x86-clk-clk-fch-Add-support-for-newer-family-of-AMD-.patch + patches.suse/drivers-acpi-acpi_apd-Remove-unused-device-property-.patch + patches.suse/ACPI-APD-Add-a-fmw-property-clk-name.patch patches.suse/clk-stm32-Fix-ltdc-s-clock-turn-off-by-clk_disable_u.patch patches.suse/clk-meson-gxbb-Fix-the-SDM_EN-bit-for-MPLL0-on-GXBB.patch patches.suse/clk-imx8mn-Fix-imx8mn_clko1_sels.patch @@ -9734,6 +9790,7 @@ patches.suse/SUNRPC-Fix-sockaddr-handling-in-svcsock_accept_class-trace-points.patch patches.suse/exfat-reuse-exfat_inode_info-variable-instead-of-cal.patch patches.suse/exfat-fix-i_blocks-for-files-truncated-over-4-GiB.patch + patches.suse/x86-PCI-Remove-initialization-of-static-variables-to.patch patches.suse/PCI-pciehp-Fix-infinite-loop-in-IRQ-handler-upon-pow.patch patches.suse/PCI-pciehp-Use-down_read-write_nested-reset_lock-to-.patch patches.suse/PCI-Work-around-Intel-I210-ROM-BAR-overlap-defect.patch @@ -9829,7 +9886,17 @@ patches.suse/cifs-Fix-smb311_update_preauth_hash-kernel-doc-comment.patch patches.suse/cifs-move-superblock-magic-defitions-to-magic-h.patch patches.suse/cifs-fix-FILE_BOTH_DIRECTORY_INFO-definition.patch + patches.suse/ACPI-scan-Change-acpi_scan_init-return-value-type-to.patch + patches.suse/ACPI-scan-Simplify-initialization-of-power-and-sleep.patch + patches.suse/ACPI-scan-Rename-label-in-acpi_scan_init.patch + patches.suse/ACPI-SPCR-check-if-table-serial_port.access_width-is.patch patches.suse/ACPI-APD-Check-for-NULL-pointer-after-calling-devm_i.patch + patches.suse/efi-Introduce-EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.patch + patches.suse/ACPI-Introduce-Platform-Firmware-Runtime-Update-devi.patch + patches.suse/ACPI-Introduce-Platform-Firmware-Runtime-Telemetry-d.patch + patches.suse/ACPI-tools-Introduce-utility-for-firmware-updates-te.patch + patches.suse/ACPI-pfr_update-Fix-return-value-check-in-pfru_write.patch + patches.suse/ACPI-pfr_telemetry-Fix-info-leak-in-pfrt_log_ioctl.patch patches.suse/vfs-fs_context-fix-up-param-length-parsing-in-legacy.patch patches.suse/rpmsg-core-Clean-up-resources-on-announce_create-fai.patch patches.suse/remoteproc-imx_rproc-Fix-a-resource-leak-in-the-remo.patch @@ -9959,6 +10026,9 @@ patches.suse/KVM-VMX-switch-blocked_vcpu_on_cpu_lock-to-raw-spinl.patch patches.suse/selftests-kvm-x86-Fix-the-warning-in-lib-x86_64-proc.patch patches.suse/scripts-dtc-dtx_diff-remove-broken-example-from-help.patch + patches.suse/ACPI-CPPC-Fix-up-I-O-port-access-in-cpc_read.patch + patches.suse/ACPI-CPPC-Drop-redundant-local-variable-from-cpc_rea.patch + patches.suse/ACPI-DPTF-Support-Raptor-Lake.patch patches.suse/scsi-qedf-Fix-potential-dereference-of-NULL-pointer patches.suse/scsi-hisi_sas-Remove-unused-variable-and-check-in-hisi_sas_send_ata_reset_each_phy patches.suse/scsi-ufs-ufs-mediatek-Fix-error-checking-in-ufs_mtk_init_va09_pwr_ctrl @@ -10259,6 +10329,7 @@ patches.suse/ASoC-hdmi-codec-Fix-OOB-memory-accesses.patch patches.suse/ASoC-rt5682-Fix-deadlock-on-resume.patch patches.suse/Input-wm97xx-Simplify-resource-management.patch + patches.suse/ACPI-require-CRC32-to-build.patch patches.suse/random-wake-up-dev-random-writers-after-zap.patch patches.suse/iommu-Fix-potential-use-after-free-during-probe patches.suse/iommu-vt-d-fix-potential-memory-leak-in-intel_setup_irq_remapping @@ -10536,6 +10607,7 @@ patches.suse/mtd-phram-Prevent-divide-by-zero-bug-in-phram_setup.patch patches.suse/mtd-rawnand-gpmi-don-t-leak-PM-reference-in-error-pa.patch patches.suse/mtd-rawnand-brcmnand-Fixed-incorrect-sub-page-ECC-st.patch + patches.suse/ACPI-tables-Quiet-ACPI-table-not-found-warning.patch patches.suse/ACPI-processor-idle-fix-lockup-regression-on-32-bit-.patch patches.suse/NFS-Remove-an-incorrect-revalidation-in-nfs4_update_.patch patches.suse/NFS-Do-not-report-writeback-errors-in-nfs_getattr.patch @@ -10941,6 +11013,7 @@ patches.suse/mm-swap-get-rid-of-livelock-in-swapin-readahead.patch patches.suse/ocfs2-fix-crash-when-initialize-filecheck-kobj-fails.patch patches.suse/selftests-vm-fix-clang-build-error-multiple-output-f.patch + patches.suse/Revert-ACPI-scan-Do-not-add-device-IDs-from-_CID-if-.patch patches.suse/alx-acquire-mutex-for-alx_reinit-in-alx_change_mtu.patch patches.suse/net-phy-marvell-Fix-invalid-comparison-in-the-resume.patch patches.suse/net-packet-fix-slab-out-of-bounds-access-in-packet_r.patch @@ -12252,8 +12325,12 @@ patches.suse/xhci-dbc-Rename-xhci_dbc_init-and-xhci_dbc_exit.patch patches.suse/xhci-dbc-Don-t-call-dbc_tty_init-on-every-dbc-tty-pr.patch patches.suse/xhci-dbgtty-use-IDR-to-support-several-dbc-instances.patch + patches.suse/xhci-Allocate-separate-command-structures-for-each-L.patch patches.suse/usb-remove-Link-Powermanagement-LPM-disable-before-p.patch + patches.suse/usb-host-xhci-drop-redundant-checks.patch + patches.suse/usb-xhci-fix-minmax.cocci-warnings.patch patches.suse/usb-dwc3-pci-Set-the-swnode-from-inside-dwc3_pci_qui.patch + patches.suse/xhci-omit-mem-read-just-after-allocation-of-trb.patch patches.suse/USB-core-Update-kerneldoc-for-usb_get_dev-and-usb_ge.patch patches.suse/usb-typec-tipd-Forward-plug-orientation-to-typec-sub.patch patches.suse/xhci-make-xhci_handshake-timeout-for-xhci_reset-adju.patch @@ -12325,6 +12402,7 @@ patches.suse/phy-amlogic-meson8b-usb2-fix-shared-reset-control-us.patch patches.suse/phy-dphy-Correct-lpx-parameter-and-its-derivatives-t.patch patches.suse/phy-phy-brcm-usb-fixup-BCM4908-support.patch + patches.suse/Revert-usb-host-xhci-mvebu-make-USB-3.0-PHY-optional.patch patches.suse/iio-inkern-apply-consumer-scale-on-IIO_VAL_INT-cases.patch patches.suse/iio-inkern-apply-consumer-scale-when-no-channel-scal.patch patches.suse/iio-inkern-make-a-best-effort-on-offset-calculation.patch @@ -12407,6 +12485,11 @@ patches.suse/NFS-Don-t-loop-forever-in-nfs_do_recoalesce.patch patches.suse/NFSv4-pNFS-Fix-another-issue-with-a-list-iterator-po.patch patches.suse/fs-fix-fd-table-size-alignment-properly.patch + patches.suse/drivers-nvdimm-Add-nvdimm-pmu-structure.patch + patches.suse/drivers-nvdimm-Add-perf-interface-to-expose-nvdimm-p.patch + patches.suse/powerpc-papr_scm-Add-perf-interface-support.patch + patches.suse/drivers-nvdimm-Fix-build-failure-when-CONFIG_PERF_EV.patch + patches.suse/powerpc-papr_scm-Fix-build-failure-when.patch patches.suse/clk-si5341-fix-reported-clk_rate-when-output-divider.patch patches.suse/clk-at91-sama7g5-fix-parents-of-PDMCs-GCLK.patch patches.suse/clk-nxp-Remove-unused-variable.patch @@ -12642,6 +12725,7 @@ patches.suse/SUNRPC-Handle-low-memory-situations-in-call_status.patch patches.suse/SUNRPC-svc_tcp_sendmsg-should-handle-errors-from-xdr.patch patches.suse/lz4-fix-LZ4_decompress_safe_partial-read-out-of-boun.patch + patches.suse/Revert-ACPI-processor-idle-Only-flush-cache-on-enter.patch patches.suse/RDMA-mlx5-Don-t-remove-cache-MRs-when-a-delay-is-nee.patch patches.suse/RDMA-mlx5-Add-a-missing-update-of-cache-last_add.patch patches.suse/IB-cm-Cancel-mad-on-the-DREQ-event-when-the-state-is.patch @@ -12659,6 +12743,7 @@ patches.suse/scsi-lpfc-fix-locking-for-lpfc_sli_iocbq_lookup.patch patches.suse/scsi-virtio-scsi-Eliminate-anonymous-module_init-module_exit patches.suse/scsi-zorro7xx-Fix-a-resource-leak-in-zorro7xx_remove_one + patches.suse/tools-testing-nvdimm-Fix-security_init-symbol-collis.patch patches.suse/sched-core-Fix-forceidle-balancing.patch patches.suse/sched-Teach-the-forced-newidle-balancer-about-CPU-af.patch patches.suse/perf-x86-intel-Update-the-FRONTEND-MSR-mask-on-Sapphire-Rapids.patch @@ -13066,6 +13151,7 @@ patches.suse/timekeeping-Mark-NMI-safe-time-accessors-as-notrace.patch patches.suse/powerpc-pseries-vas-Use-QoS-credits-from-the-userspa.patch patches.suse/powerpc-vdso-Fix-incorrect-CFI-in-gettimeofday.S.patch + patches.suse/powerpc-papr_scm-Fix-buffer-overflow-issue-with-CONF.patch patches.suse/platform-surface-aggregator-Fix-initialization-order.patch patches.suse/virtio-fix-virtio-transitional-ids.patch patches.suse/writeback-Avoid-skipping-inode-writeback.patch @@ -13354,6 +13440,7 @@ patches.suse/media-imon-reorganize-serialization.patch patches.suse/media-cec-adap.c-fix-is_configuring-state.patch patches.suse/media-ov7670-remove-ov7670_power_off-from-ov7670_rem.patch + patches.suse/media-i2c-ov2640-Depend-on-V4L2_ASYNC.patch patches.suse/media-i2c-ov5648-fix-wrong-pointer-passed-to-IS_ERR-.patch patches.suse/media-rkvdec-Stop-overclocking-the-decoder.patch patches.suse/media-rkvdec-h264-Fix-dpb_valid-implementation.patch @@ -13968,6 +14055,7 @@ patches.suse/powerpc-perf-Fix-the-threshold-compare-group-constraint-for-power10.patch patches.suse/powerpc-perf-Fix-the-threshold-compare-group-constra.patch patches.suse/powerpc-xive-Fix-refcount-leak-in-xive_spapr_init.patch + patches.suse/powerpc-papr_scm-Fix-leaking-nvdimm_events_map-eleme.patch patches.suse/powerpc-64s-Add-CPU_FTRS_POWER9_DD2_2-to-CPU_FTRS_AL.patch patches.suse/powerpc-64s-Add-CPU_FTRS_POWER10-to-ALWAYS-mask.patch patches.suse/powerpc-Enable-the-DAWR-on-POWER9-DD2.3-and-above.patch @@ -14163,6 +14251,7 @@ patches.suse/USB-host-isp116x-check-return-value-after-calling-pl.patch patches.suse/USB-storage-karma-fix-rio_karma_init-return.patch patches.suse/usb-musb-Fix-missing-of_node_put-in-omap2430_probe.patch + patches.suse/usb-core-devices-remove-dead-code-under-ifdef-PROC_E.patch patches.suse/usb-dwc3-gadget-Replace-list_for_each_entry_safe-if-.patch patches.suse/drivers-usb-host-Fix-deadlock-in-oxu_bus_suspend.patch patches.suse/usb-dwc3-pci-Fix-pm_runtime_get_sync-error-checking.patch @@ -14173,8 +14262,16 @@ patches.suse/usb-dwc3-gadget-Prevent-repeat-pullup.patch patches.suse/usb-core-hcd-Add-support-for-deferring-roothub-regis.patch patches.suse/xhci-Set-HCD-flag-to-defer-primary-roothub-registrat.patch + patches.suse/xhci-factor-out-parts-of-xhci_gen_setup.patch + patches.suse/xhci-prepare-for-operation-w-o-shared-hcd.patch + patches.suse/usb-host-xhci-plat-create-shared-hcd-after-having-ad.patch + patches.suse/usb-host-xhci-plat-prepare-operation-w-o-shared-hcd.patch + patches.suse/usb-host-xhci-plat-omit-shared-hcd-if-either-root-hu.patch + patches.suse/xhci-use-generic-command-timer-for-stop-endpoint-com.patch + patches.suse/xhci-prevent-U2-link-power-state-if-Intel-tier-polic.patch patches.suse/xhci-Allow-host-runtime-PM-as-default-for-Intel-Alde.patch patches.suse/thunderbolt-Use-different-lane-for-second-DisplayPor.patch + patches.suse/xhci-Don-t-defer-primary-roothub-registration-if-the.patch patches.suse/usb-isp1760-Fix-out-of-bounds-array-access.patch patches.suse/usb-dwc3-gadget-Move-null-pinter-check-to-proper-pla.patch patches.suse/USB-serial-pl2303-fix-type-detection-for-odd-device.patch @@ -14269,6 +14366,7 @@ patches.suse/ixgbe-fix-bcast-packets-Rx-on-VF-after-promisc-remov.patch patches.suse/ixgbe-fix-unexpected-VLAN-Rx-in-promisc-mode-on-VF.patch patches.suse/powerpc-Don-t-select-HAVE_IRQ_EXIT_ON_IRQ_STACK.patch + patches.suse/powerpc-papr_scm-don-t-requests-stats-with-0-sized-s.patch patches.suse/writeback-Fix-inode-i_io_list-not-be-protected-by-in.patch patches.suse/xen-unexport-__init-annotated-xen_xlate_map_balloone.patch patches.suse/Revert-net-mlx5e-Allow-relaxed-ordering-over-VFs.patch @@ -15432,12 +15530,16 @@ patches.suse/usb-ohci-nxp-Fix-refcount-leak-in-ohci_hcd_nxp_probe.patch patches.suse/usb-gadget-tegra-xudc-Fix-error-check-in-tegra_xudc_.patch patches.suse/usb-xhci-tegra-Fix-error-check.patch + patches.suse/usb-xhci-mtk-add-support-optional-controller-reset.patch patches.suse/usb-gadget-uvc-call-uvc-uvcg_warn-on-completed-statu.patch + patches.suse/usb-hub-port-add-sysfs-entry-to-switch-port-power.patch + patches.suse/usb-Avoid-extra-usb-SET_SEL-requests-when-enabling-l.patch patches.suse/usb-dwc3-core-Deprecate-GCTL.CORESOFTRESET.patch patches.suse/usb-dwc3-qcom-Add-helper-functions-to-enable-disable.patch patches.suse/usb-host-ohci-ppc-of-Fix-refcount-leak-bug.patch patches.suse/usb-renesas-Fix-refcount-leak-bug.patch patches.suse/usb-dwc2-gadget-remove-D-pull-up-while-no-vbus-with-.patch + patches.suse/usb-core-sysfs-convert-sysfs-snprintf-to-sysfs_emit.patch patches.suse/dt-bindings-usb-mtk-xhci-Allow-wakeup-interrupt-name.patch patches.suse/usb-host-xhci-use-snprintf-in-xhci_decode_trb.patch patches.suse/gadgetfs-ep_io-wait-until-IRQ-finishes.patch @@ -15449,6 +15551,7 @@ patches.suse/usb-dwc3-qcom-fix-missing-optional-irq-warnings.patch patches.suse/USB-serial-fix-tty-port-initialized-comments.patch patches.suse/USB-HCD-Fix-URB-giveback-issue-in-tasklet-function.patch + patches.suse/usb-core-fix-repeated-words-in-comments.patch patches.suse/usb-cdns3-change-place-of-priv_ep-assignment-in-cdns.patch patches.suse/usb-typec-ucsi-Acknowledge-the-GET_ERROR_STATUS-comm.patch patches.suse/usb-cdns3-Don-t-use-priv_dev-uninitialized-in-cdns3_.patch @@ -16048,6 +16151,8 @@ patches.suse/Input-iforce-wake-up-after-clearing-IFORCE_XMIT_RUNN.patch patches.suse/s390-hugetlb-fix-prepare_hugepage_range-check-for-2-GB-hugepages patches.suse/gpio-pca953x-Add-mutex_lock-for-regcache-sync-in-PM.patch + patches.suse/powerpc-papr_scm-Fix-nvdimm-event-mappings.patch + patches.suse/powerpc-papr_scm-Ensure-rc-is-always-initialized-in-.patch patches.suse/ARM-dts-imx6qdl-kontron-samx6i-remove-duplicated-nod.patch patches.suse/soc-imx-gpcv2-Assert-reset-before-ungating-clock.patch patches.suse/soc-brcmstb-pm-arm-Fix-refcount-leak-and-__iomem-lea.patch @@ -16604,4 +16709,5 @@ # You'd better have a good reason for adding a patch # below here. ######################################################## + patches.suse/arm64-Discard-.note.GNU-stack-section.patch diff --git a/supported.conf b/supported.conf index 7fbce3e..787aa0d 100644 --- a/supported.conf +++ b/supported.conf @@ -262,6 +262,8 @@ - drivers/acpi/ec_sys # Useful for ACPI debugging drivers/acpi/fan # ACPI Fan Driver drivers/acpi/nfit/nfit # fate#320458 fate#320460 fate#319858 fate#320459 fate#320457 + drivers/acpi/pfr_telemetry.ko # ACPI Platform Firmware Runtime Telemetry driver + drivers/acpi/pfr_update.ko # ACPI Platform Firmware Runtime Update Device driver drivers/acpi/platform_profile drivers/acpi/sbs drivers/acpi/sbshc