From: Sasha Levin Date: Tue, 8 Dec 2020 15:01:45 +0000 (-0500) Subject: Fixes for 5.4 X-Git-Tag: v5.9.14~60 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fc97239db906b103935153d5e0143251bb3b8979;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- 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 index 00000000000..c9ee5eb60c6 --- /dev/null +++ b/queue-5.4/partially-revert-bpf-zero-fill-re-used-per-cpu-map-e.patch @@ -0,0 +1,278 @@ +From 2524c75f0640a2ddc74abbfaa80ebb4202cf42c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 +--- + .../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 */ +- +-#include +-#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 */ +- +-#include "vmlinux.h" +-#include +- +-__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 index 00000000000..fea8e6b7c0c --- /dev/null +++ b/queue-5.4/pinctrl-baytrail-fix-pin-being-driven-low-for-a-whil.patch @@ -0,0 +1,174 @@ +From c3c77cad817f650b9da115ca7ce44f1deb1e7bdc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +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 +Acked-by: Mika Westerberg +Signed-off-by: Andy Shevchenko +[sudip: use byt_gpio and vg->pdev->dev for dev_info()] +Signed-off-by: Sudip Mukherjee +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2a24e14e64e --- /dev/null +++ b/queue-5.4/pinctrl-baytrail-replace-warn-with-dev_info_once-whe.patch @@ -0,0 +1,63 @@ +From 6c69f88c2811659ff37b2c0e1c2b0471114db3dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +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 +Acked-by: Mika Westerberg +Signed-off-by: Andy Shevchenko +Signed-off-by: Sudip Mukherjee +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6262dbfe5cc --- /dev/null +++ b/queue-5.4/series @@ -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