--- /dev/null
+From 1cf7e5d39939757c72a8f77b09273310433c300b 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 ec66779cb1934..71f4ce6e78aae 100644
+--- a/include/acpi/actbl2.h
++++ b/include/acpi/actbl2.h
+@@ -731,6 +731,7 @@ struct acpi_madt_generic_translator {
+ /* 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 49dbe0191303691b44cd796ff0855a4833f6c79d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Nov 2020 15:27:58 +0100
+Subject: iio: adc: xilinx: use devm_krealloc() instead of kfree() + kcalloc()
+
+From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+
+[ Upstream commit eab64715709ed440d54cac42f239e2d49df26c1f ]
+
+We now have devm_krealloc() in the kernel Use it indstead of calling
+kfree() and kcalloc() separately.
+
+Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+Tested-by: Anand Ashok Dumbre <anandash@xilinx.com>
+Reviewed-by: Anand Ashok Dumbre <anandash@xilinx.com>
+Link: https://lore.kernel.org/r/20201130142759.28216-3-brgl@bgdev.pl
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 8d6b3ea4d9ea ("iio: adc: xilinx-xadc: Don't clobber preset voltage/temperature thresholds")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/xilinx-xadc-core.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
+index 8494eb424b331..6f89a97bb127b 100644
+--- a/drivers/iio/adc/xilinx-xadc-core.c
++++ b/drivers/iio/adc/xilinx-xadc-core.c
+@@ -19,6 +19,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
++#include <linux/overflow.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <linux/sysfs.h>
+@@ -585,15 +586,22 @@ static int xadc_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *mask)
+ {
+ struct xadc *xadc = iio_priv(indio_dev);
+- unsigned int n;
++ size_t new_size, n;
++ void *data;
+
+ n = bitmap_weight(mask, indio_dev->masklength);
+
+- kfree(xadc->data);
+- xadc->data = kcalloc(n, sizeof(*xadc->data), GFP_KERNEL);
+- if (!xadc->data)
++ if (check_mul_overflow(n, sizeof(*xadc->data), &new_size))
++ return -ENOMEM;
++
++ data = devm_krealloc(indio_dev->dev.parent, xadc->data,
++ new_size, GFP_KERNEL);
++ if (!data)
+ return -ENOMEM;
+
++ memset(data, 0, new_size);
++ xadc->data = data;
++
+ return 0;
+ }
+
+@@ -1372,7 +1380,6 @@ static int xadc_remove(struct platform_device *pdev)
+ free_irq(xadc->irq, indio_dev);
+ cancel_delayed_work_sync(&xadc->zynq_unmask_work);
+ clk_disable_unprepare(xadc->clk);
+- kfree(xadc->data);
+
+ return 0;
+ }
+--
+2.42.0
+
--- /dev/null
+From 70551fc85e35be9a3aeb59ff9044f78adbf70ad9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Nov 2020 15:27:57 +0100
+Subject: iio: adc: xilinx: use helper variable for &pdev->dev
+
+From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+
+[ Upstream commit 9d8fd2a06a2bcce8eada1bad26cbe0fbfc27cdf4 ]
+
+It's more elegant to use a helper local variable to store the address
+of the underlying struct device than to dereference pdev everywhere.
+
+Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+Tested-by: Anand Ashok Dumbre <anandash@xilinx.com>
+Reviewed-by: Anand Ashok Dumbre <anandash@xilinx.com>
+Link: https://lore.kernel.org/r/20201130142759.28216-2-brgl@bgdev.pl
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 8d6b3ea4d9ea ("iio: adc: xilinx-xadc: Don't clobber preset voltage/temperature thresholds")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/xilinx-xadc-core.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
+index f93c34fe58731..8494eb424b331 100644
+--- a/drivers/iio/adc/xilinx-xadc-core.c
++++ b/drivers/iio/adc/xilinx-xadc-core.c
+@@ -1186,6 +1186,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
+
+ static int xadc_probe(struct platform_device *pdev)
+ {
++ struct device *dev = &pdev->dev;
+ const struct of_device_id *id;
+ struct iio_dev *indio_dev;
+ unsigned int bipolar_mask;
+@@ -1195,10 +1196,10 @@ static int xadc_probe(struct platform_device *pdev)
+ int irq;
+ int i;
+
+- if (!pdev->dev.of_node)
++ if (!dev->of_node)
+ return -ENODEV;
+
+- id = of_match_node(xadc_of_match_table, pdev->dev.of_node);
++ id = of_match_node(xadc_of_match_table, dev->of_node);
+ if (!id)
+ return -EINVAL;
+
+@@ -1206,7 +1207,7 @@ static int xadc_probe(struct platform_device *pdev)
+ if (irq <= 0)
+ return -ENXIO;
+
+- indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*xadc));
++ indio_dev = devm_iio_device_alloc(dev, sizeof(*xadc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+@@ -1226,7 +1227,7 @@ static int xadc_probe(struct platform_device *pdev)
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &xadc_info;
+
+- ret = xadc_parse_dt(indio_dev, pdev->dev.of_node, &conf0);
++ ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0);
+ if (ret)
+ return ret;
+
+@@ -1250,7 +1251,7 @@ static int xadc_probe(struct platform_device *pdev)
+ }
+ }
+
+- xadc->clk = devm_clk_get(&pdev->dev, NULL);
++ xadc->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(xadc->clk)) {
+ ret = PTR_ERR(xadc->clk);
+ goto err_free_samplerate_trigger;
+@@ -1276,7 +1277,7 @@ static int xadc_probe(struct platform_device *pdev)
+ }
+
+ ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
+- dev_name(&pdev->dev), indio_dev);
++ dev_name(dev), indio_dev);
+ if (ret)
+ goto err_clk_disable_unprepare;
+
+--
+2.42.0
+
--- /dev/null
+From 24785958e5d2c40b503b17a6e79305584ce75677 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Nov 2020 15:27:59 +0100
+Subject: iio: adc: xilinx: use more devres helpers and remove remove()
+
+From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+
+[ Upstream commit 2a9685d1a3b7644ca08d8355fc238b43faef7c3e ]
+
+In order to simplify resource management and error paths in probe() and
+entirely drop the remove() callback - use devres helpers wherever
+possible. Define devm actions for cancelling the delayed work and
+disabling the clock.
+
+Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+Tested-by: Anand Ashok Dumbre <anandash@xilinx.com>
+Reviewed-by: Anand Ashok Dumbre <anandash@xilinx.com>
+Link: https://lore.kernel.org/r/20201130142759.28216-4-brgl@bgdev.pl
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 8d6b3ea4d9ea ("iio: adc: xilinx-xadc: Don't clobber preset voltage/temperature thresholds")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/xilinx-xadc-core.c | 133 ++++++++++++-----------------
+ 1 file changed, 55 insertions(+), 78 deletions(-)
+
+diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
+index 6f89a97bb127b..fec266682e91d 100644
+--- a/drivers/iio/adc/xilinx-xadc-core.c
++++ b/drivers/iio/adc/xilinx-xadc-core.c
+@@ -713,11 +713,12 @@ static const struct iio_trigger_ops xadc_trigger_ops = {
+ static struct iio_trigger *xadc_alloc_trigger(struct iio_dev *indio_dev,
+ const char *name)
+ {
++ struct device *dev = indio_dev->dev.parent;
+ struct iio_trigger *trig;
+ int ret;
+
+- trig = iio_trigger_alloc("%s%d-%s", indio_dev->name,
+- indio_dev->id, name);
++ trig = devm_iio_trigger_alloc(dev, "%s%d-%s", indio_dev->name,
++ indio_dev->id, name);
+ if (trig == NULL)
+ return ERR_PTR(-ENOMEM);
+
+@@ -725,15 +726,11 @@ static struct iio_trigger *xadc_alloc_trigger(struct iio_dev *indio_dev,
+ trig->ops = &xadc_trigger_ops;
+ iio_trigger_set_drvdata(trig, iio_priv(indio_dev));
+
+- ret = iio_trigger_register(trig);
++ ret = devm_iio_trigger_register(dev, trig);
+ if (ret)
+- goto error_free_trig;
++ return ERR_PTR(ret);
+
+ return trig;
+-
+-error_free_trig:
+- iio_trigger_free(trig);
+- return ERR_PTR(ret);
+ }
+
+ static int xadc_power_adc_b(struct xadc *xadc, unsigned int seq_mode)
+@@ -1192,6 +1189,20 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
+ return 0;
+ }
+
++static void xadc_clk_disable_unprepare(void *data)
++{
++ struct clk *clk = data;
++
++ clk_disable_unprepare(clk);
++}
++
++static void xadc_cancel_delayed_work(void *data)
++{
++ struct delayed_work *work = data;
++
++ cancel_delayed_work_sync(work);
++}
++
+ static int xadc_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -1240,34 +1251,35 @@ static int xadc_probe(struct platform_device *pdev)
+ return ret;
+
+ if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
+- ret = iio_triggered_buffer_setup(indio_dev,
+- &iio_pollfunc_store_time, &xadc_trigger_handler,
+- &xadc_buffer_ops);
++ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
++ &iio_pollfunc_store_time,
++ &xadc_trigger_handler,
++ &xadc_buffer_ops);
+ if (ret)
+ return ret;
+
+ xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
+- if (IS_ERR(xadc->convst_trigger)) {
+- ret = PTR_ERR(xadc->convst_trigger);
+- goto err_triggered_buffer_cleanup;
+- }
++ if (IS_ERR(xadc->convst_trigger))
++ return PTR_ERR(xadc->convst_trigger);
++
+ xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
+ "samplerate");
+- if (IS_ERR(xadc->samplerate_trigger)) {
+- ret = PTR_ERR(xadc->samplerate_trigger);
+- goto err_free_convst_trigger;
+- }
++ if (IS_ERR(xadc->samplerate_trigger))
++ return PTR_ERR(xadc->samplerate_trigger);
+ }
+
+ xadc->clk = devm_clk_get(dev, NULL);
+- if (IS_ERR(xadc->clk)) {
+- ret = PTR_ERR(xadc->clk);
+- goto err_free_samplerate_trigger;
+- }
++ if (IS_ERR(xadc->clk))
++ return PTR_ERR(xadc->clk);
+
+ ret = clk_prepare_enable(xadc->clk);
+ if (ret)
+- goto err_free_samplerate_trigger;
++ return ret;
++
++ ret = devm_add_action_or_reset(dev,
++ xadc_clk_disable_unprepare, xadc->clk);
++ if (ret)
++ return ret;
+
+ /*
+ * Make sure not to exceed the maximum samplerate since otherwise the
+@@ -1276,22 +1288,28 @@ static int xadc_probe(struct platform_device *pdev)
+ if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
+ ret = xadc_read_samplerate(xadc);
+ if (ret < 0)
+- goto err_free_samplerate_trigger;
++ return ret;
++
+ if (ret > XADC_MAX_SAMPLERATE) {
+ ret = xadc_write_samplerate(xadc, XADC_MAX_SAMPLERATE);
+ if (ret < 0)
+- goto err_free_samplerate_trigger;
++ return ret;
+ }
+ }
+
+- ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
+- dev_name(dev), indio_dev);
++ ret = devm_request_irq(dev, xadc->irq, xadc->ops->interrupt_handler, 0,
++ dev_name(dev), indio_dev);
++ if (ret)
++ return ret;
++
++ ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work,
++ &xadc->zynq_unmask_work);
+ if (ret)
+- goto err_clk_disable_unprepare;
++ return ret;
+
+ ret = xadc->ops->setup(pdev, indio_dev, xadc->irq);
+ if (ret)
+- goto err_free_irq;
++ return ret;
+
+ for (i = 0; i < 16; i++)
+ xadc_read_adc_reg(xadc, XADC_REG_THRESHOLD(i),
+@@ -1299,7 +1317,7 @@ static int xadc_probe(struct platform_device *pdev)
+
+ ret = xadc_write_adc_reg(xadc, XADC_REG_CONF0, conf0);
+ if (ret)
+- goto err_free_irq;
++ return ret;
+
+ bipolar_mask = 0;
+ for (i = 0; i < indio_dev->num_channels; i++) {
+@@ -1309,17 +1327,18 @@ static int xadc_probe(struct platform_device *pdev)
+
+ ret = xadc_write_adc_reg(xadc, XADC_REG_INPUT_MODE(0), bipolar_mask);
+ if (ret)
+- goto err_free_irq;
++ return ret;
++
+ ret = xadc_write_adc_reg(xadc, XADC_REG_INPUT_MODE(1),
+ bipolar_mask >> 16);
+ if (ret)
+- goto err_free_irq;
++ return ret;
+
+ /* Disable all alarms */
+ ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK,
+ XADC_CONF1_ALARM_MASK);
+ if (ret)
+- goto err_free_irq;
++ return ret;
+
+ /* Set thresholds to min/max */
+ for (i = 0; i < 16; i++) {
+@@ -1334,59 +1353,17 @@ static int xadc_probe(struct platform_device *pdev)
+ ret = xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i),
+ xadc->threshold[i]);
+ if (ret)
+- goto err_free_irq;
++ return ret;
+ }
+
+ /* Go to non-buffered mode */
+ xadc_postdisable(indio_dev);
+
+- ret = iio_device_register(indio_dev);
+- if (ret)
+- goto err_free_irq;
+-
+- platform_set_drvdata(pdev, indio_dev);
+-
+- return 0;
+-
+-err_free_irq:
+- free_irq(xadc->irq, indio_dev);
+- cancel_delayed_work_sync(&xadc->zynq_unmask_work);
+-err_clk_disable_unprepare:
+- clk_disable_unprepare(xadc->clk);
+-err_free_samplerate_trigger:
+- if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
+- iio_trigger_free(xadc->samplerate_trigger);
+-err_free_convst_trigger:
+- if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
+- iio_trigger_free(xadc->convst_trigger);
+-err_triggered_buffer_cleanup:
+- if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
+- iio_triggered_buffer_cleanup(indio_dev);
+-
+- return ret;
+-}
+-
+-static int xadc_remove(struct platform_device *pdev)
+-{
+- struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+- struct xadc *xadc = iio_priv(indio_dev);
+-
+- iio_device_unregister(indio_dev);
+- if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
+- iio_trigger_free(xadc->samplerate_trigger);
+- iio_trigger_free(xadc->convst_trigger);
+- iio_triggered_buffer_cleanup(indio_dev);
+- }
+- free_irq(xadc->irq, indio_dev);
+- cancel_delayed_work_sync(&xadc->zynq_unmask_work);
+- clk_disable_unprepare(xadc->clk);
+-
+- return 0;
++ return devm_iio_device_register(dev, indio_dev);
+ }
+
+ static struct platform_driver xadc_driver = {
+ .probe = xadc_probe,
+- .remove = xadc_remove,
+ .driver = {
+ .name = "xadc",
+ .of_match_table = xadc_of_match_table,
+--
+2.42.0
+
--- /dev/null
+From 9c2528f8b330dda82ad8f1d021edc591e6fa95c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 18:10:18 -0600
+Subject: iio: adc: xilinx-xadc: Don't clobber preset voltage/temperature
+ thresholds
+
+From: Robert Hancock <robert.hancock@calian.com>
+
+[ Upstream commit 8d6b3ea4d9eaca80982442b68a292ce50ce0a135 ]
+
+In the probe function, the driver was reading out the thresholds already
+set in the core, which can be configured by the user in the Vivado tools
+when the FPGA image is built. However, it later clobbered those values
+with zero or maximum values. In particular, the overtemperature shutdown
+threshold register was overwritten with the max value, which effectively
+prevents the FPGA from shutting down when the desired threshold was
+eached, potentially risking hardware damage in that case.
+
+Remove this code to leave the preconfigured default threshold values
+intact.
+
+The code was also disabling all alarms regardless of what enable state
+they were left in by the FPGA image, including the overtemperature
+shutdown feature. Leave these bits in their original state so they are
+not unconditionally disabled.
+
+Fixes: bdc8cda1d010 ("iio:adc: Add Xilinx XADC driver")
+Signed-off-by: Robert Hancock <robert.hancock@calian.com>
+Acked-by: O'Griofa, Conall <conall.ogriofa@amd.com>
+Tested-by: O'Griofa, Conall <conall.ogriofa@amd.com>
+Link: https://lore.kernel.org/r/20230915001019.2862964-2-robert.hancock@calian.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/xilinx-xadc-core.c | 22 ----------------------
+ 1 file changed, 22 deletions(-)
+
+diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
+index fec266682e91d..30b5a17ce41a7 100644
+--- a/drivers/iio/adc/xilinx-xadc-core.c
++++ b/drivers/iio/adc/xilinx-xadc-core.c
+@@ -1334,28 +1334,6 @@ static int xadc_probe(struct platform_device *pdev)
+ if (ret)
+ return ret;
+
+- /* Disable all alarms */
+- ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK,
+- XADC_CONF1_ALARM_MASK);
+- if (ret)
+- return ret;
+-
+- /* Set thresholds to min/max */
+- for (i = 0; i < 16; i++) {
+- /*
+- * Set max voltage threshold and both temperature thresholds to
+- * 0xffff, min voltage threshold to 0.
+- */
+- if (i % 8 < 4 || i == 7)
+- xadc->threshold[i] = 0xffff;
+- else
+- xadc->threshold[i] = 0;
+- ret = xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i),
+- xadc->threshold[i]);
+- if (ret)
+- return ret;
+- }
+-
+ /* Go to non-buffered mode */
+ xadc_postdisable(indio_dev);
+
+--
+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-adc-xilinx-use-helper-variable-for-pdev-dev.patch
+iio-adc-xilinx-use-devm_krealloc-instead-of-kfree-kc.patch
+iio-adc-xilinx-use-more-devres-helpers-and-remove-re.patch
+iio-adc-xilinx-xadc-don-t-clobber-preset-voltage-tem.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 cf8da7f357c25cfa1fb0b78c3ad744e071e8d798 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 7840e650f452a..2f7f72b6f1235 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -141,7 +141,11 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
+ printk(KERN_DEBUG PREFIX "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 a7d395fab9e1231f558746ce56d13f4406fa7fa9 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 55562a9b7f92e..7840e650f452a 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -63,6 +63,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
+@@ -140,6 +141,8 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
+ printk(KERN_DEBUG PREFIX "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);
+@@ -241,6 +244,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 8a6394357ea2e57d2f829b13d2c4abf3dccd5cfa 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 89789e8c80f66..e16574c16e933 100644
+--- a/arch/x86/include/asm/i8259.h
++++ b/arch/x86/include/asm/i8259.h
+@@ -67,6 +67,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 2f7f72b6f1235..5f325d9204455 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -142,6 +142,9 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
+ 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 f325389d03516..4c9f559e1388b 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
+