]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Tue, 8 Dec 2020 15:01:45 +0000 (10:01 -0500)
committerSasha Levin <sashal@kernel.org>
Tue, 8 Dec 2020 15:01:45 +0000 (10:01 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.4/partially-revert-bpf-zero-fill-re-used-per-cpu-map-e.patch [new file with mode: 0644]
queue-5.4/pinctrl-baytrail-fix-pin-being-driven-low-for-a-whil.patch [new file with mode: 0644]
queue-5.4/pinctrl-baytrail-replace-warn-with-dev_info_once-whe.patch [new file with mode: 0644]
queue-5.4/series [new file with mode: 0644]

diff --git a/queue-5.4/partially-revert-bpf-zero-fill-re-used-per-cpu-map-e.patch b/queue-5.4/partially-revert-bpf-zero-fill-re-used-per-cpu-map-e.patch
new file mode 100644 (file)
index 0000000..c9ee5eb
--- /dev/null
@@ -0,0 +1,278 @@
+From 2524c75f0640a2ddc74abbfaa80ebb4202cf42c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Dec 2020 09:52:46 -0500
+Subject: Partially revert bpf: Zero-fill re-used per-cpu map element
+
+Drop the added selftest as it depends on functionality that doesn't
+exist in 5.4.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/prog_tests/map_init.c       | 214 ------------------
+ .../selftests/bpf/progs/test_map_init.c       |  33 ---
+ 2 files changed, 247 deletions(-)
+ delete mode 100644 tools/testing/selftests/bpf/prog_tests/map_init.c
+ delete mode 100644 tools/testing/selftests/bpf/progs/test_map_init.c
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/map_init.c b/tools/testing/selftests/bpf/prog_tests/map_init.c
+deleted file mode 100644
+index 14a31109dd0e0..0000000000000
+--- a/tools/testing/selftests/bpf/prog_tests/map_init.c
++++ /dev/null
+@@ -1,214 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/* Copyright (c) 2020 Tessares SA <http://www.tessares.net> */
+-
+-#include <test_progs.h>
+-#include "test_map_init.skel.h"
+-
+-#define TEST_VALUE 0x1234
+-#define FILL_VALUE 0xdeadbeef
+-
+-static int nr_cpus;
+-static int duration;
+-
+-typedef unsigned long long map_key_t;
+-typedef unsigned long long map_value_t;
+-typedef struct {
+-      map_value_t v; /* padding */
+-} __bpf_percpu_val_align pcpu_map_value_t;
+-
+-
+-static int map_populate(int map_fd, int num)
+-{
+-      pcpu_map_value_t value[nr_cpus];
+-      int i, err;
+-      map_key_t key;
+-
+-      for (i = 0; i < nr_cpus; i++)
+-              bpf_percpu(value, i) = FILL_VALUE;
+-
+-      for (key = 1; key <= num; key++) {
+-              err = bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST);
+-              if (!ASSERT_OK(err, "bpf_map_update_elem"))
+-                      return -1;
+-      }
+-
+-      return 0;
+-}
+-
+-static struct test_map_init *setup(enum bpf_map_type map_type, int map_sz,
+-                          int *map_fd, int populate)
+-{
+-      struct test_map_init *skel;
+-      int err;
+-
+-      skel = test_map_init__open();
+-      if (!ASSERT_OK_PTR(skel, "skel_open"))
+-              return NULL;
+-
+-      err = bpf_map__set_type(skel->maps.hashmap1, map_type);
+-      if (!ASSERT_OK(err, "bpf_map__set_type"))
+-              goto error;
+-
+-      err = bpf_map__set_max_entries(skel->maps.hashmap1, map_sz);
+-      if (!ASSERT_OK(err, "bpf_map__set_max_entries"))
+-              goto error;
+-
+-      err = test_map_init__load(skel);
+-      if (!ASSERT_OK(err, "skel_load"))
+-              goto error;
+-
+-      *map_fd = bpf_map__fd(skel->maps.hashmap1);
+-      if (CHECK(*map_fd < 0, "bpf_map__fd", "failed\n"))
+-              goto error;
+-
+-      err = map_populate(*map_fd, populate);
+-      if (!ASSERT_OK(err, "map_populate"))
+-              goto error_map;
+-
+-      return skel;
+-
+-error_map:
+-      close(*map_fd);
+-error:
+-      test_map_init__destroy(skel);
+-      return NULL;
+-}
+-
+-/* executes bpf program that updates map with key, value */
+-static int prog_run_insert_elem(struct test_map_init *skel, map_key_t key,
+-                              map_value_t value)
+-{
+-      struct test_map_init__bss *bss;
+-
+-      bss = skel->bss;
+-
+-      bss->inKey = key;
+-      bss->inValue = value;
+-      bss->inPid = getpid();
+-
+-      if (!ASSERT_OK(test_map_init__attach(skel), "skel_attach"))
+-              return -1;
+-
+-      /* Let tracepoint trigger */
+-      syscall(__NR_getpgid);
+-
+-      test_map_init__detach(skel);
+-
+-      return 0;
+-}
+-
+-static int check_values_one_cpu(pcpu_map_value_t *value, map_value_t expected)
+-{
+-      int i, nzCnt = 0;
+-      map_value_t val;
+-
+-      for (i = 0; i < nr_cpus; i++) {
+-              val = bpf_percpu(value, i);
+-              if (val) {
+-                      if (CHECK(val != expected, "map value",
+-                                "unexpected for cpu %d: 0x%llx\n", i, val))
+-                              return -1;
+-                      nzCnt++;
+-              }
+-      }
+-
+-      if (CHECK(nzCnt != 1, "map value", "set for %d CPUs instead of 1!\n",
+-                nzCnt))
+-              return -1;
+-
+-      return 0;
+-}
+-
+-/* Add key=1 elem with values set for all CPUs
+- * Delete elem key=1
+- * Run bpf prog that inserts new key=1 elem with value=0x1234
+- *   (bpf prog can only set value for current CPU)
+- * Lookup Key=1 and check value is as expected for all CPUs:
+- *   value set by bpf prog for one CPU, 0 for all others
+- */
+-static void test_pcpu_map_init(void)
+-{
+-      pcpu_map_value_t value[nr_cpus];
+-      struct test_map_init *skel;
+-      int map_fd, err;
+-      map_key_t key;
+-
+-      /* max 1 elem in map so insertion is forced to reuse freed entry */
+-      skel = setup(BPF_MAP_TYPE_PERCPU_HASH, 1, &map_fd, 1);
+-      if (!ASSERT_OK_PTR(skel, "prog_setup"))
+-              return;
+-
+-      /* delete element so the entry can be re-used*/
+-      key = 1;
+-      err = bpf_map_delete_elem(map_fd, &key);
+-      if (!ASSERT_OK(err, "bpf_map_delete_elem"))
+-              goto cleanup;
+-
+-      /* run bpf prog that inserts new elem, re-using the slot just freed */
+-      err = prog_run_insert_elem(skel, key, TEST_VALUE);
+-      if (!ASSERT_OK(err, "prog_run_insert_elem"))
+-              goto cleanup;
+-
+-      /* check that key=1 was re-created by bpf prog */
+-      err = bpf_map_lookup_elem(map_fd, &key, value);
+-      if (!ASSERT_OK(err, "bpf_map_lookup_elem"))
+-              goto cleanup;
+-
+-      /* and has expected values */
+-      check_values_one_cpu(value, TEST_VALUE);
+-
+-cleanup:
+-      test_map_init__destroy(skel);
+-}
+-
+-/* Add key=1 and key=2 elems with values set for all CPUs
+- * Run bpf prog that inserts new key=3 elem
+- *   (only for current cpu; other cpus should have initial value = 0)
+- * Lookup Key=1 and check value is as expected for all CPUs
+- */
+-static void test_pcpu_lru_map_init(void)
+-{
+-      pcpu_map_value_t value[nr_cpus];
+-      struct test_map_init *skel;
+-      int map_fd, err;
+-      map_key_t key;
+-
+-      /* Set up LRU map with 2 elements, values filled for all CPUs.
+-       * With these 2 elements, the LRU map is full
+-       */
+-      skel = setup(BPF_MAP_TYPE_LRU_PERCPU_HASH, 2, &map_fd, 2);
+-      if (!ASSERT_OK_PTR(skel, "prog_setup"))
+-              return;
+-
+-      /* run bpf prog that inserts new key=3 element, re-using LRU slot */
+-      key = 3;
+-      err = prog_run_insert_elem(skel, key, TEST_VALUE);
+-      if (!ASSERT_OK(err, "prog_run_insert_elem"))
+-              goto cleanup;
+-
+-      /* check that key=3 replaced one of earlier elements */
+-      err = bpf_map_lookup_elem(map_fd, &key, value);
+-      if (!ASSERT_OK(err, "bpf_map_lookup_elem"))
+-              goto cleanup;
+-
+-      /* and has expected values */
+-      check_values_one_cpu(value, TEST_VALUE);
+-
+-cleanup:
+-      test_map_init__destroy(skel);
+-}
+-
+-void test_map_init(void)
+-{
+-      nr_cpus = bpf_num_possible_cpus();
+-      if (nr_cpus <= 1) {
+-              printf("%s:SKIP: >1 cpu needed for this test\n", __func__);
+-              test__skip();
+-              return;
+-      }
+-
+-      if (test__start_subtest("pcpu_map_init"))
+-              test_pcpu_map_init();
+-      if (test__start_subtest("pcpu_lru_map_init"))
+-              test_pcpu_lru_map_init();
+-}
+diff --git a/tools/testing/selftests/bpf/progs/test_map_init.c b/tools/testing/selftests/bpf/progs/test_map_init.c
+deleted file mode 100644
+index c89d28ead6737..0000000000000
+--- a/tools/testing/selftests/bpf/progs/test_map_init.c
++++ /dev/null
+@@ -1,33 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/* Copyright (c) 2020 Tessares SA <http://www.tessares.net> */
+-
+-#include "vmlinux.h"
+-#include <bpf/bpf_helpers.h>
+-
+-__u64 inKey = 0;
+-__u64 inValue = 0;
+-__u32 inPid = 0;
+-
+-struct {
+-      __uint(type, BPF_MAP_TYPE_PERCPU_HASH);
+-      __uint(max_entries, 2);
+-      __type(key, __u64);
+-      __type(value, __u64);
+-} hashmap1 SEC(".maps");
+-
+-
+-SEC("tp/syscalls/sys_enter_getpgid")
+-int sysenter_getpgid(const void *ctx)
+-{
+-      /* Just do it for once, when called from our own test prog. This
+-       * ensures the map value is only updated for a single CPU.
+-       */
+-      int cur_pid = bpf_get_current_pid_tgid() >> 32;
+-
+-      if (cur_pid == inPid)
+-              bpf_map_update_elem(&hashmap1, &inKey, &inValue, BPF_NOEXIST);
+-
+-      return 0;
+-}
+-
+-char _license[] SEC("license") = "GPL";
+-- 
+2.27.0
+
diff --git a/queue-5.4/pinctrl-baytrail-fix-pin-being-driven-low-for-a-whil.patch b/queue-5.4/pinctrl-baytrail-fix-pin-being-driven-low-for-a-whil.patch
new file mode 100644 (file)
index 0000000..fea8e6b
--- /dev/null
@@ -0,0 +1,174 @@
+From c3c77cad817f650b9da115ca7ce44f1deb1e7bdc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 6 Jun 2020 11:31:50 +0200
+Subject: pinctrl: baytrail: Fix pin being driven low for a while on
+ gpiod_get(..., GPIOD_OUT_HIGH)
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 156abe2961601d60a8c2a60c6dc8dd6ce7adcdaf upstream
+
+The pins on the Bay Trail SoC have separate input-buffer and output-buffer
+enable bits and a read of the level bit of the value register will always
+return the value from the input-buffer.
+
+The BIOS of a device may configure a pin in output-only mode, only enabling
+the output buffer, and write 1 to the level bit to drive the pin high.
+This 1 written to the level bit will be stored inside the data-latch of the
+output buffer.
+
+But a subsequent read of the value register will return 0 for the level bit
+because the input-buffer is disabled. This causes a read-modify-write as
+done by byt_gpio_set_direction() to write 0 to the level bit, driving the
+pin low!
+
+Before this commit byt_gpio_direction_output() relied on
+pinctrl_gpio_direction_output() to set the direction, followed by a call
+to byt_gpio_set() to apply the selected value. This causes the pin to
+go low between the pinctrl_gpio_direction_output() and byt_gpio_set()
+calls.
+
+Change byt_gpio_direction_output() to directly make the register
+modifications itself instead. Replacing the 2 subsequent writes to the
+value register with a single write.
+
+Note that the pinctrl code does not keep track internally of the direction,
+so not going through pinctrl_gpio_direction_output() is not an issue.
+
+This issue was noticed on a Trekstor SurfTab Twin 10.1. When the panel is
+already on at boot (no external monitor connected), then the i915 driver
+does a gpiod_get(..., GPIOD_OUT_HIGH) for the panel-enable GPIO. The
+temporarily going low of that GPIO was causing the panel to reset itself
+after which it would not show an image until it was turned off and back on
+again (until a full modeset was done on it). This commit fixes this.
+
+This commit also updates the byt_gpio_direction_input() to use direct
+register accesses instead of going through pinctrl_gpio_direction_input(),
+to keep it consistent with byt_gpio_direction_output().
+
+Note for backporting, this commit depends on:
+commit e2b74419e5cc ("pinctrl: baytrail: Replace WARN with dev_info_once
+when setting direct-irq pin to output")
+
+Cc: stable@vger.kernel.org
+Fixes: 86e3ef812fe3 ("pinctrl: baytrail: Update gpio chip operations")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+[sudip: use byt_gpio and vg->pdev->dev for dev_info()]
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/intel/pinctrl-baytrail.c | 67 +++++++++++++++++++-----
+ 1 file changed, 53 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
+index 326e85f0f3ab5..5a1174a8e2bac 100644
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -811,6 +811,21 @@ static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
+       pm_runtime_put(&vg->pdev->dev);
+ }
++static void byt_gpio_direct_irq_check(struct byt_gpio *vg,
++                                    unsigned int offset)
++{
++      void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
++
++      /*
++       * Before making any direction modifications, do a check if gpio is set
++       * for direct IRQ. On Bay Trail, setting GPIO to output does not make
++       * sense, so let's at least inform the caller before they shoot
++       * themselves in the foot.
++       */
++      if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
++              dev_info_once(&vg->pdev->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
++}
++
+ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+                                 struct pinctrl_gpio_range *range,
+                                 unsigned int offset,
+@@ -818,7 +833,6 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+ {
+       struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
+       void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+-      void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+       unsigned long flags;
+       u32 value;
+@@ -828,14 +842,8 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+       value &= ~BYT_DIR_MASK;
+       if (input)
+               value |= BYT_OUTPUT_EN;
+-      else if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
+-              /*
+-               * Before making any direction modifications, do a check if gpio
+-               * is set for direct IRQ.  On baytrail, setting GPIO to output
+-               * does not make sense, so let's at least inform the caller before
+-               * they shoot themselves in the foot.
+-               */
+-              dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
++      else
++              byt_gpio_direct_irq_check(vg, offset);
+       writel(value, val_reg);
+@@ -1176,19 +1184,50 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+ {
+-      return pinctrl_gpio_direction_input(chip->base + offset);
++      struct byt_gpio *vg = gpiochip_get_data(chip);
++      void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
++      unsigned long flags;
++      u32 reg;
++
++      raw_spin_lock_irqsave(&byt_lock, flags);
++
++      reg = readl(val_reg);
++      reg &= ~BYT_DIR_MASK;
++      reg |= BYT_OUTPUT_EN;
++      writel(reg, val_reg);
++
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
++      return 0;
+ }
++/*
++ * Note despite the temptation this MUST NOT be converted into a call to
++ * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this
++ * MUST be done as a single BYT_VAL_REG register write.
++ * See the commit message of the commit adding this comment for details.
++ */
+ static int byt_gpio_direction_output(struct gpio_chip *chip,
+                                    unsigned int offset, int value)
+ {
+-      int ret = pinctrl_gpio_direction_output(chip->base + offset);
++      struct byt_gpio *vg = gpiochip_get_data(chip);
++      void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
++      unsigned long flags;
++      u32 reg;
+-      if (ret)
+-              return ret;
++      raw_spin_lock_irqsave(&byt_lock, flags);
+-      byt_gpio_set(chip, offset, value);
++      byt_gpio_direct_irq_check(vg, offset);
++      reg = readl(val_reg);
++      reg &= ~BYT_DIR_MASK;
++      if (value)
++              reg |= BYT_LEVEL;
++      else
++              reg &= ~BYT_LEVEL;
++
++      writel(reg, val_reg);
++
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+-- 
+2.27.0
+
diff --git a/queue-5.4/pinctrl-baytrail-replace-warn-with-dev_info_once-whe.patch b/queue-5.4/pinctrl-baytrail-replace-warn-with-dev_info_once-whe.patch
new file mode 100644 (file)
index 0000000..2a24e14
--- /dev/null
@@ -0,0 +1,63 @@
+From 6c69f88c2811659ff37b2c0e1c2b0471114db3dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Jan 2020 15:52:43 +0100
+Subject: pinctrl: baytrail: Replace WARN with dev_info_once when setting
+ direct-irq pin to output
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit e2b74419e5cc7cfc58f3e785849f73f8fa0af5b3 upstream
+
+Suspending Goodix touchscreens requires changing the interrupt pin to
+output before sending them a power-down command. Followed by wiggling
+the interrupt pin to wake the device up, after which it is put back
+in input mode.
+
+On Cherry Trail device the interrupt pin is listed as a GpioInt ACPI
+resource so we can do this without problems as long as we release the
+IRQ before changing the pin to output mode.
+
+On Bay Trail devices with a Goodix touchscreen direct-irq mode is used
+in combination with listing the pin as a normal GpioIo resource. This
+works fine, but this triggers the WARN in byt_gpio_set_direction-s output
+path because direct-irq support is enabled on the pin.
+
+This commit replaces the WARN call with a dev_info_once call, fixing a
+bunch of WARN splats in dmesg on each suspend/resume cycle.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/intel/pinctrl-baytrail.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
+index cae7caf5ab282..326e85f0f3ab5 100644
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -828,15 +828,15 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+       value &= ~BYT_DIR_MASK;
+       if (input)
+               value |= BYT_OUTPUT_EN;
+-      else
++      else if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
+               /*
+                * Before making any direction modifications, do a check if gpio
+                * is set for direct IRQ.  On baytrail, setting GPIO to output
+-               * does not make sense, so let's at least warn the caller before
++               * does not make sense, so let's at least inform the caller before
+                * they shoot themselves in the foot.
+                */
+-              WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
+-                   "Potential Error: Setting GPIO with direct_irq_en to output");
++              dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
++
+       writel(value, val_reg);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
+-- 
+2.27.0
+
diff --git a/queue-5.4/series b/queue-5.4/series
new file mode 100644 (file)
index 0000000..6262dbf
--- /dev/null
@@ -0,0 +1,3 @@
+pinctrl-baytrail-replace-warn-with-dev_info_once-whe.patch
+pinctrl-baytrail-fix-pin-being-driven-low-for-a-whil.patch
+partially-revert-bpf-zero-fill-re-used-per-cpu-map-e.patch