From: Sagi Grimberg sagi@grimberg.me
[ Upstream commit 1616d6c3717bae9041a4240d381ec56ccdaafedc ]
Add a quirk to fix HS-SSD-FUTURE 2048G SSD drives reporting duplicate nsids.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=217384 Reported-by: Andrey God andreygod83@protonmail.com Signed-off-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/pci.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index cd7873de31215..bbf96567365cd 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3445,6 +3445,8 @@ static const struct pci_device_id nvme_id_table[] = { NVME_QUIRK_IGNORE_DEV_SUBNQN, }, { PCI_DEVICE(0x10ec, 0x5763), /* TEAMGROUP T-FORCE CARDEA ZERO Z330 SSD */ .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1e4b, 0x1602), /* HS-SSD-FUTURE 2048G */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061), .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0065),
From: Hristo Venev hristo@venev.name
[ Upstream commit bd375feeaf3408ed00e08c3bc918d6be15f691ad ]
On Kingston KC3000 and Kingston FURY Renegade (both have the same PCI IDs) accessing temp3_{min,max} fails with an invalid field error (note that there is no problem setting the thresholds for temp1).
This contradicts the NVM Express Base Specification 2.0b, page 292:
The over temperature threshold and under temperature threshold features shall be implemented for all implemented temperature sensors (i.e., all Temperature Sensor fields that report a non-zero value).
Define NVME_QUIRK_NO_SECONDARY_TEMP_THRESH that disables the thresholds for all but the composite temperature and set it for this device.
Signed-off-by: Hristo Venev hristo@venev.name Reviewed-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/hwmon.c | 4 +++- drivers/nvme/host/nvme.h | 5 +++++ drivers/nvme/host/pci.c | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/hwmon.c b/drivers/nvme/host/hwmon.c index 9e6e56c20ec99..316f3e4ca7cc6 100644 --- a/drivers/nvme/host/hwmon.c +++ b/drivers/nvme/host/hwmon.c @@ -163,7 +163,9 @@ static umode_t nvme_hwmon_is_visible(const void *_data, case hwmon_temp_max: case hwmon_temp_min: if ((!channel && data->ctrl->wctemp) || - (channel && data->log->temp_sensor[channel - 1])) { + (channel && data->log->temp_sensor[channel - 1] && + !(data->ctrl->quirks & + NVME_QUIRK_NO_SECONDARY_TEMP_THRESH))) { if (data->ctrl->quirks & NVME_QUIRK_NO_TEMP_THRESH_CHANGE) return 0444; diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index bf46f122e9e1e..a2d4f59e0535a 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -149,6 +149,11 @@ enum nvme_quirks { * Reports garbage in the namespace identifiers (eui64, nguid, uuid). */ NVME_QUIRK_BOGUS_NID = (1 << 18), + + /* + * No temperature thresholds for channels other than 0 (Composite). + */ + NVME_QUIRK_NO_SECONDARY_TEMP_THRESH = (1 << 19), };
/* diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index bbf96567365cd..a7772c0194d5a 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3406,6 +3406,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, { PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, + { PCI_DEVICE(0x2646, 0x5013), /* Kingston KC3000, Kingston FURY Renegade */ + .driver_data = NVME_QUIRK_NO_SECONDARY_TEMP_THRESH, }, { PCI_DEVICE(0x2646, 0x5018), /* KINGSTON OM8SFP4xxxxP OS21012 NVMe SSD */ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, { PCI_DEVICE(0x2646, 0x5016), /* KINGSTON OM3PGP4xxxxP OS21011 NVMe SSD */
From: Adrian Huang ahuang12@lenovo.com
[ Upstream commit 3710e2b056cb92ad816e4d79fa54a6a5b6ad8cbd ]
When running the fio test on a 448-core AMD server + a NVME disk, a soft lockup or a hard lockup call trace is shown:
[soft lockup] watchdog: BUG: soft lockup - CPU#126 stuck for 23s! [swapper/126:0] RIP: 0010:_raw_spin_unlock_irqrestore+0x21/0x50 ... Call Trace: <IRQ> fq_flush_timeout+0x7d/0xd0 ? __pfx_fq_flush_timeout+0x10/0x10 call_timer_fn+0x2e/0x150 run_timer_softirq+0x48a/0x560 ? __pfx_fq_flush_timeout+0x10/0x10 ? clockevents_program_event+0xaf/0x130 __do_softirq+0xf1/0x335 irq_exit_rcu+0x9f/0xd0 sysvec_apic_timer_interrupt+0xb4/0xd0 </IRQ> <TASK> asm_sysvec_apic_timer_interrupt+0x1f/0x30 ...
Obvisouly, fq_flush_timeout spends over 20 seconds. Here is ftrace log:
| fq_flush_timeout() { | fq_ring_free() { | put_pages_list() { 0.170 us | free_unref_page_list(); 0.810 us | } | free_iova_fast() { | free_iova() { * 85622.66 us | _raw_spin_lock_irqsave(); 2.860 us | remove_iova(); 0.600 us | _raw_spin_unlock_irqrestore(); 0.470 us | lock_info_report(); 2.420 us | free_iova_mem.part.0(); * 85638.27 us | } * 85638.84 us | } | put_pages_list() { 0.230 us | free_unref_page_list(); 0.470 us | } ... ... $ 31017069 us | }
Most of cores are under lock contention for acquiring iova_rbtree_lock due to the iova flush queue mechanism.
[hard lockup] NMI watchdog: Watchdog detected hard LOCKUP on cpu 351 RIP: 0010:native_queued_spin_lock_slowpath+0x2d8/0x330
Call Trace: <IRQ> _raw_spin_lock_irqsave+0x4f/0x60 free_iova+0x27/0xd0 free_iova_fast+0x4d/0x1d0 fq_ring_free+0x9b/0x150 iommu_dma_free_iova+0xb4/0x2e0 __iommu_dma_unmap+0x10b/0x140 iommu_dma_unmap_sg+0x90/0x110 dma_unmap_sg_attrs+0x4a/0x50 nvme_unmap_data+0x5d/0x120 [nvme] nvme_pci_complete_batch+0x77/0xc0 [nvme] nvme_irq+0x2ee/0x350 [nvme] ? __pfx_nvme_pci_complete_batch+0x10/0x10 [nvme] __handle_irq_event_percpu+0x53/0x1a0 handle_irq_event_percpu+0x19/0x60 handle_irq_event+0x3d/0x60 handle_edge_irq+0xb3/0x210 __common_interrupt+0x7f/0x150 common_interrupt+0xc5/0xf0 </IRQ> <TASK> asm_common_interrupt+0x2b/0x40 ...
ftrace shows fq_ring_free spends over 10 seconds [1]. Again, most of cores are under lock contention for acquiring iova_rbtree_lock due to the iova flush queue mechanism.
[Root Cause] The root cause is that the max_hw_sectors_kb of nvme disk (mdts=10) is 4096kb, which streaming DMA mappings cannot benefit from the scalable IOVA mechanism introduced by the commit 9257b4a206fc ("iommu/iova: introduce per-cpu caching to iova allocation") if the length is greater than 128kb.
To fix the lock contention issue, clamp max_hw_sectors based on DMA optimized limitation in order to leverage scalable IOVA mechanism.
Note: The issue does not happen with another NVME disk (mdts = 5 and max_hw_sectors_kb = 128)
[1] https://gist.github.com/AdrianHuang/bf8ec7338204837631fbdaed25d19cc4
Suggested-by: Keith Busch kbusch@kernel.org Reported-and-tested-by: Jiwei Sun sunjw10@lenovo.com Signed-off-by: Adrian Huang ahuang12@lenovo.com Reviewed-by: Keith Busch kbusch@kernel.org Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index a7772c0194d5a..a389f1ea0b151 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2960,7 +2960,7 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev, * over a single page. */ dev->ctrl.max_hw_sectors = min_t(u32, - NVME_MAX_KB_SZ << 1, dma_max_mapping_size(&pdev->dev) >> 9); + NVME_MAX_KB_SZ << 1, dma_opt_mapping_size(&pdev->dev) >> 9); dev->ctrl.max_segments = NVME_MAX_SEGS;
/*
From: Jeremy Soller jeremy@system76.com
[ Upstream commit 7b9891ad25246b18b5ccc19518da7abc7763aa0a ]
Add pang12 quirk to enable the internal microphone.
Signed-off-by: Jeremy Soller <jeremy@system76.com Signed-off-by: Tim Crawford <tcrawford@system76.com Link: https://lore.kernel.org/r/20230505161458.19676-1-tcrawford@system76.com Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 0acdf0156f075..b844f321d139e 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -276,6 +276,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_BOARD_NAME, "8A22"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "System76"), + DMI_MATCH(DMI_PRODUCT_VERSION, "pang12"), + } + }, {} };
From: Maxim Kochetkov fido_max@inbox.ru
[ Upstream commit ab6ecfbf40fccf74b6ec2ba7ed6dd2fc024c3af2 ]
On slow CPU (FPGA/QEMU emulated) printing overrun messages from interrupt handler to uart console may leads to more overrun errors. So use dev_err_ratelimited to limit the number of error messages.
Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru Link: https://lore.kernel.org/r/20230505062820.21840-1-fido_max@inbox.ru Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/dwc/dwc-i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 7f7dd07c63b2f..3496301582b22 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -132,13 +132,13 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
/* Error Handling: TX */ if (isr[i] & ISR_TXFO) { - dev_err(dev->dev, "TX overrun (ch_id=%d)\n", i); + dev_err_ratelimited(dev->dev, "TX overrun (ch_id=%d)\n", i); irq_valid = true; }
/* Error Handling: TX */ if (isr[i] & ISR_RXFO) { - dev_err(dev->dev, "RX overrun (ch_id=%d)\n", i); + dev_err_ratelimited(dev->dev, "RX overrun (ch_id=%d)\n", i); irq_valid = true; } }
From: Hao Zeng zenghao@kylinos.cn
[ Upstream commit e652be0f59d4ba4d5c636b1f7f4dcb73aae049fa ]
The sysfs_get_enabled() opened file processor not closed, may cause a file handle leak. Putting error handling and resource cleanup code together makes the code easy to maintain and read. Removed the unnecessary else if branch from the original function, as it should return an error in cases other than '0'.
Signed-off-by: Hao Zeng zenghao@kylinos.cn Suggested-by: Shuah Khan skhan@linuxfoundation.org Signed-off-by: Shuah Khan skhan@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/power/cpupower/lib/powercap.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/tools/power/cpupower/lib/powercap.c b/tools/power/cpupower/lib/powercap.c index 0ce29ee4c2e46..a7a59c6bacda8 100644 --- a/tools/power/cpupower/lib/powercap.c +++ b/tools/power/cpupower/lib/powercap.c @@ -40,25 +40,34 @@ static int sysfs_get_enabled(char *path, int *mode) { int fd; char yes_no; + int ret = 0;
*mode = 0;
fd = open(path, O_RDONLY); - if (fd == -1) - return -1; + if (fd == -1) { + ret = -1; + goto out; + }
if (read(fd, &yes_no, 1) != 1) { - close(fd); - return -1; + ret = -1; + goto out_close; }
if (yes_no == '1') { *mode = 1; - return 0; + goto out_close; } else if (yes_no == '0') { - return 0; + goto out_close; + } else { + ret = -1; + goto out_close; } - return -1; +out_close: + close(fd); +out: + return ret; }
int powercap_get_enabled(int *mode)
From: Mark Brown broonie@kernel.org
[ Upstream commit dbcf76390eb9a65d5d0c37b0cd57335218564e37 ]
The ftrace selftests do not currently produce KTAP output, they produce a custom format much nicer for human consumption. This means that when run in automated test systems we just get a single result for the suite as a whole rather than recording results for individual test cases, making it harder to look at the test data and masking things like inappropriate skips.
Address this by adding support for KTAP output to the ftracetest script and providing a trivial wrapper which will be invoked by the kselftest runner to generate output in this format by default, users using ftracetest directly will continue to get the existing output.
This is not the most elegant solution but it is simple and effective. I did consider implementing this by post processing the existing output format but that felt more complex and likely to result in all output being lost if something goes seriously wrong during the run which would not be helpful. I did also consider just writing a separate runner script but there's enough going on with things like the signal handling for that to seem like it would be duplicating too much.
Acked-by: Steven Rostedt (Google) rostedt@goodmis.org Acked-by: Masami Hiramatsu (Google) mhiramat@kernel.org Tested-by: Masami Hiramatsu (Google) mhiramat@kernel.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Shuah Khan skhan@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/ftrace/Makefile | 3 +- tools/testing/selftests/ftrace/ftracetest | 63 ++++++++++++++++++- .../testing/selftests/ftrace/ftracetest-ktap | 8 +++ 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100755 tools/testing/selftests/ftrace/ftracetest-ktap
diff --git a/tools/testing/selftests/ftrace/Makefile b/tools/testing/selftests/ftrace/Makefile index d6e106fbce11c..a1e955d2de4cc 100644 --- a/tools/testing/selftests/ftrace/Makefile +++ b/tools/testing/selftests/ftrace/Makefile @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 all:
-TEST_PROGS := ftracetest +TEST_PROGS_EXTENDED := ftracetest +TEST_PROGS := ftracetest-ktap TEST_FILES := test.d settings EXTRA_CLEAN := $(OUTPUT)/logs/*
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest index c3311c8c40890..2506621e75dfb 100755 --- a/tools/testing/selftests/ftrace/ftracetest +++ b/tools/testing/selftests/ftrace/ftracetest @@ -13,6 +13,7 @@ echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]" echo " Options:" echo " -h|--help Show help message" echo " -k|--keep Keep passed test logs" +echo " -K|--ktap Output in KTAP format" echo " -v|--verbose Increase verbosity of test messages" echo " -vv Alias of -v -v (Show all results in stdout)" echo " -vvv Alias of -v -v -v (Show all commands immediately)" @@ -85,6 +86,10 @@ parse_opts() { # opts KEEP_LOG=1 shift 1 ;; + --ktap|-K) + KTAP=1 + shift 1 + ;; --verbose|-v|-vv|-vvv) if [ $VERBOSE -eq -1 ]; then usage "--console can not use with --verbose" @@ -178,6 +183,7 @@ TEST_DIR=$TOP_DIR/test.d TEST_CASES=`find_testcases $TEST_DIR` LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/ KEEP_LOG=0 +KTAP=0 DEBUG=0 VERBOSE=0 UNSUPPORTED_RESULT=0 @@ -229,7 +235,7 @@ prlog() { # messages newline= shift fi - printf "$*$newline" + [ "$KTAP" != "1" ] && printf "$*$newline" [ "$LOG_FILE" ] && printf "$*$newline" | strip_esc >> $LOG_FILE } catlog() { #file @@ -260,11 +266,11 @@ TOTAL_RESULT=0
INSTANCE= CASENO=0 +CASENAME=
testcase() { # testfile CASENO=$((CASENO+1)) - desc=`grep "^#[ \t]*description:" $1 | cut -f2- -d:` - prlog -n "[$CASENO]$INSTANCE$desc" + CASENAME=`grep "^#[ \t]*description:" $1 | cut -f2- -d:` }
checkreq() { # testfile @@ -277,40 +283,68 @@ test_on_instance() { # testfile grep -q "^#[ \t]*flags:.*instance" $1 }
+ktaptest() { # result comment + if [ "$KTAP" != "1" ]; then + return + fi + + local result= + if [ "$1" = "1" ]; then + result="ok" + else + result="not ok" + fi + shift + + local comment=$* + if [ "$comment" != "" ]; then + comment="# $comment" + fi + + echo $CASENO $result $INSTANCE$CASENAME $comment +} + eval_result() { # sigval case $1 in $PASS) prlog " [${color_green}PASS${color_reset}]" + ktaptest 1 PASSED_CASES="$PASSED_CASES $CASENO" return 0 ;; $FAIL) prlog " [${color_red}FAIL${color_reset}]" + ktaptest 0 FAILED_CASES="$FAILED_CASES $CASENO" return 1 # this is a bug. ;; $UNRESOLVED) prlog " [${color_blue}UNRESOLVED${color_reset}]" + ktaptest 0 UNRESOLVED UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO" return $UNRESOLVED_RESULT # depends on use case ;; $UNTESTED) prlog " [${color_blue}UNTESTED${color_reset}]" + ktaptest 1 SKIP UNTESTED_CASES="$UNTESTED_CASES $CASENO" return 0 ;; $UNSUPPORTED) prlog " [${color_blue}UNSUPPORTED${color_reset}]" + ktaptest 1 SKIP UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO" return $UNSUPPORTED_RESULT # depends on use case ;; $XFAIL) prlog " [${color_green}XFAIL${color_reset}]" + ktaptest 1 XFAIL XFAILED_CASES="$XFAILED_CASES $CASENO" return 0 ;; *) prlog " [${color_blue}UNDEFINED${color_reset}]" + ktaptest 0 error UNDEFINED_CASES="$UNDEFINED_CASES $CASENO" return 1 # this must be a test bug ;; @@ -371,6 +405,7 @@ __run_test() { # testfile run_test() { # testfile local testname=`basename $1` testcase $1 + prlog -n "[$CASENO]$INSTANCE$CASENAME" if [ ! -z "$LOG_FILE" ] ; then local testlog=`mktemp $LOG_DIR/${CASENO}-${testname}-log.XXXXXX` else @@ -405,6 +440,17 @@ run_test() { # testfile # load in the helper functions . $TEST_DIR/functions
+if [ "$KTAP" = "1" ]; then + echo "TAP version 13" + + casecount=`echo $TEST_CASES | wc -w` + for t in $TEST_CASES; do + test_on_instance $t || continue + casecount=$((casecount+1)) + done + echo "1..${casecount}" +fi + # Main loop for t in $TEST_CASES; do run_test $t @@ -439,6 +485,17 @@ prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w` prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w` prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w`
+if [ "$KTAP" = "1" ]; then + echo -n "# Totals:" + echo -n " pass:"`echo $PASSED_CASES | wc -w` + echo -n " faii:"`echo $FAILED_CASES | wc -w` + echo -n " xfail:"`echo $XFAILED_CASES | wc -w` + echo -n " xpass:0" + echo -n " skip:"`echo $UNTESTED_CASES $UNSUPPORTED_CASES | wc -w` + echo -n " error:"`echo $UNRESOLVED_CASES $UNDEFINED_CASES | wc -w` + echo +fi + cleanup
# if no error, return 0 diff --git a/tools/testing/selftests/ftrace/ftracetest-ktap b/tools/testing/selftests/ftrace/ftracetest-ktap new file mode 100755 index 0000000000000..b3284679ef3af --- /dev/null +++ b/tools/testing/selftests/ftrace/ftracetest-ktap @@ -0,0 +1,8 @@ +#!/bin/sh -e +# SPDX-License-Identifier: GPL-2.0-only +# +# ftracetest-ktap: Wrapper to integrate ftracetest with the kselftest runner +# +# Copyright (C) Arm Ltd., 2023 + +./ftracetest -K
On Thu, May 25, 2023 at 02:30:44PM -0400, Sasha Levin wrote:
From: Mark Brown broonie@kernel.org
[ Upstream commit dbcf76390eb9a65d5d0c37b0cd57335218564e37 ]
The ftrace selftests do not currently produce KTAP output, they produce a custom format much nicer for human consumption. This means that when run in automated test systems we just get a single result for the suite as a whole rather than recording results for individual test cases, making it harder to look at the test data and masking things like inappropriate skips.
This seems to be very much a new feature rather than a fix?
On Fri, May 26, 2023 at 04:23:33PM +0100, Mark Brown wrote:
On Thu, May 25, 2023 at 02:30:44PM -0400, Sasha Levin wrote:
From: Mark Brown broonie@kernel.org
[ Upstream commit dbcf76390eb9a65d5d0c37b0cd57335218564e37 ]
The ftrace selftests do not currently produce KTAP output, they produce a custom format much nicer for human consumption. This means that when run in automated test systems we just get a single result for the suite as a whole rather than recording results for individual test cases, making it harder to look at the test data and masking things like inappropriate skips.
This seems to be very much a new feature rather than a fix?
Yup, I'll drop it. Thanks!
From: V sujith kumar Reddy Vsujithkumar.Reddy@amd.com
[ Upstream commit 051d71e073614a72ad423d6dacba37a7eeff274d ]
Check substream and runtime variables before assigning.
Signed-off-by: V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com Link: https://lore.kernel.org/r/20230508070510.6100-1-Vsujithkumar.Reddy@amd.com Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/amd/acp-ipc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c index 4e0c48a361599..749e856dc6011 100644 --- a/sound/soc/sof/amd/acp-ipc.c +++ b/sound/soc/sof/amd/acp-ipc.c @@ -209,7 +209,12 @@ int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sp acp_mailbox_read(sdev, offset, p, sz); } else { struct snd_pcm_substream *substream = sps->substream; - struct acp_dsp_stream *stream = substream->runtime->private_data; + struct acp_dsp_stream *stream; + + if (!substream || !substream->runtime) + return -ESTRPIPE; + + stream = substream->runtime->private_data;
if (!stream) return -ESTRPIPE;
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit 73a23d7710331a530e972903318528b75e5a5f58 ]
Since we no longer (want to) export any libc symbols the _user portions of any drivers need to be built into image rather than the module. I missed this for the watchdog. Fix the watchdog accordingly.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Richard Weinberger richard@nod.at Signed-off-by: Sasha Levin sashal@kernel.org --- arch/um/drivers/Makefile | 4 +++- arch/um/drivers/harddog.h | 9 +++++++++ arch/um/drivers/harddog_kern.c | 7 +------ arch/um/drivers/harddog_user.c | 1 + arch/um/drivers/harddog_user_exp.c | 9 +++++++++ 5 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 arch/um/drivers/harddog.h create mode 100644 arch/um/drivers/harddog_user_exp.c
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index dee6f66353b33..a461a950f0518 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -16,7 +16,8 @@ mconsole-objs := mconsole_kern.o mconsole_user.o hostaudio-objs := hostaudio_kern.o ubd-objs := ubd_kern.o ubd_user.o port-objs := port_kern.o port_user.o -harddog-objs := harddog_kern.o harddog_user.o +harddog-objs := harddog_kern.o +harddog-builtin-$(CONFIG_UML_WATCHDOG) := harddog_user.o harddog_user_exp.o rtc-objs := rtc_kern.o rtc_user.o
LDFLAGS_pcap.o = $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libpcap.a) @@ -60,6 +61,7 @@ obj-$(CONFIG_PTY_CHAN) += pty.o obj-$(CONFIG_TTY_CHAN) += tty.o obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o obj-$(CONFIG_UML_WATCHDOG) += harddog.o +obj-y += $(harddog-builtin-y) $(harddog-builtin-m) obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o obj-$(CONFIG_UML_RANDOM) += random.o obj-$(CONFIG_VIRTIO_UML) += virtio_uml.o diff --git a/arch/um/drivers/harddog.h b/arch/um/drivers/harddog.h new file mode 100644 index 0000000000000..6d9ea60e7133e --- /dev/null +++ b/arch/um/drivers/harddog.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef UM_WATCHDOG_H +#define UM_WATCHDOG_H + +int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); +void stop_watchdog(int in_fd, int out_fd); +int ping_watchdog(int fd); + +#endif /* UM_WATCHDOG_H */ diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index e6d4f43deba82..60d1c6cab8a95 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -47,6 +47,7 @@ #include <linux/spinlock.h> #include <linux/uaccess.h> #include "mconsole.h" +#include "harddog.h"
MODULE_LICENSE("GPL");
@@ -60,8 +61,6 @@ static int harddog_out_fd = -1; * Allow only one person to hold it open */
-extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); - static int harddog_open(struct inode *inode, struct file *file) { int err = -EBUSY; @@ -92,8 +91,6 @@ static int harddog_open(struct inode *inode, struct file *file) return err; }
-extern void stop_watchdog(int in_fd, int out_fd); - static int harddog_release(struct inode *inode, struct file *file) { /* @@ -112,8 +109,6 @@ static int harddog_release(struct inode *inode, struct file *file) return 0; }
-extern int ping_watchdog(int fd); - static ssize_t harddog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index 070468d22e394..9ed89304975ed 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c @@ -7,6 +7,7 @@ #include <unistd.h> #include <errno.h> #include <os.h> +#include "harddog.h"
struct dog_data { int stdin_fd; diff --git a/arch/um/drivers/harddog_user_exp.c b/arch/um/drivers/harddog_user_exp.c new file mode 100644 index 0000000000000..c74d4b815d143 --- /dev/null +++ b/arch/um/drivers/harddog_user_exp.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/export.h> +#include "harddog.h" + +#if IS_MODULE(CONFIG_UML_WATCHDOG) +EXPORT_SYMBOL(start_watchdog); +EXPORT_SYMBOL(stop_watchdog); +EXPORT_SYMBOL(ping_watchdog); +#endif
From: Benedict Wong benedictwong@google.com
[ Upstream commit 8680407b6f8f5fba59e8f1d63c869abc280f04df ]
This change ensures that if configured in the policy, the if_id set in the policy and secpath states match during the inbound policy check. Without this, there is potential for ambiguity where entries in the secpath differing by only the if_id could be mismatched.
Notably, this is checked in the outbound direction when resolving templates to SAs, but not on the inbound path when matching SAs and policies.
Test: Tested against Android kernel unit tests & CTS Signed-off-by: Benedict Wong benedictwong@google.com Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/xfrm/xfrm_policy.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 5c61ec04b839b..361b561908075 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3312,7 +3312,7 @@ xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl)
static inline int xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, - unsigned short family) + unsigned short family, u32 if_id) { if (xfrm_state_kern(x)) return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family); @@ -3323,7 +3323,8 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, (tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) || !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) && !(x->props.mode != XFRM_MODE_TRANSPORT && - xfrm_state_addr_cmp(tmpl, x, family)); + xfrm_state_addr_cmp(tmpl, x, family)) && + (if_id == 0 || if_id == x->if_id); }
/* @@ -3335,7 +3336,7 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, */ static inline int xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start, - unsigned short family) + unsigned short family, u32 if_id) { int idx = start;
@@ -3345,7 +3346,7 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star } else start = -1; for (; idx < sp->len; idx++) { - if (xfrm_state_ok(tmpl, sp->xvec[idx], family)) + if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id)) return ++idx; if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) { if (start == -1) @@ -3730,7 +3731,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, * are implied between each two transformations. */ for (i = xfrm_nr-1, k = 0; i >= 0; i--) { - k = xfrm_policy_ok(tpp[i], sp, k, family); + k = xfrm_policy_ok(tpp[i], sp, k, family, if_id); if (k < 0) { if (k < -1) /* "-2 - errored_index" returned */
From: Aidan MacDonald aidanmacdonald.0x0@gmail.com
[ Upstream commit ad721bc919edfd8b4b06977458a412011e2f0c50 ]
When the CPU supplies bit/frame clocks, the system clock (clk_i2s) is divided to produce the bit clock. This is a simple 1/N divider with a fairly limited range, so for a given system clock frequency only a few sample rates can be produced. Usually a wider range of sample rates is supported by varying the system clock frequency.
The old calculation method was not very robust and could easily produce the wrong clock rate, especially with non-standard rates. For example, if the system clock is 1.99x the target bit clock rate, the divider would be calculated as 1 instead of the more accurate 2.
Instead, use a more accurate method that considers two adjacent divider settings and selects the one that produces the least error versus the requested rate. If the error is 5% or higher then the rate setting is rejected to prevent garbled audio.
Skip divider calculation when the codec is supplying both the bit and frame clock; in that case, the divider outputs are unused and we don't want to constrain the sample rate.
Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com Link: https://lore.kernel.org/r/20230509125134.208129-1-aidanmacdonald.0x0@gmail.c... Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/jz4740/jz4740-i2s.c | 54 ++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-)
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 6d9cfe0a50411..d0f6c945d9aee 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -218,18 +218,48 @@ static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; }
+static int jz4740_i2s_get_i2sdiv(unsigned long mclk, unsigned long rate, + unsigned long i2sdiv_max) +{ + unsigned long div, rate1, rate2, err1, err2; + + div = mclk / (64 * rate); + if (div == 0) + div = 1; + + rate1 = mclk / (64 * div); + rate2 = mclk / (64 * (div + 1)); + + err1 = abs(rate1 - rate); + err2 = abs(rate2 - rate); + + /* + * Choose the divider that produces the smallest error in the + * output rate and reject dividers with a 5% or higher error. + * In the event that both dividers are outside the acceptable + * error margin, reject the rate to prevent distorted audio. + * (The number 5% is arbitrary.) + */ + if (div <= i2sdiv_max && err1 <= err2 && err1 < rate/20) + return div; + if (div < i2sdiv_max && err2 < rate/20) + return div + 1; + + return -EINVAL; +} + static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); struct regmap_field *div_field; + unsigned long i2sdiv_max; unsigned int sample_size; - uint32_t ctrl; - int div; + uint32_t ctrl, conf; + int div = 1;
regmap_read(i2s->regmap, JZ_REG_AIC_CTRL, &ctrl); - - div = clk_get_rate(i2s->clk_i2s) / (64 * params_rate(params)); + regmap_read(i2s->regmap, JZ_REG_AIC_CONF, &conf);
switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: @@ -258,11 +288,27 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO;
div_field = i2s->field_i2sdiv_playback; + i2sdiv_max = GENMASK(i2s->soc_info->field_i2sdiv_playback.msb, + i2s->soc_info->field_i2sdiv_playback.lsb); } else { ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE; ctrl |= FIELD_PREP(JZ_AIC_CTRL_INPUT_SAMPLE_SIZE, sample_size);
div_field = i2s->field_i2sdiv_capture; + i2sdiv_max = GENMASK(i2s->soc_info->field_i2sdiv_capture.msb, + i2s->soc_info->field_i2sdiv_capture.lsb); + } + + /* + * Only calculate I2SDIV if we're supplying the bit or frame clock. + * If the codec is supplying both clocks then the divider output is + * unused, and we don't want it to limit the allowed sample rates. + */ + if (conf & (JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER)) { + div = jz4740_i2s_get_i2sdiv(clk_get_rate(i2s->clk_i2s), + params_rate(params), i2sdiv_max); + if (div < 0) + return div; }
regmap_write(i2s->regmap, JZ_REG_AIC_CTRL, ctrl);
From: Martin Povišer povik+lin@cutebit.org
[ Upstream commit efb2bfd7b3d210c479b9361c176d7426e5eb8663 ]
A bunch of TI's codecs have binding schemas which force #sound-dai-cells to one despite those codecs only having a single DAI. Allow for bindings with zero DAI cells and deprecate the former non-zero value.
Signed-off-by: Martin Povišer <povik+lin@cutebit.org Link: https://lore.kernel.org/r/20230509153412.62847-1-povik+lin@cutebit.org Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- Documentation/devicetree/bindings/sound/tas2562.yaml | 6 ++++-- Documentation/devicetree/bindings/sound/tas2770.yaml | 6 ++++-- Documentation/devicetree/bindings/sound/tas27xx.yaml | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/tas2562.yaml b/Documentation/devicetree/bindings/sound/tas2562.yaml index 1085592cefccc..81218c07079a8 100644 --- a/Documentation/devicetree/bindings/sound/tas2562.yaml +++ b/Documentation/devicetree/bindings/sound/tas2562.yaml @@ -55,7 +55,9 @@ properties: description: TDM TX current sense time slot.
'#sound-dai-cells': - const: 1 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward + # compatibility but is deprecated. + enum: [0, 1]
required: - compatible @@ -72,7 +74,7 @@ examples: codec: codec@4c { compatible = "ti,tas2562"; reg = <0x4c>; - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; interrupt-parent = <&gpio1>; interrupts = <14>; shutdown-gpios = <&gpio1 15 0>; diff --git a/Documentation/devicetree/bindings/sound/tas2770.yaml b/Documentation/devicetree/bindings/sound/tas2770.yaml index 982949ba8a4be..cdb493db47f9b 100644 --- a/Documentation/devicetree/bindings/sound/tas2770.yaml +++ b/Documentation/devicetree/bindings/sound/tas2770.yaml @@ -57,7 +57,9 @@ properties: - 1 # Falling edge
'#sound-dai-cells': - const: 1 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward + # compatibility but is deprecated. + enum: [0, 1]
required: - compatible @@ -74,7 +76,7 @@ examples: codec: codec@41 { compatible = "ti,tas2770"; reg = <0x41>; - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; interrupt-parent = <&gpio1>; interrupts = <14>; reset-gpio = <&gpio1 15 0>; diff --git a/Documentation/devicetree/bindings/sound/tas27xx.yaml b/Documentation/devicetree/bindings/sound/tas27xx.yaml index 0957dd435bb4b..2ef05aacc167a 100644 --- a/Documentation/devicetree/bindings/sound/tas27xx.yaml +++ b/Documentation/devicetree/bindings/sound/tas27xx.yaml @@ -50,7 +50,9 @@ properties: description: TDM TX voltage sense time slot.
'#sound-dai-cells': - const: 1 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward + # compatibility but is deprecated. + enum: [0, 1]
required: - compatible @@ -67,7 +69,7 @@ examples: codec: codec@38 { compatible = "ti,tas2764"; reg = <0x38>; - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; interrupt-parent = <&gpio1>; interrupts = <14>; reset-gpios = <&gpio1 15 0>;
From: Alexandru Sorodoc ealex95@gmail.com
[ Upstream commit 4b963ae1df6426f0e51de64133d379d9bde50c48 ]
These models use 2 CS35L41 amplifiers using SPI for down-facing speakers.
alc285_fixup_speaker2_to_dac1 is needed to fix volume control of the down-facing speakers.
Pin configs are needed to enable headset mic detection.
Note that these models lack the ACPI _DSD properties needed to initialize the amplifiers. They can be added during boot to get working sound out of the speakers: https://gist.github.com/lamperez/862763881c0e1c812392b5574727f6ff
Signed-off-by: Alexandru Sorodoc ealex95@gmail.com Link: https://lore.kernel.org/r/20230511161510.315170-1-ealex95@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/hda/patch_realtek.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 172ffc2c332b7..543e0adde3faf 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7063,6 +7063,8 @@ enum { ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, ALC295_FIXUP_DISABLE_DAC3, ALC285_FIXUP_SPEAKER2_TO_DAC1, + ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1, + ALC285_FIXUP_ASUS_HEADSET_MIC, ALC280_FIXUP_HP_HEADSET_MIC, ALC221_FIXUP_HP_FRONT_MIC, ALC292_FIXUP_TPT460, @@ -8033,6 +8035,22 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_THINKPAD_ACPI }, + [ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_speaker2_to_dac1, + .chained = true, + .chain_id = ALC245_FIXUP_CS35L41_SPI_2 + }, + [ALC285_FIXUP_ASUS_HEADSET_MIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x03a11050 }, + { 0x1b, 0x03a11c30 }, + { } + }, + .chained = true, + .chain_id = ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1 + }, [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -9500,6 +9518,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), + SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604V", ALC285_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603V", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2),
From: Paweł Anikiel pan@semihalf.com
[ Upstream commit f63550e2b165208a2f382afcaf5551df9569e1d4 ]
Apply a workaround for what appears to be a hardware quirk.
The problem seems to happen when enabling "whole chip power" (bit D7 register R6) for the very first time after the chip receives power. If either "output" (D4) or "DAC" (D3) aren't powered on at that time, playback becomes very distorted later on.
This happens on the Google Chameleon v3, as well as on a ZYBO Z7-10: https://ez.analog.com/audio/f/q-a/543726/solved-ssm2603-right-output-offset-... I suspect this happens only when using an external MCLK signal (which is the case for both of these boards).
Here are some experiments run on a Google Chameleon v3. These were run in userspace using a wrapper around the i2cset utility: ssmset() { i2cset -y 0 0x1a $(($1*2)) $2 }
For each of the following sequences, we apply power to the ssm2603 chip, set the configuration registers R0-R5 and R7-R8, run the selected sequence, and check for distortions on playback.
ssmset 0x09 0x01 # core ssmset 0x06 0x07 # chip, out, dac OK
ssmset 0x09 0x01 # core ssmset 0x06 0x87 # out, dac ssmset 0x06 0x07 # chip OK
(disable MCLK) ssmset 0x09 0x01 # core ssmset 0x06 0x1f # chip ssmset 0x06 0x07 # out, dac (enable MCLK) OK
ssmset 0x09 0x01 # core ssmset 0x06 0x1f # chip ssmset 0x06 0x07 # out, dac NOT OK
ssmset 0x06 0x1f # chip ssmset 0x09 0x01 # core ssmset 0x06 0x07 # out, dac NOT OK
ssmset 0x09 0x01 # core ssmset 0x06 0x0f # chip, out ssmset 0x06 0x07 # dac NOT OK
ssmset 0x09 0x01 # core ssmset 0x06 0x17 # chip, dac ssmset 0x06 0x07 # out NOT OK
For each of the following sequences, we apply power to the ssm2603 chip, run the selected sequence, issue a reset with R15, configure R0-R5 and R7-R8, run one of the NOT OK sequences from above, and check for distortions.
ssmset 0x09 0x01 # core ssmset 0x06 0x07 # chip, out, dac OK
(disable MCLK) ssmset 0x09 0x01 # core ssmset 0x06 0x07 # chip, out, dac (enable MCLK after reset) NOT OK
ssmset 0x09 0x01 # core ssmset 0x06 0x17 # chip, dac NOT OK
ssmset 0x09 0x01 # core ssmset 0x06 0x0f # chip, out NOT OK
ssmset 0x06 0x07 # chip, out, dac NOT OK
Signed-off-by: Paweł Anikiel <pan@semihalf.com Link: https://lore.kernel.org/r/20230508113037.137627-8-pan@semihalf.com Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/ssm2602.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index cbbe83b85adaf..cf7927222be15 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -53,6 +53,18 @@ static const struct reg_default ssm2602_reg[SSM2602_CACHEREGNUM] = { { .reg = 0x09, .def = 0x0000 } };
+/* + * ssm2602 register patch + * Workaround for playback distortions after power up: activates digital + * core, and then powers on output, DAC, and whole chip at the same time + */ + +static const struct reg_sequence ssm2602_patch[] = { + { SSM2602_ACTIVE, 0x01 }, + { SSM2602_PWR, 0x07 }, + { SSM2602_RESET, 0x00 }, +}; +
/*Appending several "None"s just for OSS mixer use*/ static const char *ssm2602_input_select[] = { @@ -589,6 +601,9 @@ static int ssm260x_component_probe(struct snd_soc_component *component) return ret; }
+ regmap_register_patch(ssm2602->regmap, ssm2602_patch, + ARRAY_SIZE(ssm2602_patch)); + /* set the update bits */ regmap_update_bits(ssm2602->regmap, SSM2602_LINVOL, LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
From: YongSu Yoo yongsuyoo0215@gmail.com
[ Upstream commit 7efb10d8dc70ea3000cc70dca53407c52488acd1 ]
In dvb_demux.c, some logics exist which compare the expected continuity counter and the real continuity counter. If they are not matched each other, both of the expected continuity counter and the real continuity counter should be printed. But there exists a bug that the expected continuity counter is not correctly printed. The expected continuity counter is replaced with the real countinuity counter + 1 so that the epected continuity counter is not correclty printed. This is wrong. This bug is fixed.
Link: https://lore.kernel.org/linux-media/20230305212519.499-1-yongsuyoo0215@gmail...
Signed-off-by: YongSu Yoo yongsuyoo0215@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-core/dvb_demux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index 398c86279b5b0..7c4d86bfdd6c9 100644 --- a/drivers/media/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -115,12 +115,12 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
cc = buf[3] & 0x0f; ccok = ((feed->cc + 1) & 0x0f) == cc; - feed->cc = cc; if (!ccok) { set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); dprintk_sect_loss("missed packet: %d instead of %d!\n", cc, (feed->cc + 1) & 0x0f); } + feed->cc = cc;
if (buf[1] & 0x40) // PUSI ? feed->peslen = 0xfffa; @@ -300,7 +300,6 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
cc = buf[3] & 0x0f; ccok = ((feed->cc + 1) & 0x0f) == cc; - feed->cc = cc;
if (buf[3] & 0x20) { /* adaption field present, check for discontinuity_indicator */ @@ -336,6 +335,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, feed->pusi_seen = false; dvb_dmx_swfilter_section_new(feed); } + feed->cc = cc;
if (buf[1] & 0x40) { /* PUSI=1 (is set), section boundary is here */
From: Wei Chen harperchen1110@gmail.com
[ Upstream commit 858e97d7956d17a2cb56a9413468704a4d5abfe1 ]
In az6027_i2c_xfer, msg is controlled by user. When msg[i].buf is null, commit 0ed554fd769a ("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()") fix the null-ptr-deref bug when msg[i].addr is 0x99. However, null-ptr-deref also happens when msg[i].addr is 0xd0 and 0xc0. We add check on msg[i].len to prevent null-ptr-deref.
Link: https://lore.kernel.org/linux-media/20230310165604.3093483-1-harperchen1110@... Signed-off-by: Wei Chen harperchen1110@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/dvb-usb/az6027.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c index 7d78ee09be5e1..a31c6f82f4e90 100644 --- a/drivers/media/usb/dvb-usb/az6027.c +++ b/drivers/media/usb/dvb-usb/az6027.c @@ -988,6 +988,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n /* write/read request */ if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) { req = 0xB9; + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); value = msg[i].addr + (msg[i].len << 8); length = msg[i + 1].len + 6; @@ -1001,6 +1005,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
/* demod 16bit addr */ req = 0xBD; + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); value = msg[i].addr + (2 << 8); length = msg[i].len - 2; @@ -1026,6 +1034,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n } else {
req = 0xBD; + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } index = msg[i].buf[0] & 0x00FF; value = msg[i].addr + (1 << 8); length = msg[i].len - 1;
From: Wei Chen harperchen1110@gmail.com
[ Upstream commit a6dcefcc08eca1bf4e3d213c97c3cfb75f377935 ]
In ec168_i2c_xfer, msg is controlled by user. When msg[i].buf is null and msg[i].len is zero, former checks on msg[i].buf would be passed. If accessing msg[i].buf[0] without sanity check, null pointer deref would happen. We add check on msg[i].len to prevent crash.
Similar commit: commit 0ed554fd769a ("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
Link: https://lore.kernel.org/linux-media/20230313085853.3252349-1-harperchen1110@... Signed-off-by: Wei Chen harperchen1110@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/dvb-usb-v2/ec168.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/media/usb/dvb-usb-v2/ec168.c b/drivers/media/usb/dvb-usb-v2/ec168.c index 7ed0ab9e429b1..0e4773fc025c9 100644 --- a/drivers/media/usb/dvb-usb-v2/ec168.c +++ b/drivers/media/usb/dvb-usb-v2/ec168.c @@ -115,6 +115,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], while (i < num) { if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { if (msg[i].addr == ec168_ec100_config.demod_address) { + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } req.cmd = READ_DEMOD; req.value = 0; req.index = 0xff00 + msg[i].buf[0]; /* reg */ @@ -131,6 +135,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], } } else { if (msg[i].addr == ec168_ec100_config.demod_address) { + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } req.cmd = WRITE_DEMOD; req.value = msg[i].buf[1]; /* val */ req.index = 0xff00 + msg[i].buf[0]; /* reg */ @@ -139,6 +147,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = ec168_ctrl_msg(d, &req); i += 1; } else { + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } req.cmd = WRITE_I2C; req.value = msg[i].buf[0]; /* val */ req.index = 0x0100 + msg[i].addr; /* I2C addr */
From: Wei Chen harperchen1110@gmail.com
[ Upstream commit dff919090155fb22679869e8469168f270dcd97f ]
In ce6230_i2c_master_xfer, msg is controlled by user. When msg[i].buf is null and msg[i].len is zero, former checks on msg[i].buf would be passed. Malicious data finally reach ce6230_i2c_master_xfer. If accessing msg[i].buf[0] without sanity check, null ptr deref would happen. We add check on msg[i].len to prevent crash.
Similar commit: commit 0ed554fd769a ("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
Link: https://lore.kernel.org/linux-media/20230313092751.209496-1-harperchen1110@g... Signed-off-by: Wei Chen harperchen1110@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/dvb-usb-v2/ce6230.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/media/usb/dvb-usb-v2/ce6230.c b/drivers/media/usb/dvb-usb-v2/ce6230.c index 44540de1a2066..d3b5cb4a24daf 100644 --- a/drivers/media/usb/dvb-usb-v2/ce6230.c +++ b/drivers/media/usb/dvb-usb-v2/ce6230.c @@ -101,6 +101,10 @@ static int ce6230_i2c_master_xfer(struct i2c_adapter *adap, if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { if (msg[i].addr == ce6230_zl10353_config.demod_address) { + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } req.cmd = DEMOD_READ; req.value = msg[i].addr >> 1; req.index = msg[i].buf[0]; @@ -117,6 +121,10 @@ static int ce6230_i2c_master_xfer(struct i2c_adapter *adap, } else { if (msg[i].addr == ce6230_zl10353_config.demod_address) { + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } req.cmd = DEMOD_WRITE; req.value = msg[i].addr >> 1; req.index = msg[i].buf[0];
From: Zhang Shurong zhang_shurong@foxmail.com
[ Upstream commit aa4a447b81b84f69c1a89ad899df157f386d7636 ]
In rtl28xxu_i2c_xfer, msg is controlled by user. When msg[i].buf is null and msg[i].len is zero, former checks on msg[i].buf would be passed. Malicious data finally reach rtl28xxu_i2c_xfer. If accessing msg[i].buf[0] without sanity check, null ptr deref would happen. We add check on msg[i].len to prevent crash.
Similar commit: commit 0ed554fd769a ("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
Link: https://lore.kernel.org/linux-media/tencent_3623572106754AC2F266B316798B0F6C... Signed-off-by: Zhang Shurong zhang_shurong@foxmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 795a012d40200..f7884bb56fccf 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -176,6 +176,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = -EOPNOTSUPP; goto err_mutex_unlock; } else if (msg[0].addr == 0x10) { + if (msg[0].len < 1 || msg[1].len < 1) { + ret = -EOPNOTSUPP; + goto err_mutex_unlock; + } /* method 1 - integrated demod */ if (msg[0].buf[0] == 0x00) { /* return demod page from driver cache */ @@ -189,6 +193,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = rtl28xxu_ctrl_msg(d, &req); } } else if (msg[0].len < 2) { + if (msg[0].len < 1) { + ret = -EOPNOTSUPP; + goto err_mutex_unlock; + } /* method 2 - old I2C */ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); req.index = CMD_I2C_RD; @@ -217,8 +225,16 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = -EOPNOTSUPP; goto err_mutex_unlock; } else if (msg[0].addr == 0x10) { + if (msg[0].len < 1) { + ret = -EOPNOTSUPP; + goto err_mutex_unlock; + } /* method 1 - integrated demod */ if (msg[0].buf[0] == 0x00) { + if (msg[0].len < 2) { + ret = -EOPNOTSUPP; + goto err_mutex_unlock; + } /* save demod page for later demod access */ dev->page = msg[0].buf[1]; ret = 0; @@ -231,6 +247,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = rtl28xxu_ctrl_msg(d, &req); } } else if ((msg[0].len < 23) && (!dev->new_i2c_write)) { + if (msg[0].len < 1) { + ret = -EOPNOTSUPP; + goto err_mutex_unlock; + } /* method 2 - old I2C */ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); req.index = CMD_I2C_WR;
From: Wei Chen harperchen1110@gmail.com
[ Upstream commit 9ded5bd2a49ce3015b7c936743eec0a0e6e11f0c ]
In digitv_i2c_xfer, msg is controlled by user. When msg[i].buf is null and msg[i].len is zero, former checks on msg[i].buf would be passed. Malicious data finally reach digitv_i2c_xfer. If accessing msg[i].buf[0] without sanity check, null ptr deref would happen. We add check on msg[i].len to prevent crash.
Similar commit: commit 0ed554fd769a ("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
Link: https://lore.kernel.org/linux-media/20230313095008.1039689-1-harperchen1110@... Signed-off-by: Wei Chen harperchen1110@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/dvb-usb/digitv.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 2756815a780bc..32134be169148 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c @@ -63,6 +63,10 @@ static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num warn("more than 2 i2c messages at a time is not handled yet. TODO.");
for (i = 0; i < num; i++) { + if (msg[i].len < 1) { + i = -EOPNOTSUPP; + break; + } /* write/read request */ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
From: Wei Chen harperchen1110@gmail.com
[ Upstream commit a3fd1ef27aa686d871cefe207bd6168c4b0cd29e ]
In su3000_read_mac_address, if i2c_transfer fails to execute two messages, array mac address will not be initialized. Without handling such error, later in function dvb_usb_adapter_dvb_init, proposed_mac is accessed before initialization.
Fix this error by returning a negative value if message execution fails.
Link: https://lore.kernel.org/linux-media/20230328124416.560889-1-harperchen1110@g... Signed-off-by: Wei Chen harperchen1110@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/dvb-usb/dw2102.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 0ca764282c767..8747960e61461 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -946,7 +946,7 @@ static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) for (i = 0; i < 6; i++) { obuf[1] = 0xf0 + i; if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) - break; + return -1; else mac[i] = ibuf[0]; }
From: Wei Chen harperchen1110@gmail.com
[ Upstream commit e6ad6233592593079db5c8fa592c298e51bc1356 ]
IRQ handler netup_spi_interrupt() takes spinlock spi->lock. The lock is initialized in netup_spi_init(). However, irq handler is registered before initializing the lock.
Spinlock dma->lock and i2c->lock suffer from the same problem.
Fix this by registering the irq at the end of probe.
Link: https://lore.kernel.org/linux-media/20230315134518.1074497-1-harperchen1110@... Signed-off-by: Wei Chen harperchen1110@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../media/pci/netup_unidvb/netup_unidvb_core.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 8287851b5ffdc..751a954baf651 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -887,12 +887,7 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, ndev->lmmio0, (u32)pci_resource_len(pci_dev, 0), ndev->lmmio1, (u32)pci_resource_len(pci_dev, 1), pci_dev->irq); - if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED, - "netup_unidvb", pci_dev) < 0) { - dev_err(&pci_dev->dev, - "%s(): can't get IRQ %d\n", __func__, pci_dev->irq); - goto irq_request_err; - } + ndev->dma_size = 2 * 188 * NETUP_DMA_BLOCKS_COUNT * NETUP_DMA_PACKETS_COUNT; ndev->dma_virt = dma_alloc_coherent(&pci_dev->dev, @@ -933,6 +928,14 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, dev_err(&pci_dev->dev, "netup_unidvb: DMA setup failed\n"); goto dma_setup_err; } + + if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED, + "netup_unidvb", pci_dev) < 0) { + dev_err(&pci_dev->dev, + "%s(): can't get IRQ %d\n", __func__, pci_dev->irq); + goto dma_setup_err; + } + dev_info(&pci_dev->dev, "netup_unidvb: device has been initialized\n"); return 0; @@ -951,8 +954,6 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, dma_free_coherent(&pci_dev->dev, ndev->dma_size, ndev->dma_virt, ndev->dma_phys); dma_alloc_err: - free_irq(pci_dev->irq, pci_dev); -irq_request_err: iounmap(ndev->lmmio1); pci_bar1_error: iounmap(ndev->lmmio0);
From: YongSu Yoo yongsuyoo0215@gmail.com
[ Upstream commit a4315e5be7020aac9b24a8151caf4bb85224cd0e ]
The function of "dvb_ca_en50221_write_data" at source/drivers/media /dvb-core/dvb_ca_en50221.c is used for two cases. The first case is for writing APDU data in the function of "dvb_ca_en50221_io_write" at source/drivers/media/dvb-core/ dvb_ca_en50221.c. The second case is for writing the host link buf size on the Command Register in the function of "dvb_ca_en50221_link_init" at source/drivers/media/dvb-core/dvb_ca_en50221.c. In the second case, there exists a bug like following. In the function of the "dvb_ca_en50221_link_init", after a TV host calculates the host link buf_size, the TV host writes the calculated host link buf_size on the Size Register. Accroding to the en50221 Spec (the page 60 of https://dvb.org/wp-content/uploads/2020/02/En50221.V1.pdf), before this writing operation, the "SW(CMDREG_SW)" flag in the Command Register should be set. We can see this setting operation in the function of the "dvb_ca_en50221_link_init" like below. ... if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) return ret; ... But, after that, the real writing operation is implemented using the function of the "dvb_ca_en50221_write_data" in the function of "dvb_ca_en50221_link_init", and the "dvb_ca_en50221_write_data" includes the function of "ca->pub->write_cam_control", and the function of the "ca->pub->write_cam_control" in the function of the "dvb_ca_en50221_wrte_data" does not include "CMDREG_SW" flag like below. ... if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_HC)) != 0) ... In the above source code, we can see only the "IRQEN | CMDREG_HC", but we cannot see the "CMDREG_SW". The "CMDREG_SW" flag which was set in the function of the "dvb_ca_en50221_link_init" was rollbacked by the follwoing function of the "dvb_ca_en50221_write_data". This is a bug. and this bug causes that the calculated host link buf_size is not properly written in the CI module. Through this patch, we fix this bug.
Link: https://lore.kernel.org/linux-media/20220818125027.1131-1-yongsuyoo0215@gmai... Signed-off-by: YongSu Yoo yongsuyoo0215@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-core/dvb_ca_en50221.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index c2d2792227f86..b6ca29dfb184a 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c @@ -187,7 +187,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca); static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 *ebuf, int ecount); static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, - u8 *ebuf, int ecount); + u8 *ebuf, int ecount, int size_write_flag);
/** * findstr - Safely find needle in haystack. @@ -370,7 +370,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10); if (ret) return ret; - ret = dvb_ca_en50221_write_data(ca, slot, buf, 2); + ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW); if (ret != 2) return -EIO; ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); @@ -778,11 +778,13 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, * @buf: The data in this buffer is treated as a complete link-level packet to * be written. * @bytes_write: Size of ebuf. + * @size_write_flag: A flag on Command Register which says whether the link size + * information will be writen or not. * * return: Number of bytes written, or < 0 on error. */ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, - u8 *buf, int bytes_write) + u8 *buf, int bytes_write, int size_write_flag) { struct dvb_ca_slot *sl = &ca->slot_info[slot]; int status; @@ -817,7 +819,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
/* OK, set HC bit */ status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, - IRQEN | CMDREG_HC); + IRQEN | CMDREG_HC | size_write_flag); if (status) goto exit;
@@ -1508,7 +1510,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
mutex_lock(&sl->slot_lock); status = dvb_ca_en50221_write_data(ca, slot, fragbuf, - fraglen + 2); + fraglen + 2, 0); mutex_unlock(&sl->slot_lock); if (status == (fraglen + 2)) { written = 1;
Hi!
I believe you have typo in the comment:
@@ -778,11 +778,13 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
- @buf: The data in this buffer is treated as a complete link-level packet to
be written.
- @bytes_write: Size of ebuf.
- @size_write_flag: A flag on Command Register which says whether the link size
- information will be writen or not.
writen -> written.
Best regards, Pavel
From: Hyunwoo Kim imv4bel@gmail.com
[ Upstream commit 517a281338322ff8293f988771c98aaa7205e457 ]
Since dvb_frontend_detach() is not called in ttusb_dec_exit_dvb(), which is called when the device is disconnected, dvb_frontend_free() is not finally called.
This causes a memory leak just by repeatedly plugging and unplugging the device.
Fix this issue by adding dvb_frontend_detach() to ttusb_dec_exit_dvb().
Link: https://lore.kernel.org/linux-media/20221117045925.14297-5-imv4bel@gmail.com Signed-off-by: Hyunwoo Kim imv4bel@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/ttusb-dec/ttusb_dec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index 38822cedd93a9..c4474d4c44e28 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -1544,8 +1544,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) dvb_dmx_release(&dec->demux); if (dec->fe) { dvb_unregister_frontend(dec->fe); - if (dec->fe->ops.release) - dec->fe->ops.release(dec->fe); + dvb_frontend_detach(dec->fe); } dvb_unregister_adapter(&dec->adapter); }
From: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org
[ Upstream commit ae11c0efaec32fb45130ee9886689f467232eebc ]
The driver will match mostly by DT table (even thought there is regular ID table) so there is little benefit in of_match_ptr (this also allows ACPI matching via PRP0001, even though it might not be relevant here). This also fixes !CONFIG_OF error:
drivers/media/dvb-frontends/mn88443x.c:782:34: error: ‘mn88443x_of_match’ defined but not used [-Werror=unused-const-variable=]
Link: https://lore.kernel.org/linux-media/20230312131318.351173-28-krzysztof.kozlo... Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-frontends/mn88443x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c index 1f1753f2ab1a3..0782f8377eb2f 100644 --- a/drivers/media/dvb-frontends/mn88443x.c +++ b/drivers/media/dvb-frontends/mn88443x.c @@ -798,7 +798,7 @@ MODULE_DEVICE_TABLE(i2c, mn88443x_i2c_id); static struct i2c_driver mn88443x_driver = { .driver = { .name = "mn88443x", - .of_match_table = of_match_ptr(mn88443x_of_match), + .of_match_table = mn88443x_of_match, }, .probe_new = mn88443x_probe, .remove = mn88443x_remove,
From: Hyunwoo Kim imv4bel@gmail.com
[ Upstream commit 6769a0b7ee0c3b31e1b22c3fadff2bfb642de23f ]
If the device node of dvb_frontend is open() and the device is disconnected, many kinds of UAFs may occur when calling close() on the device node.
The root cause of this is that wake_up() for dvbdev->wait_queue is implemented in the dvb_frontend_release() function, but wait_event() is not implemented in the dvb_frontend_stop() function.
So, implement wait_event() function in dvb_frontend_stop() and add 'remove_mutex' which prevents race condition for 'fe->exit'.
[mchehab: fix a couple of checkpatch warnings and some mistakes at the error handling logic]
Link: https://lore.kernel.org/linux-media/20221117045925.14297-2-imv4bel@gmail.com Signed-off-by: Hyunwoo Kim imv4bel@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-core/dvb_frontend.c | 53 ++++++++++++++++++++++----- include/media/dvb_frontend.h | 6 ++- 2 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index cc0a789f09ae5..947b61959b2b8 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -809,15 +809,26 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
dev_dbg(fe->dvb->device, "%s:\n", __func__);
+ mutex_lock(&fe->remove_mutex); + if (fe->exit != DVB_FE_DEVICE_REMOVED) fe->exit = DVB_FE_NORMAL_EXIT; mb();
- if (!fepriv->thread) + if (!fepriv->thread) { + mutex_unlock(&fe->remove_mutex); return; + }
kthread_stop(fepriv->thread);
+ mutex_unlock(&fe->remove_mutex); + + if (fepriv->dvbdev->users < -1) { + wait_event(fepriv->dvbdev->wait_queue, + fepriv->dvbdev->users == -1); + } + sema_init(&fepriv->sem, 1); fepriv->state = FESTATE_IDLE;
@@ -2761,9 +2772,13 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) struct dvb_adapter *adapter = fe->dvb; int ret;
+ mutex_lock(&fe->remove_mutex); + dev_dbg(fe->dvb->device, "%s:\n", __func__); - if (fe->exit == DVB_FE_DEVICE_REMOVED) - return -ENODEV; + if (fe->exit == DVB_FE_DEVICE_REMOVED) { + ret = -ENODEV; + goto err_remove_mutex; + }
if (adapter->mfe_shared == 2) { mutex_lock(&adapter->mfe_lock); @@ -2771,7 +2786,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) if (adapter->mfe_dvbdev && !adapter->mfe_dvbdev->writers) { mutex_unlock(&adapter->mfe_lock); - return -EBUSY; + ret = -EBUSY; + goto err_remove_mutex; } adapter->mfe_dvbdev = dvbdev; } @@ -2794,8 +2810,10 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) while (mferetry-- && (mfedev->users != -1 || mfepriv->thread)) { if (msleep_interruptible(500)) { - if (signal_pending(current)) - return -EINTR; + if (signal_pending(current)) { + ret = -EINTR; + goto err_remove_mutex; + } } }
@@ -2807,7 +2825,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) if (mfedev->users != -1 || mfepriv->thread) { mutex_unlock(&adapter->mfe_lock); - return -EBUSY; + ret = -EBUSY; + goto err_remove_mutex; } adapter->mfe_dvbdev = dvbdev; } @@ -2866,6 +2885,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
if (adapter->mfe_shared) mutex_unlock(&adapter->mfe_lock); + + mutex_unlock(&fe->remove_mutex); return ret;
err3: @@ -2887,6 +2908,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) err0: if (adapter->mfe_shared) mutex_unlock(&adapter->mfe_lock); + +err_remove_mutex: + mutex_unlock(&fe->remove_mutex); return ret; }
@@ -2897,6 +2921,8 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) struct dvb_frontend_private *fepriv = fe->frontend_priv; int ret;
+ mutex_lock(&fe->remove_mutex); + dev_dbg(fe->dvb->device, "%s:\n", __func__);
if ((file->f_flags & O_ACCMODE) != O_RDONLY) { @@ -2918,10 +2944,18 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) } mutex_unlock(&fe->dvb->mdev_lock); #endif - if (fe->exit != DVB_FE_NO_EXIT) - wake_up(&dvbdev->wait_queue); if (fe->ops.ts_bus_ctrl) fe->ops.ts_bus_ctrl(fe, 0); + + if (fe->exit != DVB_FE_NO_EXIT) { + mutex_unlock(&fe->remove_mutex); + wake_up(&dvbdev->wait_queue); + } else { + mutex_unlock(&fe->remove_mutex); + } + + } else { + mutex_unlock(&fe->remove_mutex); }
dvb_frontend_put(fe); @@ -3022,6 +3056,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb, fepriv = fe->frontend_priv;
kref_init(&fe->refcount); + mutex_init(&fe->remove_mutex);
/* * After initialization, there need to be two references: one diff --git a/include/media/dvb_frontend.h b/include/media/dvb_frontend.h index e7c44870f20de..367d5381217b5 100644 --- a/include/media/dvb_frontend.h +++ b/include/media/dvb_frontend.h @@ -686,7 +686,10 @@ struct dtv_frontend_properties { * @id: Frontend ID * @exit: Used to inform the DVB core that the frontend * thread should exit (usually, means that the hardware - * got disconnected. + * got disconnected). + * @remove_mutex: mutex that avoids a race condition between a callback + * called when the hardware is disconnected and the + * file_operations of dvb_frontend. */
struct dvb_frontend { @@ -704,6 +707,7 @@ struct dvb_frontend { int (*callback)(void *adapter_priv, int component, int cmd, int arg); int id; unsigned int exit; + struct mutex remove_mutex; };
/**
From: Hyunwoo Kim imv4bel@gmail.com
[ Upstream commit 4172385b0c9ac366dcab78eda48c26814b87ed1a ]
A race condition may occur between the .disconnect function, which is called when the device is disconnected, and the dvb_device_open() function, which is called when the device node is open()ed. This results in several types of UAFs.
The root cause of this is that you use the dvb_device_open() function, which does not implement a conditional statement that checks 'dvbnet->exit'.
So, add 'remove_mutex` to protect 'dvbnet->exit' and use locked_dvb_net_open() function to check 'dvbnet->exit'.
[mchehab: fix a checkpatch warning]
Link: https://lore.kernel.org/linux-media/20221117045925.14297-3-imv4bel@gmail.com Signed-off-by: Hyunwoo Kim imv4bel@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-core/dvb_net.c | 38 +++++++++++++++++++++++++++++--- include/media/dvb_net.h | 4 ++++ 2 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index 8a2febf33ce28..8bb8dd34c223e 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -1564,15 +1564,43 @@ static long dvb_net_ioctl(struct file *file, return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl); }
+static int locked_dvb_net_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_net *dvbnet = dvbdev->priv; + int ret; + + if (mutex_lock_interruptible(&dvbnet->remove_mutex)) + return -ERESTARTSYS; + + if (dvbnet->exit) { + mutex_unlock(&dvbnet->remove_mutex); + return -ENODEV; + } + + ret = dvb_generic_open(inode, file); + + mutex_unlock(&dvbnet->remove_mutex); + + return ret; +} + static int dvb_net_close(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct dvb_net *dvbnet = dvbdev->priv;
+ mutex_lock(&dvbnet->remove_mutex); + dvb_generic_release(inode, file);
- if(dvbdev->users == 1 && dvbnet->exit == 1) + if (dvbdev->users == 1 && dvbnet->exit == 1) { + mutex_unlock(&dvbnet->remove_mutex); wake_up(&dvbdev->wait_queue); + } else { + mutex_unlock(&dvbnet->remove_mutex); + } + return 0; }
@@ -1580,7 +1608,7 @@ static int dvb_net_close(struct inode *inode, struct file *file) static const struct file_operations dvb_net_fops = { .owner = THIS_MODULE, .unlocked_ioctl = dvb_net_ioctl, - .open = dvb_generic_open, + .open = locked_dvb_net_open, .release = dvb_net_close, .llseek = noop_llseek, }; @@ -1599,10 +1627,13 @@ void dvb_net_release (struct dvb_net *dvbnet) { int i;
+ mutex_lock(&dvbnet->remove_mutex); dvbnet->exit = 1; + mutex_unlock(&dvbnet->remove_mutex); + if (dvbnet->dvbdev->users < 1) wait_event(dvbnet->dvbdev->wait_queue, - dvbnet->dvbdev->users==1); + dvbnet->dvbdev->users == 1);
dvb_unregister_device(dvbnet->dvbdev);
@@ -1621,6 +1652,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, int i;
mutex_init(&dvbnet->ioctl_mutex); + mutex_init(&dvbnet->remove_mutex); dvbnet->demux = dmx;
for (i=0; i<DVB_NET_DEVICES_MAX; i++) diff --git a/include/media/dvb_net.h b/include/media/dvb_net.h index 5e31d37f25fac..cc01dffcc9f35 100644 --- a/include/media/dvb_net.h +++ b/include/media/dvb_net.h @@ -41,6 +41,9 @@ * @exit: flag to indicate when the device is being removed. * @demux: pointer to &struct dmx_demux. * @ioctl_mutex: protect access to this struct. + * @remove_mutex: mutex that avoids a race condition between a callback + * called when the hardware is disconnected and the + * file_operations of dvb_net. * * Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network * devices. @@ -53,6 +56,7 @@ struct dvb_net { unsigned int exit:1; struct dmx_demux *demux; struct mutex ioctl_mutex; + struct mutex remove_mutex; };
/**
From: Hyunwoo Kim imv4bel@gmail.com
[ Upstream commit 627bb528b086b4136315c25d6a447a98ea9448d3 ]
dvb_register_device() dynamically allocates fops with kmemdup() to set the fops->owner. And these fops are registered in 'file->f_ops' using replace_fops() in the dvb_device_open() process, and kfree()d in dvb_free_device().
However, it is not common to use dynamically allocated fops instead of 'static const' fops as an argument of replace_fops(), and UAF may occur. These UAFs can occur on any dvb type using dvb_register_device(), such as dvb_dvr, dvb_demux, dvb_frontend, dvb_net, etc.
So, instead of kfree() the fops dynamically allocated in dvb_register_device() in dvb_free_device() called during the .disconnect() process, kfree() it collectively in exit_dvbdev() called when the dvbdev.c module is removed.
Link: https://lore.kernel.org/linux-media/20221117045925.14297-4-imv4bel@gmail.com Signed-off-by: Hyunwoo Kim imv4bel@gmail.com Reported-by: kernel test robot lkp@intel.com Reported-by: Dan Carpenter error27@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-core/dvbdev.c | 84 ++++++++++++++++++++++++--------- include/media/dvbdev.h | 15 ++++++ 2 files changed, 78 insertions(+), 21 deletions(-)
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 0ed087caf7f3b..73d296f27ff92 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -27,6 +27,7 @@ #include <media/tuner.h>
static DEFINE_MUTEX(dvbdev_mutex); +static LIST_HEAD(dvbdevfops_list); static int dvbdev_debug;
module_param(dvbdev_debug, int, 0644); @@ -453,14 +454,15 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, enum dvb_device_type type, int demux_sink_pads) { struct dvb_device *dvbdev; - struct file_operations *dvbdevfops; + struct file_operations *dvbdevfops = NULL; + struct dvbdevfops_node *node = NULL, *new_node = NULL; struct device *clsdev; int minor; int id, ret;
mutex_lock(&dvbdev_register_lock);
- if ((id = dvbdev_get_free_id (adap, type)) < 0){ + if ((id = dvbdev_get_free_id (adap, type)) < 0) { mutex_unlock(&dvbdev_register_lock); *pdvbdev = NULL; pr_err("%s: couldn't find free device id\n", __func__); @@ -468,18 +470,45 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, }
*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); - if (!dvbdev){ mutex_unlock(&dvbdev_register_lock); return -ENOMEM; }
- dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); + /* + * When a device of the same type is probe()d more than once, + * the first allocated fops are used. This prevents memory leaks + * that can occur when the same device is probe()d repeatedly. + */ + list_for_each_entry(node, &dvbdevfops_list, list_head) { + if (node->fops->owner == adap->module && + node->type == type && + node->template == template) { + dvbdevfops = node->fops; + break; + } + }
- if (!dvbdevfops){ - kfree (dvbdev); - mutex_unlock(&dvbdev_register_lock); - return -ENOMEM; + if (dvbdevfops == NULL) { + dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); + if (!dvbdevfops) { + kfree(dvbdev); + mutex_unlock(&dvbdev_register_lock); + return -ENOMEM; + } + + new_node = kzalloc(sizeof(struct dvbdevfops_node), GFP_KERNEL); + if (!new_node) { + kfree(dvbdevfops); + kfree(dvbdev); + mutex_unlock(&dvbdev_register_lock); + return -ENOMEM; + } + + new_node->fops = dvbdevfops; + new_node->type = type; + new_node->template = template; + list_add_tail (&new_node->list_head, &dvbdevfops_list); }
memcpy(dvbdev, template, sizeof(struct dvb_device)); @@ -490,20 +519,20 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, dvbdev->priv = priv; dvbdev->fops = dvbdevfops; init_waitqueue_head (&dvbdev->wait_queue); - dvbdevfops->owner = adap->module; - list_add_tail (&dvbdev->list_head, &adap->device_list); - down_write(&minor_rwsem); #ifdef CONFIG_DVB_DYNAMIC_MINORS for (minor = 0; minor < MAX_DVB_MINORS; minor++) if (dvb_minors[minor] == NULL) break; - if (minor == MAX_DVB_MINORS) { + if (new_node) { + list_del (&new_node->list_head); + kfree(dvbdevfops); + kfree(new_node); + } list_del (&dvbdev->list_head); - kfree(dvbdevfops); kfree(dvbdev); up_write(&minor_rwsem); mutex_unlock(&dvbdev_register_lock); @@ -512,41 +541,47 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, #else minor = nums2minor(adap->num, type, id); #endif - dvbdev->minor = minor; dvb_minors[minor] = dvb_device_get(dvbdev); up_write(&minor_rwsem); - ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); if (ret) { pr_err("%s: dvb_register_media_device failed to create the mediagraph\n", __func__); - + if (new_node) { + list_del (&new_node->list_head); + kfree(dvbdevfops); + kfree(new_node); + } dvb_media_device_free(dvbdev); list_del (&dvbdev->list_head); - kfree(dvbdevfops); kfree(dvbdev); mutex_unlock(&dvbdev_register_lock); return ret; }
- mutex_unlock(&dvbdev_register_lock); - clsdev = device_create(dvb_class, adap->device, MKDEV(DVB_MAJOR, minor), dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); if (IS_ERR(clsdev)) { pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); + if (new_node) { + list_del (&new_node->list_head); + kfree(dvbdevfops); + kfree(new_node); + } dvb_media_device_free(dvbdev); list_del (&dvbdev->list_head); - kfree(dvbdevfops); kfree(dvbdev); + mutex_unlock(&dvbdev_register_lock); return PTR_ERR(clsdev); } + dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", adap->num, dnames[type], id, minor, minor);
+ mutex_unlock(&dvbdev_register_lock); return 0; } EXPORT_SYMBOL(dvb_register_device); @@ -575,7 +610,6 @@ static void dvb_free_device(struct kref *ref) { struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
- kfree (dvbdev->fops); kfree (dvbdev); }
@@ -1081,9 +1115,17 @@ static int __init init_dvbdev(void)
static void __exit exit_dvbdev(void) { + struct dvbdevfops_node *node, *next; + class_destroy(dvb_class); cdev_del(&dvb_device_cdev); unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); + + list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) { + list_del (&node->list_head); + kfree(node->fops); + kfree(node); + } }
subsys_initcall(init_dvbdev); diff --git a/include/media/dvbdev.h b/include/media/dvbdev.h index 29d25c8a6f13f..8958e5e2fc5b7 100644 --- a/include/media/dvbdev.h +++ b/include/media/dvbdev.h @@ -193,6 +193,21 @@ struct dvb_device { void *priv; };
+/** + * struct dvbdevfops_node - fops nodes registered in dvbdevfops_list + * + * @fops: Dynamically allocated fops for ->owner registration + * @type: type of dvb_device + * @template: dvb_device used for registration + * @list_head: list_head for dvbdevfops_list + */ +struct dvbdevfops_node { + struct file_operations *fops; + enum dvb_device_type type; + const struct dvb_device *template; + struct list_head list_head; +}; + /** * dvb_device_get - Increase dvb_device reference *
From: Takashi Iwai tiwai@suse.de
[ Upstream commit b8c75e4a1b325ea0a9433fa8834be97b5836b946 ]
Using a semaphore in the wait_event*() condition is no good idea. It hits a kernel WARN_ON() at prepare_to_wait_event() like: do not call blocking ops when !TASK_RUNNING; state=1 set at prepare_to_wait_event+0x6d/0x690
For avoiding the potential deadlock, rewrite to an open-coded loop instead. Unlike the loop in wait_event*(), this uses wait_woken() after the condition check, hence the task state stays consistent.
CVE-2023-31084 was assigned to this bug.
Link: https://lore.kernel.org/r/CA+UBctCu7fXn4q41O_3=id1+OdyQ85tZY1x+TkT-6OVBL6KAU...
Link: https://lore.kernel.org/linux-media/20230512151800.1874-1-tiwai@suse.de Reported-by: Yu Hao yhao016@ucr.edu Closes: https://nvd.nist.gov/vuln/detail/CVE-2023-31084 Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-core/dvb_frontend.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 947b61959b2b8..bc6950a5740f6 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -293,14 +293,22 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, }
if (events->eventw == events->eventr) { - int ret; + struct wait_queue_entry wait; + int ret = 0;
if (flags & O_NONBLOCK) return -EWOULDBLOCK;
- ret = wait_event_interruptible(events->wait_queue, - dvb_frontend_test_event(fepriv, events)); - + init_waitqueue_entry(&wait, current); + add_wait_queue(&events->wait_queue, &wait); + while (!dvb_frontend_test_event(fepriv, events)) { + wait_woken(&wait, TASK_INTERRUPTIBLE, 0); + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + } + remove_wait_queue(&events->wait_queue, &wait); if (ret < 0) return ret; }
From: Hyunwoo Kim v4bel@theori.io
[ Upstream commit 280a8ab81733da8bc442253c700a52c4c0886ffd ]
If the device node of dvb_ca_en50221 is open() and the device is disconnected, a UAF may occur when calling close() on the device node.
The root cause is that wake_up() and wait_event() for dvbdev->wait_queue are not implemented.
So implement wait_event() function in dvb_ca_en50221_release() and add 'remove_mutex' which prevents race condition for 'ca->exit'.
[mchehab: fix a checkpatch warning]
Link: https://lore.kernel.org/linux-media/20221121063308.GA33821@ubuntu Signed-off-by: Hyunwoo Kim v4bel@theori.io Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-core/dvb_ca_en50221.c | 37 ++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index b6ca29dfb184a..baf64540dc00a 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c @@ -151,6 +151,12 @@ struct dvb_ca_private {
/* mutex serializing ioctls */ struct mutex ioctl_mutex; + + /* A mutex used when a device is disconnected */ + struct mutex remove_mutex; + + /* Whether the device is disconnected */ + int exit; };
static void dvb_ca_private_free(struct dvb_ca_private *ca) @@ -1711,12 +1717,22 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
dprintk("%s\n", __func__);
- if (!try_module_get(ca->pub->owner)) + mutex_lock(&ca->remove_mutex); + + if (ca->exit) { + mutex_unlock(&ca->remove_mutex); + return -ENODEV; + } + + if (!try_module_get(ca->pub->owner)) { + mutex_unlock(&ca->remove_mutex); return -EIO; + }
err = dvb_generic_open(inode, file); if (err < 0) { module_put(ca->pub->owner); + mutex_unlock(&ca->remove_mutex); return err; }
@@ -1741,6 +1757,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
dvb_ca_private_get(ca);
+ mutex_unlock(&ca->remove_mutex); return 0; }
@@ -1760,6 +1777,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
dprintk("%s\n", __func__);
+ mutex_lock(&ca->remove_mutex); + /* mark the CA device as closed */ ca->open = 0; dvb_ca_en50221_thread_update_delay(ca); @@ -1770,6 +1789,13 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
dvb_ca_private_put(ca);
+ if (dvbdev->users == 1 && ca->exit == 1) { + mutex_unlock(&ca->remove_mutex); + wake_up(&dvbdev->wait_queue); + } else { + mutex_unlock(&ca->remove_mutex); + } + return err; }
@@ -1893,6 +1919,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, }
mutex_init(&ca->ioctl_mutex); + mutex_init(&ca->remove_mutex);
if (signal_pending(current)) { ret = -EINTR; @@ -1935,6 +1962,14 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
dprintk("%s\n", __func__);
+ mutex_lock(&ca->remove_mutex); + ca->exit = 1; + mutex_unlock(&ca->remove_mutex); + + if (ca->dvbdev->users < 1) + wait_event(ca->dvbdev->wait_queue, + ca->dvbdev->users == 1); + /* shutdown the thread if there was one */ kthread_stop(ca->thread);
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 3de975862f985f1c9e225a0d13aa3d501373f7c3 ]
When a firmware IPC error happens during a pm_runtime suspend, we ignore the error and suspend anyways. However, the code unconditionally increases the runtime_pm counter. This results in a confusing configuration where the code will suspend, resume but never suspend again due to the use of pm_runtime_get_noresume().
The intent of the counter increase was to prevent entry in D3, but if that transition to D3 is already started it cannot be stopped. In addition, there's no point in that case in trying to prevent anything, the firmware error is handled and the next resume will re-initialize the firmware completely.
This patch changes the logic to prevent suspend when the device is pm_runtime active and has a use_count > 0.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com Link: https://lore.kernel.org/r/20230512103315.8921-2-peter.ujfalusi@linux.intel.c... Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index ade0507328af4..5042312b1b98d 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -437,8 +437,8 @@ void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev, const char *msg) /* should we prevent DSP entering D3 ? */ if (!sdev->ipc_dump_printed) dev_info(sdev->dev, - "preventing DSP entering D3 state to preserve context\n"); - pm_runtime_get_noresume(sdev->dev); + "Attempting to prevent DSP from entering D3 state to preserve context\n"); + pm_runtime_get_if_in_use(sdev->dev); }
/* dump vital information to the logs */
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit da0fe8fd515a471d373acc3682bfb5522cca4d55 ]
When an error occurs, we need to make sure the device can pm_runtime suspend instead of keeping it active.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com Link: https://lore.kernel.org/r/20230512103315.8921-3-peter.ujfalusi@linux.intel.c... Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/pcm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 445acb5c3a21b..2570f33db9f3e 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -616,16 +616,17 @@ static int sof_pcm_probe(struct snd_soc_component *component) "%s/%s", plat_data->tplg_filename_prefix, plat_data->tplg_filename); - if (!tplg_filename) - return -ENOMEM; + if (!tplg_filename) { + ret = -ENOMEM; + goto pm_error; + }
ret = snd_sof_load_topology(component, tplg_filename); - if (ret < 0) { + if (ret < 0) dev_err(component->dev, "error: failed to load DSP topology %d\n", ret); - return ret; - }
+pm_error: pm_runtime_mark_last_busy(component->dev); pm_runtime_put_autosuspend(component->dev);
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit bc424273c74c1565c459c8f2a6ed95caee368d0a ]
When an error occurs, we need to make sure the device can pm_runtime suspend instead of keeping it active.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com Link: https://lore.kernel.org/r/20230512103315.8921-4-peter.ujfalusi@linux.intel.c... Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/sof-client-probes.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index fff126808bc04..8d9e9d5f40e45 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -218,12 +218,7 @@ static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to,
ret = ipc->points_info(cdev, &desc, &num_desc); if (ret < 0) - goto exit; - - pm_runtime_mark_last_busy(dev); - err = pm_runtime_put_autosuspend(dev); - if (err < 0) - dev_err_ratelimited(dev, "debugfs read failed to idle %d\n", err); + goto pm_error;
for (i = 0; i < num_desc; i++) { offset = strlen(buf); @@ -241,6 +236,13 @@ static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to, ret = simple_read_from_buffer(to, count, ppos, buf, strlen(buf));
kfree(desc); + +pm_error: + pm_runtime_mark_last_busy(dev); + err = pm_runtime_put_autosuspend(dev); + if (err < 0) + dev_err_ratelimited(dev, "debugfs read failed to idle %d\n", err); + exit: kfree(buf); return ret;
From: Kai Vehmanen kai.vehmanen@linux.intel.com
[ Upstream commit 171b53be635ac15d4feafeb33946035649b1ca14 ]
If there are failures in DSP runtime resume, the device state will not reach active and this makes it impossible e.g. to retrieve a possible DSP panic dump via "exception" debugfs node. If CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE=y is set, the data in cache is stale. If debugfs cache is not used, the region simply cannot be read.
To allow debugging these scenarios, update the debugfs cache contents in resume error handler. User-space can then later retrieve DSP panic and other state via debugfs (requires SOF debugfs cache to be enabled in build).
Reported-by: Curtis Malainey <cujomalainey@chromium.org Link: https://github.com/thesofproject/linux/issues/4274 Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com Reviewed-by: Curtis Malainey <cujomalainey@chromium.org Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com Link: https://lore.kernel.org/r/20230512104638.21376-1-peter.ujfalusi@linux.intel.... Signed-off-by: Mark Brown <broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/pm.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 85412aeb1ca16..40f392efd8246 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -159,7 +159,7 @@ static int sof_resume(struct device *dev, bool runtime_resume) ret = tplg_ops->set_up_all_pipelines(sdev, false); if (ret < 0) { dev_err(sdev->dev, "Failed to restore pipeline after resume %d\n", ret); - return ret; + goto setup_fail; } }
@@ -173,6 +173,18 @@ static int sof_resume(struct device *dev, bool runtime_resume) dev_err(sdev->dev, "ctx_restore IPC error during resume: %d\n", ret); }
+setup_fail: +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) + if (ret < 0) { + /* + * Debugfs cannot be read in runtime suspend, so cache + * the contents upon failure. This allows to capture + * possible DSP coredump information. + */ + sof_cache_debugfs(sdev); + } +#endif + return ret; }
From: Xin Long lucien.xin@gmail.com
[ Upstream commit 3ae6d66b605be604644d4bb5708a7ffd9cf1abe8 ]
As different media may requires different min mtu, and even the same media with different net family requires different min mtu, add tipc_bearer_min_mtu() to calculate min mtu accordingly.
This API will be used to check the new mtu when doing the link mtu negotiation in the next patch.
Signed-off-by: Xin Long lucien.xin@gmail.com Acked-by: Jon Maloy jmaloy@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/tipc/bearer.c | 13 +++++++++++++ net/tipc/bearer.h | 3 +++ net/tipc/udp_media.c | 5 +++-- 3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 35cac7733fd3a..0e9a29e1536b7 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -541,6 +541,19 @@ int tipc_bearer_mtu(struct net *net, u32 bearer_id) return mtu; }
+int tipc_bearer_min_mtu(struct net *net, u32 bearer_id) +{ + int mtu = TIPC_MIN_BEARER_MTU; + struct tipc_bearer *b; + + rcu_read_lock(); + b = bearer_get(net, bearer_id); + if (b) + mtu += b->encap_hlen; + rcu_read_unlock(); + return mtu; +} + /* tipc_bearer_xmit_skb - sends buffer to destination over bearer */ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 490ad6e5f7a3c..bd0cc5c287ef8 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -146,6 +146,7 @@ struct tipc_media { * @identity: array index of this bearer within TIPC bearer array * @disc: ptr to link setup request * @net_plane: network plane ('A' through 'H') currently associated with bearer + * @encap_hlen: encap headers length * @up: bearer up flag (bit 0) * @refcnt: tipc_bearer reference counter * @@ -170,6 +171,7 @@ struct tipc_bearer { u32 identity; struct tipc_discoverer *disc; char net_plane; + u16 encap_hlen; unsigned long up; refcount_t refcnt; }; @@ -232,6 +234,7 @@ int tipc_bearer_setup(void); void tipc_bearer_cleanup(void); void tipc_bearer_stop(struct net *net); int tipc_bearer_mtu(struct net *net, u32 bearer_id); +int tipc_bearer_min_mtu(struct net *net, u32 bearer_id); bool tipc_bearer_bcast_support(struct net *net, u32 bearer_id); void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id, struct sk_buff *skb, diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index c2bb818704c8f..0a85244fd6188 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c @@ -738,8 +738,8 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, udp_conf.local_ip.s_addr = local.ipv4.s_addr; udp_conf.use_udp_checksums = false; ub->ifindex = dev->ifindex; - if (tipc_mtu_bad(dev, sizeof(struct iphdr) + - sizeof(struct udphdr))) { + b->encap_hlen = sizeof(struct iphdr) + sizeof(struct udphdr); + if (tipc_mtu_bad(dev, b->encap_hlen)) { err = -EINVAL; goto err; } @@ -760,6 +760,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, else udp_conf.local_ip6 = local.ipv6; ub->ifindex = dev->ifindex; + b->encap_hlen = sizeof(struct ipv6hdr) + sizeof(struct udphdr); b->mtu = 1280; #endif } else {
From: Holger Dengler dengler@linux.ibm.com
[ Upstream commit 844cf829e5f33e00b279230470c8c93b58b8c16f ]
Key blobs for the IOCTLs PKEY_KBLOB2PROTK[23] may contain clear key material. Zeroize the copies of these keys in kernel memory after creating the protected key.
Reviewed-by: Harald Freudenberger freude@linux.ibm.com Signed-off-by: Holger Dengler dengler@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/s390/crypto/pkey_api.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 5a05d1cdfec20..a8def50c149bd 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -1293,6 +1293,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, return PTR_ERR(kkey); rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) break; @@ -1426,6 +1427,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kkey, ktp.keylen, &ktp.protkey); DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); kfree(apqns); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) break; @@ -1552,6 +1554,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, protkey, &protkeylen); DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); kfree(apqns); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) { kfree(protkey);
From: Alexander Gordeev agordeev@linux.ibm.com
[ Upstream commit a33239be2d38ff5a44427db1707c08787508d34a ]
When SMT thread CPUs are added to CPU masks the nr_cpu_ids limit is not checked and could be exceeded. This leads to a warning for example if CONFIG_DEBUG_PER_CPU_MAPS is set and the command line parameter nr_cpus is set to 1.
Reviewed-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/kernel/topology.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index c6eecd4a5302d..10b20aeb27d3b 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -95,7 +95,7 @@ static void cpu_group_map(cpumask_t *dst, struct mask_info *info, unsigned int c static void cpu_thread_map(cpumask_t *dst, unsigned int cpu) { static cpumask_t mask; - int i; + unsigned int max_cpu;
cpumask_clear(&mask); if (!cpumask_test_cpu(cpu, &cpu_setup_mask)) @@ -104,9 +104,10 @@ static void cpu_thread_map(cpumask_t *dst, unsigned int cpu) if (topology_mode != TOPOLOGY_MODE_HW) goto out; cpu -= cpu % (smp_cpu_mtid + 1); - for (i = 0; i <= smp_cpu_mtid; i++) { - if (cpumask_test_cpu(cpu + i, &cpu_setup_mask)) - cpumask_set_cpu(cpu + i, &mask); + max_cpu = min(cpu + smp_cpu_mtid, nr_cpu_ids - 1); + for (; cpu <= max_cpu; cpu++) { + if (cpumask_test_cpu(cpu, &cpu_setup_mask)) + cpumask_set_cpu(cpu, &mask); } out: cpumask_copy(dst, &mask); @@ -123,25 +124,26 @@ static void add_cpus_to_mask(struct topology_core *tl_core, unsigned int core;
for_each_set_bit(core, &tl_core->mask, TOPOLOGY_CORE_BITS) { - unsigned int rcore; - int lcpu, i; + unsigned int max_cpu, rcore; + int cpu;
rcore = TOPOLOGY_CORE_BITS - 1 - core + tl_core->origin; - lcpu = smp_find_processor_id(rcore << smp_cpu_mt_shift); - if (lcpu < 0) + cpu = smp_find_processor_id(rcore << smp_cpu_mt_shift); + if (cpu < 0) continue; - for (i = 0; i <= smp_cpu_mtid; i++) { - topo = &cpu_topology[lcpu + i]; + max_cpu = min(cpu + smp_cpu_mtid, nr_cpu_ids - 1); + for (; cpu <= max_cpu; cpu++) { + topo = &cpu_topology[cpu]; topo->drawer_id = drawer->id; topo->book_id = book->id; topo->socket_id = socket->id; topo->core_id = rcore; - topo->thread_id = lcpu + i; + topo->thread_id = cpu; topo->dedicated = tl_core->d; - cpumask_set_cpu(lcpu + i, &drawer->mask); - cpumask_set_cpu(lcpu + i, &book->mask); - cpumask_set_cpu(lcpu + i, &socket->mask); - smp_cpu_set_polarization(lcpu + i, tl_core->pp); + cpumask_set_cpu(cpu, &drawer->mask); + cpumask_set_cpu(cpu, &book->mask); + cpumask_set_cpu(cpu, &socket->mask); + smp_cpu_set_polarization(cpu, tl_core->pp); } } }
From: Alexander Gordeev agordeev@linux.ibm.com
[ Upstream commit 2facd5d3980f3a26c04fe6ec8689a1d019a5812c ]
The pointer to IPL Parameter Information Block is stored in the absolute lowcore for later use by dump tools. That pointer is a virtual address, though it should be physical instead.
Note, this does not fix a real issue, since virtual and physical addresses are currently the same.
Suggested-by: Heiko Carstens hca@linux.ibm.com Reviewed-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/kernel/ipl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 5f0f5c86963a9..e43ee9becbbb9 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1936,14 +1936,13 @@ static struct shutdown_action __refdata dump_action = {
static void dump_reipl_run(struct shutdown_trigger *trigger) { - unsigned long ipib = (unsigned long) reipl_block_actual; struct lowcore *abs_lc; unsigned int csum;
csum = (__force unsigned int) csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); abs_lc = get_abs_lowcore(); - abs_lc->ipib = ipib; + abs_lc->ipib = __pa(reipl_block_actual); abs_lc->ipib_checksum = csum; put_abs_lowcore(abs_lc); dump_run(trigger);
From: Rubén Gómez mrgommer@proton.me
[ Upstream commit 71a485624c4cbb144169852d7bb8ca8c0667d7a3 ]
Add an ACPI IRQ override quirk for LG UltraPC 17U70P to address the internal keyboard problem on it.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=213031 Link: https://bugzilla.kernel.org/show_bug.cgi?id=216983 Signed-off-by: Rubén Gómez Agudo mrgommer@proton.me [ rjw: Subject, changelog, white space damage fixes ] Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/acpi/resource.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index e8492b3a393ab..0800a9d775580 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -516,6 +516,17 @@ static const struct dmi_system_id maingear_laptop[] = { { } };
+static const struct dmi_system_id lg_laptop[] = { + { + .ident = "LG Electronics 17U70P", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_BOARD_NAME, "17U70P"), + }, + }, + { } +}; + struct irq_override_cmp { const struct dmi_system_id *system; unsigned char irq; @@ -532,6 +543,7 @@ static const struct irq_override_cmp override_table[] = { { lenovo_laptop, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true }, { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, + { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, };
static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
From: Yun Lu luyun@kylinos.cn
[ Upstream commit 20429444e653ee8242dfbf815c0c37866beb371b ]
When using rtl8192cu with rtl8xxxu driver to connect wifi, there is a probability of failure, which shows "authentication with ... timed out". Through debugging, it was found that the RCR register has been inexplicably modified to an incorrect value, resulting in the nic not being able to receive authenticated frames.
To fix this problem, add regrcr in rtl8xxxu_priv struct, and store the RCR value every time the register is written, and use it the next time the register need to be modified.
Signed-off-by: Yun Lu luyun@kylinos.cn Link: https://lore.kernel.org/all/20230427020512.1221062-1-luyun_611@163.com Signed-off-by: Kalle Valo kvalo@kernel.org Link: https://lore.kernel.org/r/20230512012055.2990472-1-luyun_611@163.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 1 + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index c8cee4a247551..4088aaa1c618d 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1518,6 +1518,7 @@ struct rtl8xxxu_priv { u32 rege9c; u32 regeb4; u32 regebc; + u32 regrcr; int next_mbox; int nr_out_eps;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 54ca6f2ced3f3..74ff5130971e2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -4049,6 +4049,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL | RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC; rtl8xxxu_write32(priv, REG_RCR, val32); + priv->regrcr = val32;
if (priv->rtl_chip == RTL8188F) { /* Accept all data frames */ @@ -6269,7 +6270,7 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast) { struct rtl8xxxu_priv *priv = hw->priv; - u32 rcr = rtl8xxxu_read32(priv, REG_RCR); + u32 rcr = priv->regrcr;
dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n", __func__, changed_flags, *total_flags); @@ -6315,6 +6316,7 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw, */
rtl8xxxu_write32(priv, REG_RCR, rcr); + priv->regrcr = rcr;
*total_flags &= (FIF_ALLMULTI | FIF_FCSFAIL | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL | FIF_OTHER_BSS | FIF_PSPOLL |
From: Dario Binacchi dario.binacchi@amarulasolutions.com
[ Upstream commit 011644249686f2675e142519cd59e81e04cfc231 ]
Add pin configurations for using CAN controller on stm32f7.
Signed-off-by: Dario Binacchi dario.binacchi@amarulasolutions.com Link: https://lore.kernel.org/all/20230427204540.3126234-4-dario.binacchi@amarulas... Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/stm32f7-pinctrl.dtsi | 82 ++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f7-pinctrl.dtsi b/arch/arm/boot/dts/stm32f7-pinctrl.dtsi index c8e6c52fb248e..9f65403295ca0 100644 --- a/arch/arm/boot/dts/stm32f7-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32f7-pinctrl.dtsi @@ -283,6 +283,88 @@ pins2 { slew-rate = <2>; }; }; + + can1_pins_a: can1-0 { + pins1 { + pinmux = <STM32_PINMUX('A', 12, AF9)>; /* CAN1_TX */ + }; + pins2 { + pinmux = <STM32_PINMUX('A', 11, AF9)>; /* CAN1_RX */ + bias-pull-up; + }; + }; + + can1_pins_b: can1-1 { + pins1 { + pinmux = <STM32_PINMUX('B', 9, AF9)>; /* CAN1_TX */ + }; + pins2 { + pinmux = <STM32_PINMUX('B', 8, AF9)>; /* CAN1_RX */ + bias-pull-up; + }; + }; + + can1_pins_c: can1-2 { + pins1 { + pinmux = <STM32_PINMUX('D', 1, AF9)>; /* CAN1_TX */ + }; + pins2 { + pinmux = <STM32_PINMUX('D', 0, AF9)>; /* CAN1_RX */ + bias-pull-up; + + }; + }; + + can1_pins_d: can1-3 { + pins1 { + pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */ + }; + pins2 { + pinmux = <STM32_PINMUX('H', 14, AF9)>; /* CAN1_RX */ + bias-pull-up; + + }; + }; + + can2_pins_a: can2-0 { + pins1 { + pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN2_TX */ + }; + pins2 { + pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN2_RX */ + bias-pull-up; + }; + }; + + can2_pins_b: can2-1 { + pins1 { + pinmux = <STM32_PINMUX('B', 13, AF9)>; /* CAN2_TX */ + }; + pins2 { + pinmux = <STM32_PINMUX('B', 12, AF9)>; /* CAN2_RX */ + bias-pull-up; + }; + }; + + can3_pins_a: can3-0 { + pins1 { + pinmux = <STM32_PINMUX('A', 15, AF11)>; /* CAN3_TX */ + }; + pins2 { + pinmux = <STM32_PINMUX('A', 8, AF11)>; /* CAN3_RX */ + bias-pull-up; + }; + }; + + can3_pins_b: can3-1 { + pins1 { + pinmux = <STM32_PINMUX('B', 4, AF11)>; /* CAN3_TX */ + }; + pins2 { + pinmux = <STM32_PINMUX('B', 3, AF11)>; /* CAN3_RX */ + bias-pull-up; + }; + }; }; }; };
From: Dario Binacchi dario.binacchi@amarulasolutions.com
[ Upstream commit 0920ccdf41e3078a4dd2567eb905ea154bc826e6 ]
Add support for bxcan (Basic eXtended CAN controller) to STM32F746. The chip contains three CAN peripherals, CAN1 and CAN2 in dual peripheral configuration and CAN3 in single peripheral configuration: - Dual CAN peripheral configuration: * CAN1: Primary bxCAN for managing the communication between a secondary bxCAN and the 512-byte SRAM memory. * CAN2: Secondary bxCAN with no direct access to the SRAM memory. This means that the two bxCAN cells share the 512-byte SRAM memory and CAN2 can't be used without enabling CAN1. - Single CAN peripheral configuration: * CAN3: Primary bxCAN with dedicated Memory Access Controller unit and 512-byte SRAM memory.
------------------------------------------------------------------------- | features | CAN1 | CAN2 | CAN 3 | ------------------------------------------------------------------------- | SRAM | 512-byte shared between CAN1 & CAN2 | 512-byte | ------------------------------------------------------------------------- | Filters | 26 filters shared between CAN1 & CAN2 | 14 filters | -------------------------------------------------------------------------
Signed-off-by: Dario Binacchi dario.binacchi@amarulasolutions.com Link: https://lore.kernel.org/all/20230427204540.3126234-6-dario.binacchi@amarulas... Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/stm32f746.dtsi | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi index dc868e6da40e0..973698bc9ef4b 100644 --- a/arch/arm/boot/dts/stm32f746.dtsi +++ b/arch/arm/boot/dts/stm32f746.dtsi @@ -257,6 +257,23 @@ rtc: rtc@40002800 { status = "disabled"; };
+ can3: can@40003400 { + compatible = "st,stm32f4-bxcan"; + reg = <0x40003400 0x200>; + interrupts = <104>, <105>, <106>, <107>; + interrupt-names = "tx", "rx0", "rx1", "sce"; + resets = <&rcc STM32F7_APB1_RESET(CAN3)>; + clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN3)>; + st,gcan = <&gcan3>; + status = "disabled"; + }; + + gcan3: gcan@40003600 { + compatible = "st,stm32f4-gcan", "syscon"; + reg = <0x40003600 0x200>; + clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN3)>; + }; + usart2: serial@40004400 { compatible = "st,stm32f7-uart"; reg = <0x40004400 0x400>; @@ -337,6 +354,36 @@ i2c4: i2c@40006000 { status = "disabled"; };
+ can1: can@40006400 { + compatible = "st,stm32f4-bxcan"; + reg = <0x40006400 0x200>; + interrupts = <19>, <20>, <21>, <22>; + interrupt-names = "tx", "rx0", "rx1", "sce"; + resets = <&rcc STM32F7_APB1_RESET(CAN1)>; + clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN1)>; + st,can-primary; + st,gcan = <&gcan1>; + status = "disabled"; + }; + + gcan1: gcan@40006600 { + compatible = "st,stm32f4-gcan", "syscon"; + reg = <0x40006600 0x200>; + clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN1)>; + }; + + can2: can@40006800 { + compatible = "st,stm32f4-bxcan"; + reg = <0x40006800 0x200>; + interrupts = <63>, <64>, <65>, <66>; + interrupt-names = "tx", "rx0", "rx1", "sce"; + resets = <&rcc STM32F7_APB1_RESET(CAN2)>; + clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN2)>; + st,can-secondary; + st,gcan = <&gcan1>; + status = "disabled"; + }; + cec: cec@40006c00 { compatible = "st,stm32-cec"; reg = <0x40006C00 0x400>;
From: Min-Hua Chen minhuadotchen@gmail.com
[ Upstream commit d91d580878064b880f3574ac35b98d8b70ee8620 ]
This patch fixes several sparse warnings for fault.c:
arch/arm64/mm/fault.c:493:24: sparse: warning: incorrect type in return expression (different base types) arch/arm64/mm/fault.c:493:24: sparse: expected restricted vm_fault_t arch/arm64/mm/fault.c:493:24: sparse: got int arch/arm64/mm/fault.c:501:32: sparse: warning: incorrect type in return expression (different base types) arch/arm64/mm/fault.c:501:32: sparse: expected restricted vm_fault_t arch/arm64/mm/fault.c:501:32: sparse: got int arch/arm64/mm/fault.c:503:32: sparse: warning: incorrect type in return expression (different base types) arch/arm64/mm/fault.c:503:32: sparse: expected restricted vm_fault_t arch/arm64/mm/fault.c:503:32: sparse: got int arch/arm64/mm/fault.c:511:24: sparse: warning: incorrect type in return expression (different base types) arch/arm64/mm/fault.c:511:24: sparse: expected restricted vm_fault_t arch/arm64/mm/fault.c:511:24: sparse: got int arch/arm64/mm/fault.c:670:13: sparse: warning: restricted vm_fault_t degrades to integer arch/arm64/mm/fault.c:670:13: sparse: warning: restricted vm_fault_t degrades to integer arch/arm64/mm/fault.c:713:39: sparse: warning: restricted vm_fault_t degrades to integer
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Min-Hua Chen minhuadotchen@gmail.com Link: https://lore.kernel.org/r/20230502151909.128810-1-minhuadotchen@gmail.com Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/mm/fault.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index f4cb0f85ccf49..d1136259b7b85 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -480,8 +480,8 @@ static void do_bad_area(unsigned long far, unsigned long esr, } }
-#define VM_FAULT_BADMAP 0x010000 -#define VM_FAULT_BADACCESS 0x020000 +#define VM_FAULT_BADMAP ((__force vm_fault_t)0x010000) +#define VM_FAULT_BADACCESS ((__force vm_fault_t)0x020000)
static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int mm_flags, unsigned long vm_flags,
From: Linus Walleij linus.walleij@linaro.org
[ Upstream commit b0abde80620f42d1ceb3de5e4c1a49cdd5628229 ]
Like the other calls in this function virt_to_page() expects a pointer, not an integer.
However since many architectures implement virt_to_pfn() as a macro, this function becomes polymorphic and accepts both a (unsigned long) and a (void *).
Fix this up with an explicit cast.
Signed-off-by: Linus Walleij linus.walleij@linaro.org Link: http://lists.infradead.org/pipermail/linux-arm-kernel/2023-May/832583.html Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/kernel/vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 0119dc91abb5d..d9e1355730ef5 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -288,7 +288,7 @@ static int aarch32_alloc_kuser_vdso_page(void)
memcpy((void *)(vdso_page + 0x1000 - kuser_sz), __kuser_helper_start, kuser_sz); - aarch32_vectors_page = virt_to_page(vdso_page); + aarch32_vectors_page = virt_to_page((void *)vdso_page); return 0; }
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit 860e1b43da94551cd1e73adc36b3c64cc3e5dc01 ]
There's no need to call ieee80211_recalc_chanctx_min_def() since it cannot and won't call the driver anyway; just use _ieee80211_recalc_chanctx_min_def() instead.
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Gregory Greenman gregory.greenman@intel.com Link: https://lore.kernel.org/r/20230504134511.828474-3-gregory.greenman@intel.com Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/chan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index dbc34fbe7c8f4..d23d1a7b4cc39 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -638,7 +638,7 @@ ieee80211_alloc_chanctx(struct ieee80211_local *local, ctx->conf.rx_chains_dynamic = 1; ctx->mode = mode; ctx->conf.radar_enabled = false; - ieee80211_recalc_chanctx_min_def(local, ctx); + _ieee80211_recalc_chanctx_min_def(local, ctx);
return ctx; }
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit b72a455a2409fd94d6d9b4eb51d659a88213243b ]
When a chanctx is reserved for a new vif and we recalculate the minimal definition for it, we need to consider the new interface it's being reserved for before we assign it, so it can be used directly with the correct min channel width.
Fix the code to - optionally - consider that, and use that option just before doing the reassignment.
Also, when considering channel context reservations, we should only consider the one link we're currently working with. Change the boolean argument to a link pointer to do that.
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Gregory Greenman gregory.greenman@intel.com Link: https://lore.kernel.org/r/20230504134511.828474-4-gregory.greenman@intel.com Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/chan.c | 72 +++++++++++++++++++++++--------------- net/mac80211/ieee80211_i.h | 3 +- net/mac80211/util.c | 2 +- 3 files changed, 47 insertions(+), 30 deletions(-)
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index d23d1a7b4cc39..1b182cf9d6610 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -258,7 +258,8 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata,
static enum nl80211_chan_width ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata, - struct ieee80211_chanctx_conf *conf) + struct ieee80211_chanctx *ctx, + struct ieee80211_link_data *rsvd_for) { enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT; struct ieee80211_vif *vif = &sdata->vif; @@ -267,13 +268,14 @@ ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata, rcu_read_lock(); for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) { enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT; - struct ieee80211_bss_conf *link_conf = - rcu_dereference(sdata->vif.link_conf[link_id]); + struct ieee80211_link_data *link = + rcu_dereference(sdata->link[link_id]);
- if (!link_conf) + if (!link) continue;
- if (rcu_access_pointer(link_conf->chanctx_conf) != conf) + if (link != rsvd_for && + rcu_access_pointer(link->conf->chanctx_conf) != &ctx->conf) continue;
switch (vif->type) { @@ -287,7 +289,7 @@ ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata, * point, so take the width from the chandef, but * account also for TDLS peers */ - width = max(link_conf->chandef.width, + width = max(link->conf->chandef.width, ieee80211_get_max_required_bw(sdata, link_id)); break; case NL80211_IFTYPE_P2P_DEVICE: @@ -296,7 +298,7 @@ ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata, case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_OCB: - width = link_conf->chandef.width; + width = link->conf->chandef.width; break; case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_UNSPECIFIED: @@ -316,7 +318,8 @@ ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata,
static enum nl80211_chan_width ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, - struct ieee80211_chanctx_conf *conf) + struct ieee80211_chanctx *ctx, + struct ieee80211_link_data *rsvd_for) { struct ieee80211_sub_if_data *sdata; enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT; @@ -328,7 +331,8 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, if (!ieee80211_sdata_running(sdata)) continue;
- width = ieee80211_get_chanctx_vif_max_required_bw(sdata, conf); + width = ieee80211_get_chanctx_vif_max_required_bw(sdata, ctx, + rsvd_for);
max_bw = max(max_bw, width); } @@ -336,8 +340,8 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, /* use the configured bandwidth in case of monitor interface */ sdata = rcu_dereference(local->monitor_sdata); if (sdata && - rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == conf) - max_bw = max(max_bw, conf->def.width); + rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &ctx->conf) + max_bw = max(max_bw, ctx->conf.def.width);
rcu_read_unlock();
@@ -349,8 +353,10 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, * the max of min required widths of all the interfaces bound to this * channel context. */ -static u32 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, - struct ieee80211_chanctx *ctx) +static u32 +_ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx, + struct ieee80211_link_data *rsvd_for) { enum nl80211_chan_width max_bw; struct cfg80211_chan_def min_def; @@ -370,7 +376,7 @@ static u32 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, return 0; }
- max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf); + max_bw = ieee80211_get_chanctx_max_required_bw(local, ctx, rsvd_for);
/* downgrade chandef up to max_bw */ min_def = ctx->conf.def; @@ -448,9 +454,10 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local, * channel context. */ void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, - struct ieee80211_chanctx *ctx) + struct ieee80211_chanctx *ctx, + struct ieee80211_link_data *rsvd_for) { - u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx); + u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
if (!changed) return; @@ -464,10 +471,11 @@ void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, ieee80211_chan_bw_change(local, ctx, false); }
-static void ieee80211_change_chanctx(struct ieee80211_local *local, - struct ieee80211_chanctx *ctx, - struct ieee80211_chanctx *old_ctx, - const struct cfg80211_chan_def *chandef) +static void _ieee80211_change_chanctx(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx, + struct ieee80211_chanctx *old_ctx, + const struct cfg80211_chan_def *chandef, + struct ieee80211_link_data *rsvd_for) { u32 changed;
@@ -492,7 +500,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local, ieee80211_chan_bw_change(local, old_ctx, true);
if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) { - ieee80211_recalc_chanctx_min_def(local, ctx); + ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for); return; }
@@ -502,7 +510,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
/* check if min chanctx also changed */ changed = IEEE80211_CHANCTX_CHANGE_WIDTH | - _ieee80211_recalc_chanctx_min_def(local, ctx); + _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for); drv_change_chanctx(local, ctx, changed);
if (!local->use_chanctx) { @@ -514,6 +522,14 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local, ieee80211_chan_bw_change(local, old_ctx, false); }
+static void ieee80211_change_chanctx(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx, + struct ieee80211_chanctx *old_ctx, + const struct cfg80211_chan_def *chandef) +{ + _ieee80211_change_chanctx(local, ctx, old_ctx, chandef, NULL); +} + static struct ieee80211_chanctx * ieee80211_find_chanctx(struct ieee80211_local *local, const struct cfg80211_chan_def *chandef, @@ -638,7 +654,7 @@ ieee80211_alloc_chanctx(struct ieee80211_local *local, ctx->conf.rx_chains_dynamic = 1; ctx->mode = mode; ctx->conf.radar_enabled = false; - _ieee80211_recalc_chanctx_min_def(local, ctx); + _ieee80211_recalc_chanctx_min_def(local, ctx, NULL);
return ctx; } @@ -873,12 +889,12 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, ieee80211_recalc_chanctx_chantype(local, curr_ctx); ieee80211_recalc_smps_chanctx(local, curr_ctx); ieee80211_recalc_radar_chanctx(local, curr_ctx); - ieee80211_recalc_chanctx_min_def(local, curr_ctx); + ieee80211_recalc_chanctx_min_def(local, curr_ctx, NULL); }
if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) { ieee80211_recalc_txpower(sdata, false); - ieee80211_recalc_chanctx_min_def(local, new_ctx); + ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL); }
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && @@ -1270,7 +1286,7 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
ieee80211_link_update_chandef(link, &link->reserved_chandef);
- ieee80211_change_chanctx(local, new_ctx, old_ctx, chandef); + _ieee80211_change_chanctx(local, new_ctx, old_ctx, chandef, link);
vif_chsw[0].vif = &sdata->vif; vif_chsw[0].old_ctx = &old_ctx->conf; @@ -1300,7 +1316,7 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link) if (ieee80211_chanctx_refcount(local, old_ctx) == 0) ieee80211_free_chanctx(local, old_ctx);
- ieee80211_recalc_chanctx_min_def(local, new_ctx); + ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL); ieee80211_recalc_smps_chanctx(local, new_ctx); ieee80211_recalc_radar_chanctx(local, new_ctx);
@@ -1665,7 +1681,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local) ieee80211_recalc_chanctx_chantype(local, ctx); ieee80211_recalc_smps_chanctx(local, ctx); ieee80211_recalc_radar_chanctx(local, ctx); - ieee80211_recalc_chanctx_min_def(local, ctx); + ieee80211_recalc_chanctx_min_def(local, ctx, NULL);
list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links, reserved_chanctx_list) { diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e082582e0aa28..eba7ae63fac45 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2494,7 +2494,8 @@ int ieee80211_chanctx_refcount(struct ieee80211_local *local, void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, struct ieee80211_chanctx *chanctx); void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, - struct ieee80211_chanctx *ctx); + struct ieee80211_chanctx *ctx, + struct ieee80211_link_data *rsvd_for); bool ieee80211_is_radar_required(struct ieee80211_local *local);
void ieee80211_dfs_cac_timer(unsigned long data); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 8c397650b96f6..d7b382866b260 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -3007,7 +3007,7 @@ void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata,
chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); - ieee80211_recalc_chanctx_min_def(local, chanctx); + ieee80211_recalc_chanctx_min_def(local, chanctx, NULL); } unlock: mutex_unlock(&local->chanctx_mtx);
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit 04312de4ced4b152749614e8179f3978a20a992f ]
When we allocate a new channel context, or find an existing one that is compatible, we currently assign it to a link before its mindef is updated. This leads to strange situations, especially in link switching where you switch to an 80 MHz link and expect it to be active immediately, but the mindef is still configured to 20 MHz while assigning. Also, it's strange that the chandef passed to the assign method's argument is wider than the one in the context.
Fix this by calculating the mindef with the new link considered before calling the driver.
In particular, this fixes an iwlwifi problem during link switch where the firmware would assert because the (link) station that was added for the AP is configured to transmit at a bandwidth that's wider than the channel context that it's configured on.
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Gregory Greenman gregory.greenman@intel.com Link: https://lore.kernel.org/r/20230504134511.828474-5-gregory.greenman@intel.com Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/chan.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 1b182cf9d6610..77c90ed8f5d7d 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -871,6 +871,9 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, }
if (new_ctx) { + /* recalc considering the link we'll use it for now */ + ieee80211_recalc_chanctx_min_def(local, new_ctx, link); + ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx); if (ret) goto out;
From: Ariel Malamud ariel.malamud@intel.com
[ Upstream commit a8938bc881d2a03f9b77f19fae924fe798a01285 ]
The rs_drv_get_rate flow reads the lq_sta to return the optimal rate for tx frames. This read flow is not protected thereby leaving a small window, a few instructions wide, open to contention by an asynchronous rate update. Indeed this race condition was hit and the update occurred in the middle of the read.
Fix this by locking the lq_sta struct during read.
Signed-off-by: Ariel Malamud ariel.malamud@intel.com Signed-off-by: Gregory Greenman gregory.greenman@intel.com Link: https://lore.kernel.org/r/20230514120631.b52c9ed5c379.I15290b78e0d966c1b6827... Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 0b50b816684a0..2be6801d48aca 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -2692,6 +2692,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta, return;
lq_sta = mvm_sta; + + spin_lock(&lq_sta->pers.lock); iwl_mvm_hwrate_to_tx_rate_v1(lq_sta->last_rate_n_flags, info->band, &info->control.rates[0]); info->control.rates[0].count = 1; @@ -2706,6 +2708,7 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta, iwl_mvm_hwrate_to_tx_rate_v1(last_ucode_rate, info->band, &txrc->reported_rate); } + spin_unlock(&lq_sta->pers.lock); }
static void *rs_drv_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
From: Po-Wen Kao powen.kao@mediatek.com
[ Upstream commit 5149452ca66289ef33d13897ee845a2f6f5b680f ]
The transfer command descriptor is allocated in ufshcd_memory_alloc() and referenced by the transfer request descriptor with stride size sizeof_utp_transfer_cmd_desc() instead of sizeof(struct utp_transfer_cmd_desc).
Consequently, computing tag by address offset should also refer to the same stride.
Signed-off-by: Po-Wen Kao powen.kao@mediatek.com Link: https://lore.kernel.org/r/20230504154454.26654-2-powen.kao@mediatek.com Reviewed-by: Bart Van Assche bvanassche@acm.org Reviewed-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Stanley Chu stanley.chu@mediatek.com Reviewed-by: Ziqi Chen quic_ziqichen@quicinc.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ufs/core/ufs-mcq.c | 2 +- drivers/ufs/core/ufshcd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index 202ff71e1b582..b7c5f39b50e6d 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -265,7 +265,7 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba, addr = (le64_to_cpu(cqe->command_desc_base_addr) & CQE_UCD_BA) - hba->ucdl_dma_addr;
- return div_u64(addr, sizeof(struct utp_transfer_cmd_desc)); + return div_u64(addr, sizeof_utp_transfer_cmd_desc(hba)); }
static void ufshcd_mcq_process_cqe(struct ufs_hba *hba, diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 70b112038792a..c7a9a1cedf920 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -8422,7 +8422,7 @@ static void ufshcd_release_sdb_queue(struct ufs_hba *hba, int nutrs) { size_t ucdl_size, utrdl_size;
- ucdl_size = sizeof(struct utp_transfer_cmd_desc) * nutrs; + ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * nutrs; dmam_free_coherent(hba->dev, ucdl_size, hba->ucdl_base_addr, hba->ucdl_dma_addr);
From: Po-Wen Kao powen.kao@mediatek.com
[ Upstream commit 06caeb536b2b21668efd2d6fa97c09461957b3a7 ]
Naming the functions after standard operators like sizeof() may cause confusion. Rename it to ufshcd_get_ucd_size().
Signed-off-by: Po-Wen Kao powen.kao@mediatek.com Link: https://lore.kernel.org/r/20230504154454.26654-3-powen.kao@mediatek.com Suggested-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Stanley Chu stanley.chu@mediatek.com Reviewed-by: Ziqi Chen quic_ziqichen@quicinc.com Reviewed-by: Bart Van Assche bvanassche@acm.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ufs/core/ufs-mcq.c | 2 +- drivers/ufs/core/ufshcd.c | 10 +++++----- include/ufs/ufshcd.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index b7c5f39b50e6d..937933d3f77c2 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -265,7 +265,7 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba, addr = (le64_to_cpu(cqe->command_desc_base_addr) & CQE_UCD_BA) - hba->ucdl_dma_addr;
- return div_u64(addr, sizeof_utp_transfer_cmd_desc(hba)); + return div_u64(addr, ufshcd_get_ucd_size(hba)); }
static void ufshcd_mcq_process_cqe(struct ufs_hba *hba, diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index c7a9a1cedf920..b95b5afd7eaeb 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -2821,10 +2821,10 @@ static void ufshcd_map_queues(struct Scsi_Host *shost) static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i) { struct utp_transfer_cmd_desc *cmd_descp = (void *)hba->ucdl_base_addr + - i * sizeof_utp_transfer_cmd_desc(hba); + i * ufshcd_get_ucd_size(hba); struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr; dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr + - i * sizeof_utp_transfer_cmd_desc(hba); + i * ufshcd_get_ucd_size(hba); u16 response_offset = offsetof(struct utp_transfer_cmd_desc, response_upiu); u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table); @@ -3733,7 +3733,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) size_t utmrdl_size, utrdl_size, ucdl_size;
/* Allocate memory for UTP command descriptors */ - ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * hba->nutrs; + ucdl_size = ufshcd_get_ucd_size(hba) * hba->nutrs; hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev, ucdl_size, &hba->ucdl_dma_addr, @@ -3833,7 +3833,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table);
- cmd_desc_size = sizeof_utp_transfer_cmd_desc(hba); + cmd_desc_size = ufshcd_get_ucd_size(hba); cmd_desc_dma_addr = hba->ucdl_dma_addr;
for (i = 0; i < hba->nutrs; i++) { @@ -8422,7 +8422,7 @@ static void ufshcd_release_sdb_queue(struct ufs_hba *hba, int nutrs) { size_t ucdl_size, utrdl_size;
- ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * nutrs; + ucdl_size = ufshcd_get_ucd_size(hba) * nutrs; dmam_free_coherent(hba->dev, ucdl_size, hba->ucdl_base_addr, hba->ucdl_dma_addr);
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 431c3afb2ce0f..db70944c681aa 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1138,7 +1138,7 @@ static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba) ({ (void)(hba); BUILD_BUG_ON(sg_entry_size != sizeof(struct ufshcd_sg_entry)); }) #endif
-static inline size_t sizeof_utp_transfer_cmd_desc(const struct ufs_hba *hba) +static inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba) { return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba); }
From: Po-Wen Kao powen.kao@mediatek.com
[ Upstream commit 72a81bb0b6fc9b759ac0fdaca3ec5884a8b2f304 ]
Since MAXQ is 0-based value, add one to obtain number of hardware queues.
Signed-off-by: Po-Wen Kao powen.kao@mediatek.com Link: https://lore.kernel.org/r/20230504154454.26654-4-powen.kao@mediatek.com Reviewed-by: Bean Huo beanhuo@micron.com Reviewed-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Bart Van Assche bvanassche@acm.org Reviewed-by: Stanley Chu stanley.chu@mediatek.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ufs/core/ufs-mcq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index 937933d3f77c2..51b3c6ae781df 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -150,7 +150,8 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) u32 hba_maxq, rem, tot_queues; struct Scsi_Host *host = hba->host;
- hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities); + /* maxq is 0 based value */ + hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1;
tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues + rw_queues;
From: Wenchao Hao haowenchao2@huawei.com
[ Upstream commit 6ca9818d1624e136a76ae8faedb6b6c95ca66903 ]
The "atomic_inc(&cmd->device->iorequest_cnt)" in scsi_queue_rq() would cause kernel panic because cmd->device may be freed after returning from scsi_dispatch_cmd().
This reverts commit cfee29ffb45b1c9798011b19d454637d1b0fe87d.
Signed-off-by: Wenchao Hao haowenchao2@huawei.com Reported-by: Ming Lei ming.lei@redhat.com Closes: https://lore.kernel.org/r/ZF+zB+bB7iqe0wGd@ovpn-8-17.pek2.redhat.com Link: https://lore.kernel.org/r/20230515070156.1790181-2-haowenchao2@huawei.com Reviewed-by: Ming Lei ming.lei@redhat.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/scsi_lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b7c569a42aa47..03964b26f3f27 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1463,6 +1463,8 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd) struct Scsi_Host *host = cmd->device->host; int rtn = 0;
+ atomic_inc(&cmd->device->iorequest_cnt); + /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { /* in SDEV_DEL we error all commands. DID_NO_CONNECT @@ -1761,7 +1763,6 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, goto out_dec_host_busy; }
- atomic_inc(&cmd->device->iorequest_cnt); return BLK_STS_OK;
out_dec_host_busy:
From: Wenchao Hao haowenchao2@huawei.com
[ Upstream commit 09e797c8641f6ad435c33ae24c223351197ea29a ]
If scsi_dispatch_cmd() failed, the SCSI command was not sent to the target, scsi_queue_rq() would return BLK_STS_RESOURCE and the related request would be requeued. The timeout of this request would not fire, no one would increase iodone_cnt.
The above flow would result the iodone_cnt smaller than iorequest_cnt. So decrease the iorequest_cnt if dispatch failed to workaround the issue.
Signed-off-by: Wenchao Hao haowenchao2@huawei.com Reported-by: Ming Lei ming.lei@redhat.com Closes: https://lore.kernel.org/r/ZF+zB+bB7iqe0wGd@ovpn-8-17.pek2.redhat.com Link: https://lore.kernel.org/r/20230515070156.1790181-3-haowenchao2@huawei.com Reviewed-by: Ming Lei ming.lei@redhat.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/scsi_lib.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 03964b26f3f27..0226c9279cef6 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1485,6 +1485,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd) */ SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, "queuecommand : device blocked\n")); + atomic_dec(&cmd->device->iorequest_cnt); return SCSI_MLQUEUE_DEVICE_BUSY; }
@@ -1517,6 +1518,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd) trace_scsi_dispatch_cmd_start(cmd); rtn = host->hostt->queuecommand(host, cmd); if (rtn) { + atomic_dec(&cmd->device->iorequest_cnt); trace_scsi_dispatch_cmd_error(cmd, rtn); if (rtn != SCSI_MLQUEUE_DEVICE_BUSY && rtn != SCSI_MLQUEUE_TARGET_BUSY)
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 212457ccbd60dba34f965e4ffbe62f0e4f970538 ]
clang warns about an unpacked structure inside of a packed one:
drivers/net/wireless/broadcom/b43/b43.h:654:4: error: field data within 'struct b43_iv' is less aligned than 'union (unnamed union at /home/arnd/arm-soc/drivers/net/wireless/broadcom/b43/b43.h:651:2)' and is usually due to 'struct b43_iv' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access]
The problem here is that the anonymous union has the default alignment from its members, apparently because the original author mixed up the placement of the __packed attribute by placing it next to the struct member rather than the union definition. As the struct itself is also marked as __packed, there is no need to mark its members, so just move the annotation to the inner type instead.
As Michael noted, the same problem is present in b43legacy, so change both at the same time.
Acked-by: Michael Büsch m@bues.ch Reported-by: kernel test robot lkp@intel.com Reviewed-by: Simon Horman simon.horman@corigine.com Tested-by: Larry Finger Larry.Finger@lwfinger.net Link: https://lore.kernel.org/oe-kbuild-all/202305160749.ay1HAoyP-lkp@intel.com/ Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Kalle Valo kvalo@kernel.org Link: https://lore.kernel.org/r/20230516183442.536589-1-arnd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/broadcom/b43/b43.h | 2 +- drivers/net/wireless/broadcom/b43legacy/b43legacy.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/broadcom/b43/b43.h b/drivers/net/wireless/broadcom/b43/b43.h index 9fc7c088a539e..67b4bac048e58 100644 --- a/drivers/net/wireless/broadcom/b43/b43.h +++ b/drivers/net/wireless/broadcom/b43/b43.h @@ -651,7 +651,7 @@ struct b43_iv { union { __be16 d16; __be32 d32; - } data __packed; + } __packed data; } __packed;
diff --git a/drivers/net/wireless/broadcom/b43legacy/b43legacy.h b/drivers/net/wireless/broadcom/b43legacy/b43legacy.h index 6b0cec467938f..f49365d14619f 100644 --- a/drivers/net/wireless/broadcom/b43legacy/b43legacy.h +++ b/drivers/net/wireless/broadcom/b43legacy/b43legacy.h @@ -379,7 +379,7 @@ struct b43legacy_iv { union { __be16 d16; __be32 d32; - } data __packed; + } __packed data; } __packed;
#define B43legacy_PHYMODE(phytype) (1 << (phytype))
From: Kai-Heng Feng kai.heng.feng@canonical.com
[ Upstream commit ab87603b251134441a67385ecc9d3371be17b7a7 ]
When the system attempts to sleep while mtk_t7xx is not ready, the driver cannot put the device to sleep: [ 12.472918] mtk_t7xx 0000:57:00.0: [PM] Exiting suspend, modem in invalid state [ 12.472936] mtk_t7xx 0000:57:00.0: PM: pci_pm_suspend(): t7xx_pci_pm_suspend+0x0/0x20 [mtk_t7xx] returns -14 [ 12.473678] mtk_t7xx 0000:57:00.0: PM: dpm_run_callback(): pci_pm_suspend+0x0/0x1b0 returns -14 [ 12.473711] mtk_t7xx 0000:57:00.0: PM: failed to suspend async: error -14 [ 12.764776] PM: Some devices failed to suspend, or early wake event detected
Mediatek confirmed the device can take a rather long time to complete its initialization, so wait for up to 20 seconds until init is done.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wwan/t7xx/t7xx_pci.c | 18 ++++++++++++++++++ drivers/net/wwan/t7xx/t7xx_pci.h | 1 + 2 files changed, 19 insertions(+)
diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c index 226fc1703e90f..91256e005b846 100644 --- a/drivers/net/wwan/t7xx/t7xx_pci.c +++ b/drivers/net/wwan/t7xx/t7xx_pci.c @@ -45,6 +45,7 @@ #define T7XX_PCI_IREG_BASE 0 #define T7XX_PCI_EREG_BASE 2
+#define T7XX_INIT_TIMEOUT 20 #define PM_SLEEP_DIS_TIMEOUT_MS 20 #define PM_ACK_TIMEOUT_MS 1500 #define PM_AUTOSUSPEND_MS 20000 @@ -96,6 +97,7 @@ static int t7xx_pci_pm_init(struct t7xx_pci_dev *t7xx_dev) spin_lock_init(&t7xx_dev->md_pm_lock); init_completion(&t7xx_dev->sleep_lock_acquire); init_completion(&t7xx_dev->pm_sr_ack); + init_completion(&t7xx_dev->init_done); atomic_set(&t7xx_dev->md_pm_state, MTK_PM_INIT);
device_init_wakeup(&pdev->dev, true); @@ -124,6 +126,7 @@ void t7xx_pci_pm_init_late(struct t7xx_pci_dev *t7xx_dev) pm_runtime_mark_last_busy(&t7xx_dev->pdev->dev); pm_runtime_allow(&t7xx_dev->pdev->dev); pm_runtime_put_noidle(&t7xx_dev->pdev->dev); + complete_all(&t7xx_dev->init_done); }
static int t7xx_pci_pm_reinit(struct t7xx_pci_dev *t7xx_dev) @@ -529,6 +532,20 @@ static void t7xx_pci_shutdown(struct pci_dev *pdev) __t7xx_pci_pm_suspend(pdev); }
+static int t7xx_pci_pm_prepare(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct t7xx_pci_dev *t7xx_dev; + + t7xx_dev = pci_get_drvdata(pdev); + if (!wait_for_completion_timeout(&t7xx_dev->init_done, T7XX_INIT_TIMEOUT * HZ)) { + dev_warn(dev, "Not ready for system sleep.\n"); + return -ETIMEDOUT; + } + + return 0; +} + static int t7xx_pci_pm_suspend(struct device *dev) { return __t7xx_pci_pm_suspend(to_pci_dev(dev)); @@ -555,6 +572,7 @@ static int t7xx_pci_pm_runtime_resume(struct device *dev) }
static const struct dev_pm_ops t7xx_pci_pm_ops = { + .prepare = t7xx_pci_pm_prepare, .suspend = t7xx_pci_pm_suspend, .resume = t7xx_pci_pm_resume, .resume_noirq = t7xx_pci_pm_resume_noirq, diff --git a/drivers/net/wwan/t7xx/t7xx_pci.h b/drivers/net/wwan/t7xx/t7xx_pci.h index 112efa534eace..f08f1ab744691 100644 --- a/drivers/net/wwan/t7xx/t7xx_pci.h +++ b/drivers/net/wwan/t7xx/t7xx_pci.h @@ -69,6 +69,7 @@ struct t7xx_pci_dev { struct t7xx_modem *md; struct t7xx_ccmni_ctrl *ccmni_ctlb; bool rgu_pci_irq_en; + struct completion init_done;
/* Low Power Items */ struct list_head md_pm_entities;
From: Tom Rix trix@redhat.com
[ Upstream commit 224a876e37543eee111bf9b6aa4935080e619335 ]
gcc with W=1 and ! CONFIG_NF_NAT net/netfilter/nf_conntrack_netlink.c:3463:32: error: ‘exp_nat_nla_policy’ defined but not used [-Werror=unused-const-variable=] 3463 | static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { | ^~~~~~~~~~~~~~~~~~ net/netfilter/nf_conntrack_netlink.c:2979:33: error: ‘any_addr’ defined but not used [-Werror=unused-const-variable=] 2979 | static const union nf_inet_addr any_addr; | ^~~~~~~~
These variables use is controlled by CONFIG_NF_NAT, so should their definitions.
Signed-off-by: Tom Rix trix@redhat.com Reviewed-by: Simon Horman simon.horman@corigine.com Signed-off-by: Florian Westphal fw@strlen.de Signed-off-by: Sasha Levin sashal@kernel.org --- net/netfilter/nf_conntrack_netlink.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 6f3b23a6653cc..7217a89f067cb 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -2984,7 +2984,9 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb, return -1; }
+#if IS_ENABLED(CONFIG_NF_NAT) static const union nf_inet_addr any_addr; +#endif
static __be32 nf_expect_get_id(const struct nf_conntrack_expect *exp) { @@ -3468,10 +3470,12 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, return 0; }
+#if IS_ENABLED(CONFIG_NF_NAT) static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 }, [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, }; +#endif
static int ctnetlink_parse_expect_nat(const struct nlattr *attr,
From: Christoph Hellwig hch@lst.de
[ Upstream commit 1743e5f6000901a11f4e1cd741bfa9136f3ec9b1 ]
nvme_mpath_remove_disk is called after del_gendisk, at which point a blk_mark_disk_dead call doesn't make any sense.
Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Keith Busch kbusch@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/multipath.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 9171452e2f6d4..2bc159a318ff0 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -884,7 +884,6 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head) { if (!head->disk) return; - blk_mark_disk_dead(head->disk); /* make sure all pending bios are cleaned up */ kblockd_schedule_work(&head->requeue_work); flush_work(&head->requeue_work);
From: Maurizio Lombardi mlombard@redhat.com
[ Upstream commit 2eb94dd56a4a4e3fe286def3e2ba207804a37345 ]
If a userspace application performes a "delete_controller" command early during the ctrl initialization, the delete operation may race against the init code and the kernel will crash.
nvme nvme5: Connect command failed: host path error nvme nvme5: failed to connect queue: 0 ret=880 PF: supervisor write access in kernel mode PF: error_code(0x0002) - not-present page blk_mq_quiesce_queue+0x18/0x90 nvme_tcp_delete_ctrl+0x24/0x40 [nvme_tcp] nvme_do_delete_ctrl+0x7f/0x8b [nvme_core] nvme_sysfs_delete.cold+0x8/0xd [nvme_core] kernfs_fop_write_iter+0x124/0x1b0 new_sync_write+0xff/0x190 vfs_write+0x1ef/0x280
Fix the crash by checking the NVME_CTRL_STARTED_ONCE bit; if it's not set it means that the nvme controller is still in the process of getting initialized and the kernel will return an -EBUSY error to userspace. Set the NVME_CTRL_STARTED_ONCE later in the nvme_start_ctrl() function, after the controller start operation is completed.
Signed-off-by: Maurizio Lombardi mlombard@redhat.com Reviewed-by: Sagi Grimberg sagi@grimberg.me Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Keith Busch kbusch@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index bdf1601219fc4..c015393beeee8 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3585,6 +3585,9 @@ static ssize_t nvme_sysfs_delete(struct device *dev, { struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags)) + return -EBUSY; + if (device_remove_file_self(dev, attr)) nvme_delete_ctrl_sync(ctrl); return count; @@ -5045,7 +5048,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl) * that were missed. We identify persistent discovery controllers by * checking that they started once before, hence are reconnecting back. */ - if (test_and_set_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags) && + if (test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags) && nvme_discovery_ctrl(ctrl)) nvme_change_uevent(ctrl, "NVME_EVENT=rediscover");
@@ -5056,6 +5059,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl) }
nvme_change_uevent(ctrl, "NVME_EVENT=connected"); + set_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags); } EXPORT_SYMBOL_GPL(nvme_start_ctrl);
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 040b5a046a9e18098580d3ccd029e2318fca7859 ]
Two functions are defined and used in pcm_oss.c but also optionally used from io.c, with an optional prototype. If CONFIG_SND_PCM_OSS_PLUGINS is disabled, this causes a warning as the functions are not static and have no prototype:
sound/core/oss/pcm_oss.c:1235:19: error: no previous prototype for 'snd_pcm_oss_write3' [-Werror=missing-prototypes] sound/core/oss/pcm_oss.c:1266:19: error: no previous prototype for 'snd_pcm_oss_read3' [-Werror=missing-prototypes]
Avoid this by making the prototypes unconditional.
Signed-off-by: Arnd Bergmann arnd@arndb.de Link: https://lore.kernel.org/r/20230516195046.550584-2-arnd@kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/core/oss/pcm_plugin.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index 46e273bd4a786..50a6b50f5db4c 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h @@ -141,6 +141,14 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size); void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr); +#else + +static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } +static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; } +static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; } + +#endif + snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t size, int in_kernel); @@ -151,14 +159,6 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames);
-#else - -static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } -static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; } -static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; } - -#endif - #ifdef PLUGIN_DEBUG #define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args) #else
From: Rob Clark robdclark@chromium.org
[ Upstream commit 5c054db54c43a5fcb5cc81012361f5e3fac37637 ]
Otherwise it is not always obvious if a dt or iommu change is causing us to fall back to global pgtable.
Signed-off-by: Rob Clark robdclark@chromium.org Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Patchwork: https://patchwork.freedesktop.org/patch/537359/ Link: https://lore.kernel.org/r/20230516222039.907690-2-robdclark@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/msm_iommu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index c2507582ecf34..0d6a69cd6f7a5 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -234,7 +234,12 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) /* Get the pagetable configuration from the domain */ if (adreno_smmu->cookie) ttbr1_cfg = adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie); - if (!ttbr1_cfg) + + /* + * If you hit this WARN_ONCE() you are probably missing an entry in + * qcom_smmu_impl_of_match[] in arm-smmu-qcom.c + */ + if (WARN_ONCE(!ttbr1_cfg, "No per-process page tables")) return ERR_PTR(-ENODEV);
/*
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit fb1b7be9b16c1f4626969ba4e95a97da2a452b41 ]
When CONFIG_PROC_FS is disabled, the function declarations for some procfs functions are hidden, but the definitions are still build, as shown by this compiler warning:
net/atm/resources.c:403:7: error: no previous prototype for 'atm_dev_seq_start' [-Werror=missing-prototypes] net/atm/resources.c:409:6: error: no previous prototype for 'atm_dev_seq_stop' [-Werror=missing-prototypes] net/atm/resources.c:414:7: error: no previous prototype for 'atm_dev_seq_next' [-Werror=missing-prototypes]
Add another #ifdef to leave these out of the build.
Signed-off-by: Arnd Bergmann arnd@arndb.de Link: https://lore.kernel.org/r/20230516194625.549249-2-arnd@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/atm/resources.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/net/atm/resources.c b/net/atm/resources.c index 2b2d33eeaf200..995d29e7fb138 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -400,6 +400,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, return error; }
+#ifdef CONFIG_PROC_FS void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) { mutex_lock(&atm_dev_mutex); @@ -415,3 +416,4 @@ void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) { return seq_list_next(v, &atm_devs, pos); } +#endif
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 2e9f8ab68f42b059e80db71266c1675c07c664bd ]
mdio_bus_init() is either used as a local module_init() entry, or it gets called in phy_device.c. In the former case, there is no declaration, which causes a warning:
drivers/net/phy/mdio_bus.c:1371:12: error: no previous prototype for 'mdio_bus_init' [-Werror=missing-prototypes]
Remove the #ifdef around the declaration to avoid the warning..
Signed-off-by: Arnd Bergmann arnd@arndb.de Link: https://lore.kernel.org/r/20230516194625.549249-4-arnd@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/phy.h | 2 -- 1 file changed, 2 deletions(-)
diff --git a/include/linux/phy.h b/include/linux/phy.h index db7c0bd67559d..2874b9ed31f2e 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1860,10 +1860,8 @@ void phy_package_leave(struct phy_device *phydev); int devm_phy_package_join(struct device *dev, struct phy_device *phydev, int addr, size_t priv_size);
-#if IS_ENABLED(CONFIG_PHYLIB) int __init mdio_bus_init(void); void mdio_bus_exit(void); -#endif
int phy_ethtool_get_strings(struct phy_device *phydev, u8 *data); int phy_ethtool_get_sset_count(struct phy_device *phydev);
From: Xiubo Li xiubli@redhat.com
[ Upstream commit 9aaa7eb018661b2da221362d9bacb096bd596f52 ]
Smatch static checker warning:
fs/ceph/mds_client.c:3968 reconnect_caps_cb() warn: missing error code here? '__get_cap_for_mds()' failed. 'err' = '0'
[ idryomov: Dan says that Smatch considers it intentional only if the "ret = 0;" assignment is within 4 or 5 lines of the goto. ]
Reported-by: Dan Carpenter dan.carpenter@linaro.org Signed-off-by: Xiubo Li xiubli@redhat.com Reviewed-by: Ilya Dryomov idryomov@gmail.com Signed-off-by: Ilya Dryomov idryomov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ceph/mds_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 54e3c2ab21d22..1989c8deea55a 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -3938,7 +3938,7 @@ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg) struct dentry *dentry; struct ceph_cap *cap; char *path; - int pathlen = 0, err = 0; + int pathlen = 0, err; u64 pathbase; u64 snap_follows;
@@ -3961,6 +3961,7 @@ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg) cap = __get_cap_for_mds(ci, mds); if (!cap) { spin_unlock(&ci->i_ceph_lock); + err = 0; goto out_err; } dout(" adding %p ino %llx.%llx cap %p %lld %s\n",
From: Guchun Chen guchun.chen@amd.com
[ Upstream commit c1a322a7a4a96cd0a3dde32ce37af437a78bf8cd ]
When performing device unbind or halt, we have disabled all irqs at the very begining like amdgpu_pci_remove or amdgpu_device_halt. So amdgpu_irq_put for irqs stored in fence driver should not be called any more, otherwise, below calltrace will arrive.
[ 139.114088] WARNING: CPU: 2 PID: 1550 at drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:616 amdgpu_irq_put+0xf6/0x110 [amdgpu] [ 139.114655] Call Trace: [ 139.114655] <TASK> [ 139.114657] amdgpu_fence_driver_hw_fini+0x93/0x130 [amdgpu] [ 139.114836] amdgpu_device_fini_hw+0xb6/0x350 [amdgpu] [ 139.114955] amdgpu_driver_unload_kms+0x51/0x70 [amdgpu] [ 139.115075] amdgpu_pci_remove+0x63/0x160 [amdgpu] [ 139.115193] ? __pm_runtime_resume+0x64/0x90 [ 139.115195] pci_device_remove+0x3a/0xb0 [ 139.115197] device_remove+0x43/0x70 [ 139.115198] device_release_driver_internal+0xbd/0x140
Signed-off-by: Guchun Chen guchun.chen@amd.com Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index f52d0ba91a770..a7d250809da99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -582,7 +582,8 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev) if (r) amdgpu_fence_driver_force_completion(ring);
- if (ring->fence_drv.irq_src) + if (!drm_dev_is_unplugged(adev_to_drm(adev)) && + ring->fence_drv.irq_src) amdgpu_irq_put(adev, ring->fence_drv.irq_src, ring->fence_drv.irq_type);
From: Ming Lei ming.lei@redhat.com
[ Upstream commit ac5902f84bb546c64aea02c439c2579cbf40318f ]
When handling UBLK_IO_FETCH_REQ, ctx->uring_lock is grabbed first, then ub->mutex is acquired.
When handling UBLK_CMD_STOP_DEV or UBLK_CMD_DEL_DEV, ub->mutex is grabbed first, then calling io_uring_cmd_done() for canceling uring command, in which ctx->uring_lock may be required.
Real deadlock only happens when all the above commands are issued from same uring context, and in reality different uring contexts are often used for handing control command and IO command.
Fix the issue by using io_uring_cmd_complete_in_task() to cancel command in ublk_cancel_dev(ublk_cancel_queue).
Reported-by: Shinichiro Kawasaki shinichiro.kawasaki@wdc.com Closes: https://lore.kernel.org/linux-block/becol2g7sawl4rsjq2dztsbc7mqypfqko6wzsyoy... Cc: Ziyang Zhang ZiyangZhang@linux.alibaba.com Signed-off-by: Ming Lei ming.lei@redhat.com Tested-by: Shinichiro Kawasaki shinichiro.kawasaki@wdc.com Link: https://lore.kernel.org/r/20230517133408.210944-1-ming.lei@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/block/ublk_drv.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 41c35ab2c25a1..4db5f1bcac44a 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -1122,6 +1122,11 @@ static inline bool ublk_queue_ready(struct ublk_queue *ubq) return ubq->nr_io_ready == ubq->q_depth; }
+static void ublk_cmd_cancel_cb(struct io_uring_cmd *cmd, unsigned issue_flags) +{ + io_uring_cmd_done(cmd, UBLK_IO_RES_ABORT, 0, issue_flags); +} + static void ublk_cancel_queue(struct ublk_queue *ubq) { int i; @@ -1133,8 +1138,8 @@ static void ublk_cancel_queue(struct ublk_queue *ubq) struct ublk_io *io = &ubq->ios[i];
if (io->flags & UBLK_IO_FLAG_ACTIVE) - io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, 0, - IO_URING_F_UNLOCKED); + io_uring_cmd_complete_in_task(io->cmd, + ublk_cmd_cancel_cb); }
/* all io commands are canceled */
From: Daniel Smith dansmith@ds.gy
[ Upstream commit 0649728123cf6a5518e154b4e1735fc85ea4f55c ]
Add a quirk for Teamgroup MP33 that reports duplicate ids for disk.
Signed-off-by: Daniel Smith dansmith@ds.gy [kch: patch formatting] Signed-off-by: Chaitanya Kulkarni kch@nvidia.com Tested-by: Daniel Smith dansmith@ds.gy Signed-off-by: Keith Busch kbusch@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/pci.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index a389f1ea0b151..60f51155a6d20 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3449,6 +3449,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1e4b, 0x1602), /* HS-SSD-FUTURE 2048G */ .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x10ec, 0x5765), /* TEAMGROUP MP33 2TB SSD */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061), .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0065),
From: Loic Poulain loic.poulain@linaro.org
[ Upstream commit 69baa3a623fd2e58624f24f2f23d46f87b817c93 ]
User should not be able to write block device if it is read-only at block level (e.g force_ro attribute). This is ensured in the regular fops write operation (blkdev_write_iter) but not when writing via user mapping (mmap), allowing user to actually write a read-only block device via a PROT_WRITE mapping.
Example: This can lead to integrity issue of eMMC boot partition (e.g mmcblk0boot0) which is read-only by default.
To fix this issue, simply deny shared writable mapping if the block is readonly.
Note: Block remains writable if switch to read-only is performed after the initial mapping, but this is expected behavior according to commit a32e236eb93e ("Partially revert "block: fail op_is_write() requests to read-only partitions"")'.
Signed-off-by: Loic Poulain loic.poulain@linaro.org Reviewed-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20230510074223.991297-1-loic.poulain@linaro.org Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/fops.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/block/fops.c b/block/fops.c index d2e6be4e3d1c7..58d0aebc7313a 100644 --- a/block/fops.c +++ b/block/fops.c @@ -678,6 +678,16 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start, return error; }
+static int blkdev_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct inode *bd_inode = bdev_file_inode(file); + + if (bdev_read_only(I_BDEV(bd_inode))) + return generic_file_readonly_mmap(file, vma); + + return generic_file_mmap(file, vma); +} + const struct file_operations def_blk_fops = { .open = blkdev_open, .release = blkdev_close, @@ -685,7 +695,7 @@ const struct file_operations def_blk_fops = { .read_iter = blkdev_read_iter, .write_iter = blkdev_write_iter, .iopoll = iocb_bio_iopoll, - .mmap = generic_file_mmap, + .mmap = blkdev_mmap, .fsync = blkdev_fsync, .unlocked_ioctl = blkdev_ioctl, #ifdef CONFIG_COMPAT
Hi Sasha,
This feedback is on the whole 67-patch series. I'm replying to patch 1 because this series lacks a cover letter. Please include a cover letter next time.
This series doesn't apply because the following error happens on patch 35:
Applying: tipc: add tipc_bearer_min_mtu to calculate min mtu error: patch failed: net/tipc/bearer.h:146 error: net/tipc/bearer.h: patch does not apply error: patch failed: net/tipc/udp_media.c:738 error: net/tipc/udp_media.c: patch does not apply Patch failed at 0035 tipc: add tipc_bearer_min_mtu to calculate min mtu
For the base commit I tried the latest linux-6.3.y, both with and without the latest queue-6.3 applied.
As with any kernel patch series, please make it clear what the base commit is. Otherwise the series is unreviewable and untestable.
- Eric
On Thu, May 25, 2023 at 07:02:01PM +0000, Eric Biggers wrote:
Hi Sasha,
This feedback is on the whole 67-patch series. I'm replying to patch 1 because this series lacks a cover letter. Please include a cover letter next time.
This series doesn't apply because the following error happens on patch 35:
Applying: tipc: add tipc_bearer_min_mtu to calculate min mtu error: patch failed: net/tipc/bearer.h:146 error: net/tipc/bearer.h: patch does not apply error: patch failed: net/tipc/udp_media.c:738 error: net/tipc/udp_media.c: patch does not apply Patch failed at 0035 tipc: add tipc_bearer_min_mtu to calculate min mtu
For the base commit I tried the latest linux-6.3.y, both with and without the latest queue-6.3 applied.
Yup, it was based on the prior release, and the conflict you see here is because the patch in question was brought in to the stable tree via a different route.
As with any kernel patch series, please make it clear what the base commit is. Otherwise the series is unreviewable and untestable.
Ack, I can add annotation of the base. In general - if an AUTOSEL patch fails to apply/build when brought to a newer release, it'll simply get dropped.
linux-stable-mirror@lists.linaro.org