From: Sasha Levin Date: Mon, 11 Dec 2023 04:13:39 +0000 (-0500) Subject: Fixes for 5.4 X-Git-Tag: v6.6.6~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c05625a9c4c9cd71b98c4be018f1edb191526f30;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/gpiolib-sysfs-fix-error-handling-on-failed-export.patch b/queue-5.4/gpiolib-sysfs-fix-error-handling-on-failed-export.patch new file mode 100644 index 00000000000..839a334c8bc --- /dev/null +++ b/queue-5.4/gpiolib-sysfs-fix-error-handling-on-failed-export.patch @@ -0,0 +1,61 @@ +From b5cc5c1c1edd62142a46ecdd2a108e2709573571 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 16:23:07 +0100 +Subject: gpiolib: sysfs: Fix error handling on failed export + +From: Boerge Struempfel + +[ Upstream commit 95dd1e34ff5bbee93a28ff3947eceaf6de811b1a ] + +If gpio_set_transitory() fails, we should free the GPIO again. Most +notably, the flag FLAG_REQUESTED has previously been set in +gpiod_request_commit(), and should be reset on failure. + +To my knowledge, this does not affect any current users, since the +gpio_set_transitory() mainly returns 0 and -ENOTSUPP, which is converted +to 0. However the gpio_set_transitory() function calles the .set_config() +function of the corresponding GPIO chip and there are some GPIO drivers in +which some (unlikely) branches return other values like -EPROBE_DEFER, +and -EINVAL. In these cases, the above mentioned FLAG_REQUESTED would not +be reset, which results in the pin being blocked until the next reboot. + +Fixes: e10f72bf4b3e ("gpio: gpiolib: Generalise state persistence beyond sleep") +Signed-off-by: Boerge Struempfel +Reviewed-by: Andy Shevchenko +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpiolib-sysfs.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c +index 558cd900d3996..b993416961a75 100644 +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -490,14 +490,17 @@ static ssize_t export_store(struct class *class, + } + + status = gpiod_set_transitory(desc, false); +- if (!status) { +- status = gpiod_export(desc, true); +- if (status < 0) +- gpiod_free(desc); +- else +- set_bit(FLAG_SYSFS, &desc->flags); ++ if (status) { ++ gpiod_free(desc); ++ goto done; + } + ++ status = gpiod_export(desc, true); ++ if (status < 0) ++ gpiod_free(desc); ++ else ++ set_bit(FLAG_SYSFS, &desc->flags); ++ + done: + if (status) + pr_debug("%s: status %d\n", __func__, status); +-- +2.42.0 + diff --git a/queue-5.4/mmc-core-add-helpers-mmc_regulator_enable-disable_vq.patch b/queue-5.4/mmc-core-add-helpers-mmc_regulator_enable-disable_vq.patch new file mode 100644 index 00000000000..535cadd0922 --- /dev/null +++ b/queue-5.4/mmc-core-add-helpers-mmc_regulator_enable-disable_vq.patch @@ -0,0 +1,100 @@ +From 502f10af856972dd72bdc984535d0dc101a147db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Mar 2023 23:39:55 +0100 +Subject: mmc: core: add helpers mmc_regulator_enable/disable_vqmmc + +From: Heiner Kallweit + +[ Upstream commit 8d91f3f8ae57e6292142ca89f322e90fa0d6ac02 ] + +There's a number of drivers (e.g. dw_mmc, meson-gx, mmci, sunxi) using +the same mechanism and a private flag vqmmc_enabled to deal with +enabling/disabling the vqmmc regulator. + +Move this to the core and create new helpers mmc_regulator_enable_vqmmc +and mmc_regulator_disable_vqmmc. + +Signed-off-by: Heiner Kallweit +Acked-by: Martin Blumenstingl +Link: https://lore.kernel.org/r/71586432-360f-9b92-17f6-b05a8a971bc2@gmail.com +Signed-off-by: Ulf Hansson +Stable-dep-of: 477865af60b2 ("mmc: sdhci-sprd: Fix vqmmc not shutting down after the card was pulled") +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/regulator.c | 41 ++++++++++++++++++++++++++++++++++++ + include/linux/mmc/host.h | 3 +++ + 2 files changed, 44 insertions(+) + +diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c +index b6febbcf8978d..327032cbbb1f8 100644 +--- a/drivers/mmc/core/regulator.c ++++ b/drivers/mmc/core/regulator.c +@@ -258,3 +258,44 @@ int mmc_regulator_get_supply(struct mmc_host *mmc) + return 0; + } + EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); ++ ++/** ++ * mmc_regulator_enable_vqmmc - enable VQMMC regulator for a host ++ * @mmc: the host to regulate ++ * ++ * Returns 0 or errno. Enables the regulator for vqmmc. ++ * Keeps track of the enable status for ensuring that calls to ++ * regulator_enable/disable are balanced. ++ */ ++int mmc_regulator_enable_vqmmc(struct mmc_host *mmc) ++{ ++ int ret = 0; ++ ++ if (!IS_ERR(mmc->supply.vqmmc) && !mmc->vqmmc_enabled) { ++ ret = regulator_enable(mmc->supply.vqmmc); ++ if (ret < 0) ++ dev_err(mmc_dev(mmc), "enabling vqmmc regulator failed\n"); ++ else ++ mmc->vqmmc_enabled = true; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(mmc_regulator_enable_vqmmc); ++ ++/** ++ * mmc_regulator_disable_vqmmc - disable VQMMC regulator for a host ++ * @mmc: the host to regulate ++ * ++ * Returns 0 or errno. Disables the regulator for vqmmc. ++ * Keeps track of the enable status for ensuring that calls to ++ * regulator_enable/disable are balanced. ++ */ ++void mmc_regulator_disable_vqmmc(struct mmc_host *mmc) ++{ ++ if (!IS_ERR(mmc->supply.vqmmc) && mmc->vqmmc_enabled) { ++ regulator_disable(mmc->supply.vqmmc); ++ mmc->vqmmc_enabled = false; ++ } ++} ++EXPORT_SYMBOL_GPL(mmc_regulator_disable_vqmmc); +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index a0e1cf1bef4e5..68880c2b4fe07 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -397,6 +397,7 @@ struct mmc_host { + unsigned int use_blk_mq:1; /* use blk-mq */ + unsigned int retune_crc_disable:1; /* don't trigger retune upon crc */ + unsigned int can_dma_map_merge:1; /* merging can be used */ ++ unsigned int vqmmc_enabled:1; /* vqmmc regulator is enabled */ + + int rescan_disable; /* disable card detection */ + int rescan_entered; /* used with nonremovable devices */ +@@ -534,6 +535,8 @@ static inline int mmc_regulator_set_vqmmc(struct mmc_host *mmc, + #endif + + int mmc_regulator_get_supply(struct mmc_host *mmc); ++int mmc_regulator_enable_vqmmc(struct mmc_host *mmc); ++void mmc_regulator_disable_vqmmc(struct mmc_host *mmc); + + static inline int mmc_card_is_removable(struct mmc_host *host) + { +-- +2.42.0 + diff --git a/queue-5.4/mmc-sdhci-sprd-fix-vqmmc-not-shutting-down-after-the.patch b/queue-5.4/mmc-sdhci-sprd-fix-vqmmc-not-shutting-down-after-the.patch new file mode 100644 index 00000000000..1c9b5025ce7 --- /dev/null +++ b/queue-5.4/mmc-sdhci-sprd-fix-vqmmc-not-shutting-down-after-the.patch @@ -0,0 +1,94 @@ +From dff1e89408ce049365c9bd51263607a9f9e0d374 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Nov 2023 16:34:06 +0800 +Subject: mmc: sdhci-sprd: Fix vqmmc not shutting down after the card was + pulled + +From: Wenchao Chen + +[ Upstream commit 477865af60b2117ceaa1d558e03559108c15c78c ] + +With cat regulator_summary, we found that vqmmc was not shutting +down after the card was pulled. + +cat /sys/kernel/debug/regulator/regulator_summary +1.before fix +1)Insert SD card + vddsdio 1 1 0 unknown 3500mV 0mA 1200mV 3750mV + 71100000.mmc-vqmmc 1 0mA 3500mV 3600mV + +2)Pull out the SD card + vddsdio 1 1 0 unknown 3500mV 0mA 1200mV 3750mV + 71100000.mmc-vqmmc 1 0mA 3500mV 3600mV + +2.after fix +1)Insert SD cardt + vddsdio 1 1 0 unknown 3500mV 0mA 1200mV 3750mV + 71100000.mmc-vqmmc 1 0mA 3500mV 3600mV + +2)Pull out the SD card + vddsdio 0 1 0 unknown 3500mV 0mA 1200mV 3750mV + 71100000.mmc-vqmmc 0 0mA 3500mV 3600mV + +Fixes: fb8bd90f83c4 ("mmc: sdhci-sprd: Add Spreadtrum's initial host controller") +Signed-off-by: Wenchao Chen +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20231115083406.7368-1-wenchao.chen@unisoc.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci-sprd.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c +index 1b1dad9d9a604..b624589e62a0e 100644 +--- a/drivers/mmc/host/sdhci-sprd.c ++++ b/drivers/mmc/host/sdhci-sprd.c +@@ -381,12 +381,33 @@ static unsigned int sdhci_sprd_get_ro(struct sdhci_host *host) + return 0; + } + ++static void sdhci_sprd_set_power(struct sdhci_host *host, unsigned char mode, ++ unsigned short vdd) ++{ ++ struct mmc_host *mmc = host->mmc; ++ ++ switch (mode) { ++ case MMC_POWER_OFF: ++ mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, 0); ++ ++ mmc_regulator_disable_vqmmc(mmc); ++ break; ++ case MMC_POWER_ON: ++ mmc_regulator_enable_vqmmc(mmc); ++ break; ++ case MMC_POWER_UP: ++ mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, vdd); ++ break; ++ } ++} ++ + static struct sdhci_ops sdhci_sprd_ops = { + .read_l = sdhci_sprd_readl, + .write_l = sdhci_sprd_writel, + .write_w = sdhci_sprd_writew, + .write_b = sdhci_sprd_writeb, + .set_clock = sdhci_sprd_set_clock, ++ .set_power = sdhci_sprd_set_power, + .get_max_clock = sdhci_sprd_get_max_clock, + .get_min_clock = sdhci_sprd_get_min_clock, + .set_bus_width = sdhci_set_bus_width, +@@ -630,6 +651,10 @@ static int sdhci_sprd_probe(struct platform_device *pdev) + host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | + SDHCI_SUPPORT_DDR50); + ++ ret = mmc_regulator_get_supply(host->mmc); ++ if (ret) ++ goto pm_runtime_disable; ++ + ret = sdhci_setup_host(host); + if (ret) + goto pm_runtime_disable; +-- +2.42.0 + diff --git a/queue-5.4/perf-core-add-a-new-read-format-to-get-a-number-of-l.patch b/queue-5.4/perf-core-add-a-new-read-format-to-get-a-number-of-l.patch new file mode 100644 index 00000000000..04db3c9ac09 --- /dev/null +++ b/queue-5.4/perf-core-add-a-new-read-format-to-get-a-number-of-l.patch @@ -0,0 +1,194 @@ +From 38a1b0b4f9d800018b1896b4e55351fb5eefedd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 11:06:23 -0700 +Subject: perf/core: Add a new read format to get a number of lost samples + +From: Namhyung Kim + +[ Upstream commit 119a784c81270eb88e573174ed2209225d646656 ] + +Sometimes we want to know an accurate number of samples even if it's +lost. Currenlty PERF_RECORD_LOST is generated for a ring-buffer which +might be shared with other events. So it's hard to know per-event +lost count. + +Add event->lost_samples field and PERF_FORMAT_LOST to retrieve it from +userspace. + +Original-patch-by: Jiri Olsa +Signed-off-by: Namhyung Kim +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20220616180623.1358843-1-namhyung@kernel.org +Stable-dep-of: 382c27f4ed28 ("perf: Fix perf_event_validate_size()") +Signed-off-by: Sasha Levin +--- + include/linux/perf_event.h | 2 ++ + include/uapi/linux/perf_event.h | 5 ++++- + kernel/events/core.c | 21 ++++++++++++++++++--- + kernel/events/ring_buffer.c | 5 ++++- + 4 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 4c7409e23318b..9e0e20c11aa34 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -702,6 +702,8 @@ struct perf_event { + struct pid_namespace *ns; + u64 id; + ++ atomic64_t lost_samples; ++ + u64 (*clock)(void); + perf_overflow_handler_t overflow_handler; + void *overflow_handler_context; +diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h +index ceccd980ffcfe..19c143a293bea 100644 +--- a/include/uapi/linux/perf_event.h ++++ b/include/uapi/linux/perf_event.h +@@ -273,6 +273,7 @@ enum { + * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED + * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING + * { u64 id; } && PERF_FORMAT_ID ++ * { u64 lost; } && PERF_FORMAT_LOST + * } && !PERF_FORMAT_GROUP + * + * { u64 nr; +@@ -280,6 +281,7 @@ enum { + * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING + * { u64 value; + * { u64 id; } && PERF_FORMAT_ID ++ * { u64 lost; } && PERF_FORMAT_LOST + * } cntr[nr]; + * } && PERF_FORMAT_GROUP + * }; +@@ -289,8 +291,9 @@ enum perf_event_read_format { + PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1, + PERF_FORMAT_ID = 1U << 2, + PERF_FORMAT_GROUP = 1U << 3, ++ PERF_FORMAT_LOST = 1U << 4, + +- PERF_FORMAT_MAX = 1U << 4, /* non-ABI */ ++ PERF_FORMAT_MAX = 1U << 5, /* non-ABI */ + }; + + #define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ +diff --git a/kernel/events/core.c b/kernel/events/core.c +index cd32c7e55568a..f5d5e0cdb223b 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -1726,6 +1726,9 @@ static void __perf_event_read_size(struct perf_event *event, int nr_siblings) + if (event->attr.read_format & PERF_FORMAT_ID) + entry += sizeof(u64); + ++ if (event->attr.read_format & PERF_FORMAT_LOST) ++ entry += sizeof(u64); ++ + if (event->attr.read_format & PERF_FORMAT_GROUP) { + nr += nr_siblings; + size += sizeof(u64); +@@ -4915,11 +4918,15 @@ static int __perf_read_group_add(struct perf_event *leader, + values[n++] += perf_event_count(leader); + if (read_format & PERF_FORMAT_ID) + values[n++] = primary_event_id(leader); ++ if (read_format & PERF_FORMAT_LOST) ++ values[n++] = atomic64_read(&leader->lost_samples); + + for_each_sibling_event(sub, leader) { + values[n++] += perf_event_count(sub); + if (read_format & PERF_FORMAT_ID) + values[n++] = primary_event_id(sub); ++ if (read_format & PERF_FORMAT_LOST) ++ values[n++] = atomic64_read(&sub->lost_samples); + } + + unlock: +@@ -4973,7 +4980,7 @@ static int perf_read_one(struct perf_event *event, + u64 read_format, char __user *buf) + { + u64 enabled, running; +- u64 values[4]; ++ u64 values[5]; + int n = 0; + + values[n++] = __perf_event_read_value(event, &enabled, &running); +@@ -4983,6 +4990,8 @@ static int perf_read_one(struct perf_event *event, + values[n++] = running; + if (read_format & PERF_FORMAT_ID) + values[n++] = primary_event_id(event); ++ if (read_format & PERF_FORMAT_LOST) ++ values[n++] = atomic64_read(&event->lost_samples); + + if (copy_to_user(buf, values, n * sizeof(u64))) + return -EFAULT; +@@ -6312,7 +6321,7 @@ static void perf_output_read_one(struct perf_output_handle *handle, + u64 enabled, u64 running) + { + u64 read_format = event->attr.read_format; +- u64 values[4]; ++ u64 values[5]; + int n = 0; + + values[n++] = perf_event_count(event); +@@ -6326,6 +6335,8 @@ static void perf_output_read_one(struct perf_output_handle *handle, + } + if (read_format & PERF_FORMAT_ID) + values[n++] = primary_event_id(event); ++ if (read_format & PERF_FORMAT_LOST) ++ values[n++] = atomic64_read(&event->lost_samples); + + __output_copy(handle, values, n * sizeof(u64)); + } +@@ -6336,7 +6347,7 @@ static void perf_output_read_group(struct perf_output_handle *handle, + { + struct perf_event *leader = event->group_leader, *sub; + u64 read_format = event->attr.read_format; +- u64 values[5]; ++ u64 values[6]; + int n = 0; + + values[n++] = 1 + leader->nr_siblings; +@@ -6354,6 +6365,8 @@ static void perf_output_read_group(struct perf_output_handle *handle, + values[n++] = perf_event_count(leader); + if (read_format & PERF_FORMAT_ID) + values[n++] = primary_event_id(leader); ++ if (read_format & PERF_FORMAT_LOST) ++ values[n++] = atomic64_read(&leader->lost_samples); + + __output_copy(handle, values, n * sizeof(u64)); + +@@ -6367,6 +6380,8 @@ static void perf_output_read_group(struct perf_output_handle *handle, + values[n++] = perf_event_count(sub); + if (read_format & PERF_FORMAT_ID) + values[n++] = primary_event_id(sub); ++ if (read_format & PERF_FORMAT_LOST) ++ values[n++] = atomic64_read(&sub->lost_samples); + + __output_copy(handle, values, n * sizeof(u64)); + } +diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c +index fb3edb2f8ac93..679cc87b40f4b 100644 +--- a/kernel/events/ring_buffer.c ++++ b/kernel/events/ring_buffer.c +@@ -171,8 +171,10 @@ __perf_output_begin(struct perf_output_handle *handle, + goto out; + + if (unlikely(rb->paused)) { +- if (rb->nr_pages) ++ if (rb->nr_pages) { + local_inc(&rb->lost); ++ atomic64_inc(&event->lost_samples); ++ } + goto out; + } + +@@ -255,6 +257,7 @@ __perf_output_begin(struct perf_output_handle *handle, + + fail: + local_inc(&rb->lost); ++ atomic64_inc(&event->lost_samples); + perf_output_put_handle(handle); + out: + rcu_read_unlock(); +-- +2.42.0 + diff --git a/queue-5.4/perf-fix-perf_event_validate_size.patch b/queue-5.4/perf-fix-perf_event_validate_size.patch new file mode 100644 index 00000000000..dd44712994f --- /dev/null +++ b/queue-5.4/perf-fix-perf_event_validate_size.patch @@ -0,0 +1,135 @@ +From 707b43abd87582f5f4b508649dfc975f90926211 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 15:24:52 +0100 +Subject: perf: Fix perf_event_validate_size() + +From: Peter Zijlstra + +[ Upstream commit 382c27f4ed28f803b1f1473ac2d8db0afc795a1b ] + +Budimir noted that perf_event_validate_size() only checks the size of +the newly added event, even though the sizes of all existing events +can also change due to not all events having the same read_format. + +When we attach the new event, perf_group_attach(), we do re-compute +the size for all events. + +Fixes: a723968c0ed3 ("perf: Fix u16 overflows") +Reported-by: Budimir Markovic +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Sasha Levin +--- + kernel/events/core.c | 61 +++++++++++++++++++++++++++----------------- + 1 file changed, 38 insertions(+), 23 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index f5d5e0cdb223b..fcc8e3823198f 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -1711,31 +1711,34 @@ static inline void perf_event__state_init(struct perf_event *event) + PERF_EVENT_STATE_INACTIVE; + } + +-static void __perf_event_read_size(struct perf_event *event, int nr_siblings) ++static int __perf_event_read_size(u64 read_format, int nr_siblings) + { + int entry = sizeof(u64); /* value */ + int size = 0; + int nr = 1; + +- if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) ++ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + size += sizeof(u64); + +- if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) ++ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + size += sizeof(u64); + +- if (event->attr.read_format & PERF_FORMAT_ID) ++ if (read_format & PERF_FORMAT_ID) + entry += sizeof(u64); + +- if (event->attr.read_format & PERF_FORMAT_LOST) ++ if (read_format & PERF_FORMAT_LOST) + entry += sizeof(u64); + +- if (event->attr.read_format & PERF_FORMAT_GROUP) { ++ if (read_format & PERF_FORMAT_GROUP) { + nr += nr_siblings; + size += sizeof(u64); + } + +- size += entry * nr; +- event->read_size = size; ++ /* ++ * Since perf_event_validate_size() limits this to 16k and inhibits ++ * adding more siblings, this will never overflow. ++ */ ++ return size + nr * entry; + } + + static void __perf_event_header_size(struct perf_event *event, u64 sample_type) +@@ -1776,8 +1779,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type) + */ + static void perf_event__header_size(struct perf_event *event) + { +- __perf_event_read_size(event, +- event->group_leader->nr_siblings); ++ event->read_size = ++ __perf_event_read_size(event->attr.read_format, ++ event->group_leader->nr_siblings); + __perf_event_header_size(event, event->attr.sample_type); + } + +@@ -1808,24 +1812,35 @@ static void perf_event__id_header_size(struct perf_event *event) + event->id_header_size = size; + } + ++/* ++ * Check that adding an event to the group does not result in anybody ++ * overflowing the 64k event limit imposed by the output buffer. ++ * ++ * Specifically, check that the read_size for the event does not exceed 16k, ++ * read_size being the one term that grows with groups size. Since read_size ++ * depends on per-event read_format, also (re)check the existing events. ++ * ++ * This leaves 48k for the constant size fields and things like callchains, ++ * branch stacks and register sets. ++ */ + static bool perf_event_validate_size(struct perf_event *event) + { +- /* +- * The values computed here will be over-written when we actually +- * attach the event. +- */ +- __perf_event_read_size(event, event->group_leader->nr_siblings + 1); +- __perf_event_header_size(event, event->attr.sample_type & ~PERF_SAMPLE_READ); +- perf_event__id_header_size(event); ++ struct perf_event *sibling, *group_leader = event->group_leader; + +- /* +- * Sum the lot; should not exceed the 64k limit we have on records. +- * Conservative limit to allow for callchains and other variable fields. +- */ +- if (event->read_size + event->header_size + +- event->id_header_size + sizeof(struct perf_event_header) >= 16*1024) ++ if (__perf_event_read_size(event->attr.read_format, ++ group_leader->nr_siblings + 1) > 16*1024) + return false; + ++ if (__perf_event_read_size(group_leader->attr.read_format, ++ group_leader->nr_siblings + 1) > 16*1024) ++ return false; ++ ++ for_each_sibling_event(sibling, group_leader) { ++ if (__perf_event_read_size(sibling->attr.read_format, ++ group_leader->nr_siblings + 1) > 16*1024) ++ return false; ++ } ++ + return true; + } + +-- +2.42.0 + diff --git a/queue-5.4/series b/queue-5.4/series index 4a1408634aa..4d6b95a5b75 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -41,3 +41,8 @@ tracing-fix-a-possible-race-when-disabling-buffered-events.patch packet-move-reference-count-in-packet_sock-to-atomic_long_t.patch arm64-dts-mediatek-mt7622-fix-memory-node-warning-check.patch arm64-dts-mediatek-mt8173-evb-fix-regulator-fixed-node-names.patch +perf-core-add-a-new-read-format-to-get-a-number-of-l.patch +perf-fix-perf_event_validate_size.patch +gpiolib-sysfs-fix-error-handling-on-failed-export.patch +mmc-core-add-helpers-mmc_regulator_enable-disable_vq.patch +mmc-sdhci-sprd-fix-vqmmc-not-shutting-down-after-the.patch