]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Mon, 11 Dec 2023 04:13:39 +0000 (23:13 -0500)
committerSasha Levin <sashal@kernel.org>
Mon, 11 Dec 2023 04:13:39 +0000 (23:13 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.4/gpiolib-sysfs-fix-error-handling-on-failed-export.patch [new file with mode: 0644]
queue-5.4/mmc-core-add-helpers-mmc_regulator_enable-disable_vq.patch [new file with mode: 0644]
queue-5.4/mmc-sdhci-sprd-fix-vqmmc-not-shutting-down-after-the.patch [new file with mode: 0644]
queue-5.4/perf-core-add-a-new-read-format-to-get-a-number-of-l.patch [new file with mode: 0644]
queue-5.4/perf-fix-perf_event_validate_size.patch [new file with mode: 0644]
queue-5.4/series

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 (file)
index 0000000..839a334
--- /dev/null
@@ -0,0 +1,61 @@
+From b5cc5c1c1edd62142a46ecdd2a108e2709573571 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Nov 2023 16:23:07 +0100
+Subject: gpiolib: sysfs: Fix error handling on failed export
+
+From: Boerge Struempfel <boerge.struempfel@gmail.com>
+
+[ 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 <boerge.struempfel@gmail.com>
+Reviewed-by: Andy Shevchenko <andy@kernel.org>
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..535cadd
--- /dev/null
@@ -0,0 +1,100 @@
+From 502f10af856972dd72bdc984535d0dc101a147db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Mar 2023 23:39:55 +0100
+Subject: mmc: core: add helpers mmc_regulator_enable/disable_vqmmc
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ 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 <hkallweit1@gmail.com>
+Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Link: https://lore.kernel.org/r/71586432-360f-9b92-17f6-b05a8a971bc2@gmail.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Stable-dep-of: 477865af60b2 ("mmc: sdhci-sprd: Fix vqmmc not shutting down after the card was pulled")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1c9b502
--- /dev/null
@@ -0,0 +1,94 @@
+From dff1e89408ce049365c9bd51263607a9f9e0d374 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <wenchao.chen@unisoc.com>
+
+[ 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 <wenchao.chen@unisoc.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20231115083406.7368-1-wenchao.chen@unisoc.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..04db3c9
--- /dev/null
@@ -0,0 +1,194 @@
+From 38a1b0b4f9d800018b1896b4e55351fb5eefedd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <namhyung@kernel.org>
+
+[ 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 <jolsa@redhat.com>
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..dd44712
--- /dev/null
@@ -0,0 +1,135 @@
+From 707b43abd87582f5f4b508649dfc975f90926211 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Nov 2023 15:24:52 +0100
+Subject: perf: Fix perf_event_validate_size()
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ 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 <markovicbudimir@gmail.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
index 4a1408634aae50af794a223378767a8930e4e3fd..4d6b95a5b75bcbea93920cd016584dfee02d032b 100644 (file)
@@ -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