--- /dev/null
+From 6bbfb39a4aeced79feedb2cefc8bc3a207df6126 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 16:41:45 -0500
+Subject: ACPICA: Add support for MADT online enabled bit
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit 435a8dc8d9b9d91e625901fea5b5695b9b976d84 ]
+
+The online enabled bit on newer ACPI implmentations will indicate
+whether the CPU is hotpluggable.
+
+Link: http://github.com/acpica/acpica/pull/708/
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 128b0c9781c9 ("x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/acpi/actbl2.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
+index a47b32a5cbdeb..074449cb11a17 100644
+--- a/include/acpi/actbl2.h
++++ b/include/acpi/actbl2.h
+@@ -978,6 +978,7 @@ struct acpi_madt_multiproc_wakeup_mailbox {
+ /* MADT Local APIC flags */
+
+ #define ACPI_MADT_ENABLED (1) /* 00: Processor is usable if set */
++#define ACPI_MADT_ONLINE_CAPABLE (2) /* 01: System HW supports enabling processor at runtime */
+
+ /* MADT MPS INTI flags (inti_flags) */
+
+--
+2.42.0
+
--- /dev/null
+From 9017f1c97947dfb8054891f3acdda2dc84964813 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 2 Sep 2023 21:46:20 +0200
+Subject: iio: afe: rescale: Accept only offset channels
+
+From: Linus Walleij <linus.walleij@linaro.org>
+
+[ Upstream commit bee448390e5166d019e9e037194d487ee94399d9 ]
+
+As noted by Jonathan Cameron: it is perfectly legal for a channel
+to have an offset but no scale in addition to the raw interface.
+The conversion will imply that scale is 1:1.
+
+Make rescale_configure_channel() accept just scale, or just offset
+to process a channel.
+
+When a user asks for IIO_CHAN_INFO_OFFSET in rescale_read_raw()
+we now have to deal with the fact that OFFSET could be present
+but SCALE missing. Add code to simply scale 1:1 in this case.
+
+Link: https://lore.kernel.org/linux-iio/CACRpkdZXBjHU4t-GVOCFxRO-AHGxKnxMeHD2s4Y4PuC29gBq6g@mail.gmail.com/
+Fixes: 53ebee949980 ("iio: afe: iio-rescale: Support processed channels")
+Fixes: 9decacd8b3a4 ("iio: afe: rescale: Fix boolean logic bug")
+Reported-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Reviewed-by: Peter Rosin <peda@axentia.se>
+Link: https://lore.kernel.org/r/20230902-iio-rescale-only-offset-v2-1-988b807754c8@linaro.org
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/afe/iio-rescale.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
+index 84f21dc94a2f7..ea0a39882eb25 100644
+--- a/drivers/iio/afe/iio-rescale.c
++++ b/drivers/iio/afe/iio-rescale.c
+@@ -152,8 +152,18 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
+ return ret < 0 ? ret : -EOPNOTSUPP;
+ }
+
+- ret = iio_read_channel_scale(rescale->source, &scale, &scale2);
+- return rescale_process_offset(rescale, ret, scale, scale2,
++ if (iio_channel_has_info(rescale->source->channel,
++ IIO_CHAN_INFO_SCALE)) {
++ ret = iio_read_channel_scale(rescale->source, &scale, &scale2);
++ return rescale_process_offset(rescale, ret, scale, scale2,
++ schan_off, val, val2);
++ }
++
++ /*
++ * If we get here we have no scale so scale 1:1 but apply
++ * rescaler and offset, if any.
++ */
++ return rescale_process_offset(rescale, IIO_VAL_FRACTIONAL, 1, 1,
+ schan_off, val, val2);
+ default:
+ return -EINVAL;
+@@ -218,8 +228,9 @@ static int rescale_configure_channel(struct device *dev,
+ chan->type = rescale->cfg->type;
+
+ if (iio_channel_has_info(schan, IIO_CHAN_INFO_RAW) &&
+- iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE)) {
+- dev_info(dev, "using raw+scale source channel\n");
++ (iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE) ||
++ iio_channel_has_info(schan, IIO_CHAN_INFO_OFFSET))) {
++ dev_info(dev, "using raw+scale/offset source channel\n");
+ } else if (iio_channel_has_info(schan, IIO_CHAN_INFO_PROCESSED)) {
+ dev_info(dev, "using processed channel\n");
+ rescale->chan_processed = true;
+--
+2.42.0
+
--- /dev/null
+From 6d6740c90c77d6aaff27745ab1060378fc23dfc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Feb 2022 21:57:32 -0500
+Subject: iio: afe: rescale: add offset support
+
+From: Liam Beguin <liambeguin@gmail.com>
+
+[ Upstream commit a29c3283653b80b916c5ca5292c5d36415e38e92 ]
+
+This is a preparatory change required for the addition of temperature
+sensing front ends.
+
+Signed-off-by: Liam Beguin <liambeguin@gmail.com>
+Reviewed-by: Peter Rosin <peda@axentia.se>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Link: https://lore.kernel.org/r/20220213025739.2561834-4-liambeguin@gmail.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: bee448390e51 ("iio: afe: rescale: Accept only offset channels")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/afe/iio-rescale.c | 81 +++++++++++++++++++++++++++++++++
+ include/linux/iio/afe/rescale.h | 4 ++
+ 2 files changed, 85 insertions(+)
+
+diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
+index 6cc453ab9c685..84f21dc94a2f7 100644
+--- a/drivers/iio/afe/iio-rescale.c
++++ b/drivers/iio/afe/iio-rescale.c
+@@ -3,6 +3,7 @@
+ * IIO rescale driver
+ *
+ * Copyright (C) 2018 Axentia Technologies AB
++ * Copyright (C) 2022 Liam Beguin <liambeguin@gmail.com>
+ *
+ * Author: Peter Rosin <peda@axentia.se>
+ */
+@@ -47,11 +48,46 @@ int rescale_process_scale(struct rescale *rescale, int scale_type,
+ }
+ }
+
++int rescale_process_offset(struct rescale *rescale, int scale_type,
++ int scale, int scale2, int schan_off,
++ int *val, int *val2)
++{
++ s64 tmp, tmp2;
++
++ switch (scale_type) {
++ case IIO_VAL_FRACTIONAL:
++ tmp = (s64)rescale->offset * scale2;
++ *val = div_s64(tmp, scale) + schan_off;
++ return IIO_VAL_INT;
++ case IIO_VAL_INT:
++ *val = div_s64(rescale->offset, scale) + schan_off;
++ return IIO_VAL_INT;
++ case IIO_VAL_FRACTIONAL_LOG2:
++ tmp = (s64)rescale->offset * (1 << scale2);
++ *val = div_s64(tmp, scale) + schan_off;
++ return IIO_VAL_INT;
++ case IIO_VAL_INT_PLUS_NANO:
++ tmp = (s64)rescale->offset * 1000000000LL;
++ tmp2 = ((s64)scale * 1000000000LL) + scale2;
++ *val = div64_s64(tmp, tmp2) + schan_off;
++ return IIO_VAL_INT;
++ case IIO_VAL_INT_PLUS_MICRO:
++ tmp = (s64)rescale->offset * 1000000LL;
++ tmp2 = ((s64)scale * 1000000LL) + scale2;
++ *val = div64_s64(tmp, tmp2) + schan_off;
++ return IIO_VAL_INT;
++ default:
++ return -EOPNOTSUPP;
++ }
++}
++
+ static int rescale_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+ {
+ struct rescale *rescale = iio_priv(indio_dev);
++ int scale, scale2;
++ int schan_off = 0;
+ int ret;
+
+ switch (mask) {
+@@ -78,6 +114,47 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
+ ret = iio_read_channel_scale(rescale->source, val, val2);
+ }
+ return rescale_process_scale(rescale, ret, val, val2);
++ case IIO_CHAN_INFO_OFFSET:
++ /*
++ * Processed channels are scaled 1-to-1 and source offset is
++ * already taken into account.
++ *
++ * In other cases, real world measurement are expressed as:
++ *
++ * schan_scale * (raw + schan_offset)
++ *
++ * Given that the rescaler parameters are applied recursively:
++ *
++ * rescaler_scale * (schan_scale * (raw + schan_offset) +
++ * rescaler_offset)
++ *
++ * Or,
++ *
++ * (rescaler_scale * schan_scale) * (raw +
++ * (schan_offset + rescaler_offset / schan_scale)
++ *
++ * Thus, reusing the original expression the parameters exposed
++ * to userspace are:
++ *
++ * scale = schan_scale * rescaler_scale
++ * offset = schan_offset + rescaler_offset / schan_scale
++ */
++ if (rescale->chan_processed) {
++ *val = rescale->offset;
++ return IIO_VAL_INT;
++ }
++
++ if (iio_channel_has_info(rescale->source->channel,
++ IIO_CHAN_INFO_OFFSET)) {
++ ret = iio_read_channel_offset(rescale->source,
++ &schan_off, NULL);
++ if (ret != IIO_VAL_INT)
++ return ret < 0 ? ret : -EOPNOTSUPP;
++ }
++
++ ret = iio_read_channel_scale(rescale->source, &scale, &scale2);
++ return rescale_process_offset(rescale, ret, scale, scale2,
++ schan_off, val, val2);
+ default:
+ return -EINVAL;
+ }
+@@ -154,6 +231,9 @@ static int rescale_configure_channel(struct device *dev,
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE);
+
++ if (rescale->offset)
++ chan->info_mask_separate |= BIT(IIO_CHAN_INFO_OFFSET);
++
+ /*
+ * Using .read_avail() is fringe to begin with and makes no sense
+ * whatsoever for processed channels, so we make sure that this cannot
+@@ -318,6 +398,7 @@ static int rescale_probe(struct platform_device *pdev)
+ rescale->cfg = of_device_get_match_data(dev);
+ rescale->numerator = 1;
+ rescale->denominator = 1;
++ rescale->offset = 0;
+
+ ret = rescale->cfg->props(dev, rescale);
+ if (ret)
+diff --git a/include/linux/iio/afe/rescale.h b/include/linux/iio/afe/rescale.h
+index 8a2eb34af3271..6eecb435488f1 100644
+--- a/include/linux/iio/afe/rescale.h
++++ b/include/linux/iio/afe/rescale.h
+@@ -25,8 +25,12 @@ struct rescale {
+ bool chan_processed;
+ s32 numerator;
+ s32 denominator;
++ s32 offset;
+ };
+
+ int rescale_process_scale(struct rescale *rescale, int scale_type,
+ int *val, int *val2);
++int rescale_process_offset(struct rescale *rescale, int scale_type,
++ int scale, int scale2, int schan_off,
++ int *val, int *val2);
+ #endif /* __IIO_RESCALE_H__ */
+--
+2.42.0
+
--- /dev/null
+From 49297ba6a1b82ab14c6e0e0df935ab947941e7f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Feb 2022 21:57:30 -0500
+Subject: iio: afe: rescale: expose scale processing function
+
+From: Liam Beguin <liambeguin@gmail.com>
+
+[ Upstream commit bc437f7515f5e14aec9f2801412d9ea48116a97d ]
+
+In preparation for the addition of kunit tests, expose the logic
+responsible for combining channel scales.
+
+Signed-off-by: Liam Beguin <liambeguin@gmail.com>
+Reviewed-by: Peter Rosin <peda@axentia.se>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Link: https://lore.kernel.org/r/20220213025739.2561834-2-liambeguin@gmail.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: bee448390e51 ("iio: afe: rescale: Accept only offset channels")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/afe/iio-rescale.c | 65 ++++++++++++++-------------------
+ include/linux/iio/afe/rescale.h | 32 ++++++++++++++++
+ 2 files changed, 60 insertions(+), 37 deletions(-)
+ create mode 100644 include/linux/iio/afe/rescale.h
+
+diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
+index b0934f85a4a04..6cc453ab9c685 100644
+--- a/drivers/iio/afe/iio-rescale.c
++++ b/drivers/iio/afe/iio-rescale.c
+@@ -15,32 +15,43 @@
+ #include <linux/platform_device.h>
+ #include <linux/property.h>
+
++#include <linux/iio/afe/rescale.h>
+ #include <linux/iio/consumer.h>
+ #include <linux/iio/iio.h>
+
+-struct rescale;
+-
+-struct rescale_cfg {
+- enum iio_chan_type type;
+- int (*props)(struct device *dev, struct rescale *rescale);
+-};
++int rescale_process_scale(struct rescale *rescale, int scale_type,
++ int *val, int *val2)
++{
++ s64 tmp;
+
+-struct rescale {
+- const struct rescale_cfg *cfg;
+- struct iio_channel *source;
+- struct iio_chan_spec chan;
+- struct iio_chan_spec_ext_info *ext_info;
+- bool chan_processed;
+- s32 numerator;
+- s32 denominator;
+-};
++ switch (scale_type) {
++ case IIO_VAL_FRACTIONAL:
++ *val *= rescale->numerator;
++ *val2 *= rescale->denominator;
++ return scale_type;
++ case IIO_VAL_INT:
++ *val *= rescale->numerator;
++ if (rescale->denominator == 1)
++ return scale_type;
++ *val2 = rescale->denominator;
++ return IIO_VAL_FRACTIONAL;
++ case IIO_VAL_FRACTIONAL_LOG2:
++ tmp = (s64)*val * 1000000000LL;
++ tmp = div_s64(tmp, rescale->denominator);
++ tmp *= rescale->numerator;
++ tmp = div_s64(tmp, 1000000000LL);
++ *val = tmp;
++ return scale_type;
++ default:
++ return -EOPNOTSUPP;
++ }
++}
+
+ static int rescale_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+ {
+ struct rescale *rescale = iio_priv(indio_dev);
+- s64 tmp;
+ int ret;
+
+ switch (mask) {
+@@ -66,27 +77,7 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
+ } else {
+ ret = iio_read_channel_scale(rescale->source, val, val2);
+ }
+- switch (ret) {
+- case IIO_VAL_FRACTIONAL:
+- *val *= rescale->numerator;
+- *val2 *= rescale->denominator;
+- return ret;
+- case IIO_VAL_INT:
+- *val *= rescale->numerator;
+- if (rescale->denominator == 1)
+- return ret;
+- *val2 = rescale->denominator;
+- return IIO_VAL_FRACTIONAL;
+- case IIO_VAL_FRACTIONAL_LOG2:
+- tmp = (s64)*val * 1000000000LL;
+- tmp = div_s64(tmp, rescale->denominator);
+- tmp *= rescale->numerator;
+- tmp = div_s64(tmp, 1000000000LL);
+- *val = tmp;
+- return ret;
+- default:
+- return -EOPNOTSUPP;
+- }
++ return rescale_process_scale(rescale, ret, val, val2);
+ default:
+ return -EINVAL;
+ }
+diff --git a/include/linux/iio/afe/rescale.h b/include/linux/iio/afe/rescale.h
+new file mode 100644
+index 0000000000000..8a2eb34af3271
+--- /dev/null
++++ b/include/linux/iio/afe/rescale.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2018 Axentia Technologies AB
++ */
++
++#ifndef __IIO_RESCALE_H__
++#define __IIO_RESCALE_H__
++
++#include <linux/types.h>
++#include <linux/iio/iio.h>
++
++struct device;
++struct rescale;
++
++struct rescale_cfg {
++ enum iio_chan_type type;
++ int (*props)(struct device *dev, struct rescale *rescale);
++};
++
++struct rescale {
++ const struct rescale_cfg *cfg;
++ struct iio_channel *source;
++ struct iio_chan_spec chan;
++ struct iio_chan_spec_ext_info *ext_info;
++ bool chan_processed;
++ s32 numerator;
++ s32 denominator;
++};
++
++int rescale_process_scale(struct rescale *rescale, int scale_type,
++ int *val, int *val2);
++#endif /* __IIO_RESCALE_H__ */
+--
+2.42.0
+
--- /dev/null
+From b297eb959e92d9585ed80f1f866842573a2e5c5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Jan 2022 15:53:08 -0500
+Subject: iio: afe: rescale: reorder includes
+
+From: Liam Beguin <liambeguin@gmail.com>
+
+[ Upstream commit cd717ac6f69db4953ca701c6220c7cb58e17f35a ]
+
+Includes should be ordered alphabetically which is already the case,
+but follow what is done in other drivers by separation IIO specific
+headers with a blank line.
+
+Signed-off-by: Liam Beguin <liambeguin@gmail.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Link: https://lore.kernel.org/r/20220108205319.2046348-6-liambeguin@gmail.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: bee448390e51 ("iio: afe: rescale: Accept only offset channels")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/afe/iio-rescale.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
+index cc28713b0dc8b..b0934f85a4a04 100644
+--- a/drivers/iio/afe/iio-rescale.c
++++ b/drivers/iio/afe/iio-rescale.c
+@@ -9,14 +9,15 @@
+
+ #include <linux/err.h>
+ #include <linux/gcd.h>
+-#include <linux/iio/consumer.h>
+-#include <linux/iio/iio.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+ #include <linux/platform_device.h>
+ #include <linux/property.h>
+
++#include <linux/iio/consumer.h>
++#include <linux/iio/iio.h>
++
+ struct rescale;
+
+ struct rescale_cfg {
+--
+2.42.0
+
perf-core-fix-potential-null-deref.patch
sparc32-fix-a-braino-in-fault-handling-in-csum_and_copy_..._user.patch
clk-sanitize-possible_parent_show-to-handle-return-value-of-of_clk_get_parent_name.patch
+iio-afe-rescale-reorder-includes.patch
+iio-afe-rescale-expose-scale-processing-function.patch
+iio-afe-rescale-add-offset-support.patch
+iio-afe-rescale-accept-only-offset-channels.patch
+acpica-add-support-for-madt-online-enabled-bit.patch
+x86-acpi-don-t-add-cpus-that-are-not-online-capable.patch
+x86-acpi-boot-use-fadt-version-to-check-support-for-.patch
+x86-i8259-skip-probing-when-acpi-madt-advertises-pca.patch
--- /dev/null
+From 34ade583680b1ffe8f88f0edbb890f58e733a0dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Mar 2023 12:45:35 -0500
+Subject: x86/ACPI/boot: Use FADT version to check support for online capable
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit a74fabfbd1b7013045afc8cc541e6cab3360ccb5 ]
+
+ACPI 6.3 introduced the online capable bit, and also introduced MADT
+version 5.
+
+Latter was used to distinguish whether the offset storing online capable
+could be used. However ACPI 6.2b has MADT version "45" which is for
+an errata version of the ACPI 6.2 spec. This means that the Linux code
+for detecting availability of MADT will mistakenly flag ACPI 6.2b as
+supporting online capable which is inaccurate as it's an ACPI 6.3 feature.
+
+Instead use the FADT major and minor revision fields to distinguish this.
+
+ [ bp: Massage. ]
+
+Fixes: aa06e20f1be6 ("x86/ACPI: Don't add CPUs that are not online capable")
+Reported-by: Eric DeVolder <eric.devolder@oracle.com>
+Reported-by: Borislav Petkov <bp@alien8.de>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Cc: <stable@kernel.org>
+Link: https://lore.kernel.org/r/943d2445-84df-d939-f578-5d8240d342cc@unsolicited.net
+Stable-dep-of: 128b0c9781c9 ("x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/acpi/boot.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
+index 0d01e7f5078c2..6d716b9c0ec19 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -139,7 +139,11 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
+
+ pr_debug("Local APIC address 0x%08x\n", madt->address);
+ }
+- if (madt->header.revision >= 5)
++
++ /* ACPI 6.3 and newer support the online capable bit. */
++ if (acpi_gbl_FADT.header.revision > 6 ||
++ (acpi_gbl_FADT.header.revision == 6 &&
++ acpi_gbl_FADT.minor_revision >= 3))
+ acpi_support_online_capable = true;
+
+ default_acpi_madt_oem_check(madt->header.oem_id,
+--
+2.42.0
+
--- /dev/null
+From 93c81745f8a495babd9b08f8be0cd36dab9cdf7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 16:41:46 -0500
+Subject: x86/ACPI: Don't add CPUs that are not online capable
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit aa06e20f1be628186f0c2dcec09ea0009eb69778 ]
+
+A number of systems are showing "hotplug capable" CPUs when they
+are not really hotpluggable. This is because the MADT has extra
+CPU entries to support different CPUs that may be inserted into
+the socket with different numbers of cores.
+
+Starting with ACPI 6.3 the spec has an Online Capable bit in the
+MADT used to determine whether or not a CPU is hotplug capable
+when the enabled bit is not set.
+
+Link: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html?#local-apic-flags
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 128b0c9781c9 ("x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/acpi/boot.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
+index 94ac7402c1ac2..0d01e7f5078c2 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -62,6 +62,7 @@ int acpi_fix_pin2_polarity __initdata;
+
+ #ifdef CONFIG_X86_LOCAL_APIC
+ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
++static bool acpi_support_online_capable;
+ #endif
+
+ #ifdef CONFIG_X86_IO_APIC
+@@ -138,6 +139,8 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
+
+ pr_debug("Local APIC address 0x%08x\n", madt->address);
+ }
++ if (madt->header.revision >= 5)
++ acpi_support_online_capable = true;
+
+ default_acpi_madt_oem_check(madt->header.oem_id,
+ madt->header.oem_table_id);
+@@ -239,6 +242,12 @@ acpi_parse_lapic(union acpi_subtable_headers * header, const unsigned long end)
+ if (processor->id == 0xff)
+ return 0;
+
++ /* don't register processors that can not be onlined */
++ if (acpi_support_online_capable &&
++ !(processor->lapic_flags & ACPI_MADT_ENABLED) &&
++ !(processor->lapic_flags & ACPI_MADT_ONLINE_CAPABLE))
++ return 0;
++
+ /*
+ * We need to register disabled CPU as well to permit
+ * counting disabled CPUs. This allows us to size
+--
+2.42.0
+
--- /dev/null
+From e0fe8d54195b3d88a7c1acbe953035cc56ad4143 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Oct 2023 23:04:15 +0200
+Subject: x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 128b0c9781c9f2651bea163cb85e52a6c7be0f9e ]
+
+David and a few others reported that on certain newer systems some legacy
+interrupts fail to work correctly.
+
+Debugging revealed that the BIOS of these systems leaves the legacy PIC in
+uninitialized state which makes the PIC detection fail and the kernel
+switches to a dummy implementation.
+
+Unfortunately this fallback causes quite some code to fail as it depends on
+checks for the number of legacy PIC interrupts or the availability of the
+real PIC.
+
+In theory there is no reason to use the PIC on any modern system when
+IO/APIC is available, but the dependencies on the related checks cannot be
+resolved trivially and on short notice. This needs lots of analysis and
+rework.
+
+The PIC detection has been added to avoid quirky checks and force selection
+of the dummy implementation all over the place, especially in VM guest
+scenarios. So it's not an option to revert the relevant commit as that
+would break a lot of other scenarios.
+
+One solution would be to try to initialize the PIC on detection fail and
+retry the detection, but that puts the burden on everything which does not
+have a PIC.
+
+Fortunately the ACPI/MADT table header has a flag field, which advertises
+in bit 0 that the system is PCAT compatible, which means it has a legacy
+8259 PIC.
+
+Evaluate that bit and if set avoid the detection routine and keep the real
+PIC installed, which then gets initialized (for nothing) and makes the rest
+of the code with all the dependencies work again.
+
+Fixes: e179f6914152 ("x86, irq, pic: Probe for legacy PIC and set legacy_pic appropriately")
+Reported-by: David Lazar <dlazar@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: David Lazar <dlazar@gmail.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Cc: stable@vger.kernel.org
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218003
+Link: https://lore.kernel.org/r/875y2u5s8g.ffs@tglx
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/i8259.h | 2 ++
+ arch/x86/kernel/acpi/boot.c | 3 +++
+ arch/x86/kernel/i8259.c | 38 ++++++++++++++++++++++++++++--------
+ 3 files changed, 35 insertions(+), 8 deletions(-)
+
+diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
+index 637fa1df35124..c715097e92fd2 100644
+--- a/arch/x86/include/asm/i8259.h
++++ b/arch/x86/include/asm/i8259.h
+@@ -69,6 +69,8 @@ struct legacy_pic {
+ void (*make_irq)(unsigned int irq);
+ };
+
++void legacy_pic_pcat_compat(void);
++
+ extern struct legacy_pic *legacy_pic;
+ extern struct legacy_pic null_legacy_pic;
+
+diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
+index 6d716b9c0ec19..5491987374537 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -140,6 +140,9 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
+ pr_debug("Local APIC address 0x%08x\n", madt->address);
+ }
+
++ if (madt->flags & ACPI_MADT_PCAT_COMPAT)
++ legacy_pic_pcat_compat();
++
+ /* ACPI 6.3 and newer support the online capable bit. */
+ if (acpi_gbl_FADT.header.revision > 6 ||
+ (acpi_gbl_FADT.header.revision == 6 &&
+diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
+index f91e5e31aa4f0..2ac5f488300cf 100644
+--- a/arch/x86/kernel/i8259.c
++++ b/arch/x86/kernel/i8259.c
+@@ -32,6 +32,7 @@
+ */
+ static void init_8259A(int auto_eoi);
+
++static bool pcat_compat __ro_after_init;
+ static int i8259A_auto_eoi;
+ DEFINE_RAW_SPINLOCK(i8259A_lock);
+
+@@ -301,15 +302,32 @@ static void unmask_8259A(void)
+
+ static int probe_8259A(void)
+ {
++ unsigned char new_val, probe_val = ~(1 << PIC_CASCADE_IR);
+ unsigned long flags;
+- unsigned char probe_val = ~(1 << PIC_CASCADE_IR);
+- unsigned char new_val;
++
++ /*
++ * If MADT has the PCAT_COMPAT flag set, then do not bother probing
++ * for the PIC. Some BIOSes leave the PIC uninitialized and probing
++ * fails.
++ *
++ * Right now this causes problems as quite some code depends on
++ * nr_legacy_irqs() > 0 or has_legacy_pic() == true. This is silly
++ * when the system has an IO/APIC because then PIC is not required
++ * at all, except for really old machines where the timer interrupt
++ * must be routed through the PIC. So just pretend that the PIC is
++ * there and let legacy_pic->init() initialize it for nothing.
++ *
++ * Alternatively this could just try to initialize the PIC and
++ * repeat the probe, but for cases where there is no PIC that's
++ * just pointless.
++ */
++ if (pcat_compat)
++ return nr_legacy_irqs();
++
+ /*
+- * Check to see if we have a PIC.
+- * Mask all except the cascade and read
+- * back the value we just wrote. If we don't
+- * have a PIC, we will read 0xff as opposed to the
+- * value we wrote.
++ * Check to see if we have a PIC. Mask all except the cascade and
++ * read back the value we just wrote. If we don't have a PIC, we
++ * will read 0xff as opposed to the value we wrote.
+ */
+ raw_spin_lock_irqsave(&i8259A_lock, flags);
+
+@@ -431,5 +449,9 @@ static int __init i8259A_init_ops(void)
+
+ return 0;
+ }
+-
+ device_initcall(i8259A_init_ops);
++
++void __init legacy_pic_pcat_compat(void)
++{
++ pcat_compat = true;
++}
+--
+2.42.0
+